Compare commits
48 Commits
Author | SHA1 | Date |
---|---|---|
simonkellet | 54d9f06a9e | 2 years ago |
simonkellet | d1a97c0d8f | 2 years ago |
simonkellet | 693d933c19 | 2 years ago |
simonkellet | c9ca3c5bba | 2 years ago |
Sandy Brownlee | ce307a11a6 | 2 years ago |
Sandy Brownlee | 55fdd944fa | 2 years ago |
Sandy Brownlee | 7a8fb2564c | 2 years ago |
Sandy Brownlee | 6a30c4db8b | 2 years ago |
simonkellet | e1268aae42 | 2 years ago |
Sandy Brownlee | 461749e44a | 2 years ago |
simonkellet | 4341d02572 | 2 years ago |
simonkellet | 32bd99d78b | 2 years ago |
simonkellet | fab24be627 | 2 years ago |
simonkellet | 6b7fdd3bb0 | 2 years ago |
simonkellet | f69942533f | 2 years ago |
Sandy Brownlee | 0c1b2530fa | 2 years ago |
Sandy Brownlee | f5951671b9 | 2 years ago |
Sandy Brownlee | 1da8cabdf7 | 2 years ago |
simonkellet | a647259dc2 | 2 years ago |
simonkellet | befe8f93a2 | 2 years ago |
simonkellet | 7c64cb7eff | 2 years ago |
simonkellet | a4c304f58d | 2 years ago |
simonkellet | 36f3fac111 | 2 years ago |
simonkellet | cd280e3c4b | 2 years ago |
simonkellet | d28b3c7403 | 2 years ago |
simonkellet | 3f58bdfad9 | 2 years ago |
simonkellet | 6377dd8250 | 2 years ago |
simonkellet | 955517af29 | 2 years ago |
Sandy Brownlee | 3dade998ba | 2 years ago |
Sandy Brownlee | 048cbac0b4 | 2 years ago |
Sandy Brownlee | 77846e5800 | 2 years ago |
Sandy Brownlee | f4e1a08f61 | 2 years ago |
Sandy Brownlee | c3c2076d9e | 2 years ago |
Sandy Brownlee | 64c25f1486 | 2 years ago |
Sandy Brownlee | c469297712 | 2 years ago |
Sandy Brownlee | a2cac87f81 | 2 years ago |
Sandy Brownlee | b3375e2050 | 2 years ago |
Sandy Brownlee | 11be265081 | 2 years ago |
Sandy Brownlee | 6820b55cf1 | 2 years ago |
Sandy Brownlee | f709234c4e | 2 years ago |
Sandy Brownlee | 07b0d85bdf | 2 years ago |
Sandy Brownlee | e8780a5b11 | 2 years ago |
Sandy Brownlee | 90977fb64f | 2 years ago |
Sandy Brownlee | 3150ae8fa9 | 2 years ago |
Sandy Brownlee | a026ec3840 | 2 years ago |
Sandy Brownlee | 3de9d5e0cc | 2 years ago |
Sandy Brownlee | ee57c9f711 | 2 years ago |
Sandy Brownlee | 01f468f07d | 2 years ago |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<classpath> |
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/> |
||||
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/> |
||||
<classpathentry kind="output" path="bin/default"/> |
||||
</classpath> |
@ -1,4 +1,4 @@ |
||||
apply plugin: 'java-library' |
||||
apply plugin: 'eclipse' |
||||
|
||||
sourceCompatibility = 17 |
||||
sourceCompatibility = 11 |
@ -1,5 +1,5 @@ |
||||
package triangle.abstractMachine; |
||||
|
||||
public enum OpCode { |
||||
LOAD, LOADA, LOADI, LOADL, STORE, STOREI, CALL, CALLI, RETURN, PUSH, POP, JUMP, JUMPI, JUMPIF, HALT |
||||
LOAD, LOADA, LOADI, LOADL, STORE, STOREI, CALL, CALLI, RETURN, NOP, PUSH, POP, JUMP, JUMPI, JUMPIF, HALT |
||||
} |
||||
|
@ -1,12 +1,21 @@ |
||||
apply plugin: 'java' |
||||
apply plugin: 'application' |
||||
|
||||
sourceCompatibility = 17 |
||||
sourceCompatibility = 11 |
||||
|
||||
repositories { |
||||
mavenCentral() |
||||
} |
||||
|
||||
|
||||
dependencies { |
||||
implementation project(':Triangle.AbstractMachine') |
||||
testImplementation group: 'junit', name: 'junit', version: '4.13.2' |
||||
} |
||||
|
||||
application { |
||||
mainClass = 'Triangle.Compiler' |
||||
} |
||||
} |
||||
|
||||
// allow access to programs for unit tests |
||||
sourceSets.test.resources.srcDir file("$rootDir/programs") |
@ -0,0 +1,22 @@ |
||||
package triangle.abstractSyntaxTrees.commands; |
||||
|
||||
import triangle.abstractSyntaxTrees.expressions.Expression; |
||||
import triangle.abstractSyntaxTrees.visitors.CommandVisitor; |
||||
import triangle.syntacticAnalyzer.SourcePosition; |
||||
|
||||
public class RepeatCommand extends Command { |
||||
|
||||
public RepeatCommand(Expression eAST, Command cAST, SourcePosition position) { |
||||
super(position); |
||||
E = eAST; |
||||
C = cAST; |
||||
} |
||||
|
||||
public <TArg, TResult> TResult visit(CommandVisitor<TArg, TResult> v, TArg arg) { |
||||
return v.visitRepeatCommand(this, arg); |
||||
} |
||||
|
||||
//public final Expression E;
|
||||
public Expression E; |
||||
public final Command C; |
||||
} |
@ -0,0 +1,27 @@ |
||||
package triangle.codeGenerator.entities; |
||||
|
||||
import triangle.abstractMachine.Machine; |
||||
import triangle.abstractMachine.OpCode; |
||||
import triangle.abstractMachine.Primitive; |
||||
import triangle.abstractMachine.Register; |
||||
import triangle.codeGenerator.Emitter; |
||||
import triangle.codeGenerator.Frame; |
||||
|
||||
public class BarPrimitiveRoutine extends RuntimeEntity implements RoutineEntity { |
||||
|
||||
public BarPrimitiveRoutine() { |
||||
super(Machine.closureSize); |
||||
} |
||||
|
||||
public void encodeCall(Emitter emitter, Frame frame) { |
||||
//push the literal value of 100 onto the stack
|
||||
emitter.emit(OpCode.LOADL, 0, 100); |
||||
emitter.emit(OpCode.CALL, Register.PB, Primitive.MULT); |
||||
} |
||||
|
||||
public void encodeFetch(Emitter emitter, Frame frame) { |
||||
emitter.emit(OpCode.LOADA, 0, Register.SB, 0); |
||||
emitter.emit(OpCode.LOADA, Register.PB, Primitive.MULT); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,601 @@ |
||||
package triangle.optimiser; |
||||
|
||||
import triangle.StdEnvironment; |
||||
import triangle.abstractSyntaxTrees.AbstractSyntaxTree; |
||||
import triangle.abstractSyntaxTrees.Program; |
||||
import triangle.abstractSyntaxTrees.actuals.ConstActualParameter; |
||||
import triangle.abstractSyntaxTrees.actuals.EmptyActualParameterSequence; |
||||
import triangle.abstractSyntaxTrees.actuals.FuncActualParameter; |
||||
import triangle.abstractSyntaxTrees.actuals.MultipleActualParameterSequence; |
||||
import triangle.abstractSyntaxTrees.actuals.ProcActualParameter; |
||||
import triangle.abstractSyntaxTrees.actuals.SingleActualParameterSequence; |
||||
import triangle.abstractSyntaxTrees.actuals.VarActualParameter; |
||||
import triangle.abstractSyntaxTrees.aggregates.MultipleArrayAggregate; |
||||
import triangle.abstractSyntaxTrees.aggregates.MultipleRecordAggregate; |
||||
import triangle.abstractSyntaxTrees.aggregates.SingleArrayAggregate; |
||||
import triangle.abstractSyntaxTrees.aggregates.SingleRecordAggregate; |
||||
import triangle.abstractSyntaxTrees.commands.AssignCommand; |
||||
import triangle.abstractSyntaxTrees.commands.CallCommand; |
||||
import triangle.abstractSyntaxTrees.commands.EmptyCommand; |
||||
import triangle.abstractSyntaxTrees.commands.IfCommand; |
||||
import triangle.abstractSyntaxTrees.commands.LetCommand; |
||||
import triangle.abstractSyntaxTrees.commands.RepeatCommand; |
||||
import triangle.abstractSyntaxTrees.commands.SequentialCommand; |
||||
import triangle.abstractSyntaxTrees.commands.WhileCommand; |
||||
import triangle.abstractSyntaxTrees.declarations.BinaryOperatorDeclaration; |
||||
import triangle.abstractSyntaxTrees.declarations.ConstDeclaration; |
||||
import triangle.abstractSyntaxTrees.declarations.FuncDeclaration; |
||||
import triangle.abstractSyntaxTrees.declarations.ProcDeclaration; |
||||
import triangle.abstractSyntaxTrees.declarations.SequentialDeclaration; |
||||
import triangle.abstractSyntaxTrees.declarations.UnaryOperatorDeclaration; |
||||
import triangle.abstractSyntaxTrees.declarations.VarDeclaration; |
||||
import triangle.abstractSyntaxTrees.expressions.ArrayExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.BinaryExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.CallExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.CharacterExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.EmptyExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.Expression; |
||||
import triangle.abstractSyntaxTrees.expressions.IfExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.IntegerExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.LetExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.RecordExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.UnaryExpression; |
||||
import triangle.abstractSyntaxTrees.expressions.VnameExpression; |
||||
import triangle.abstractSyntaxTrees.formals.ConstFormalParameter; |
||||
import triangle.abstractSyntaxTrees.formals.EmptyFormalParameterSequence; |
||||
import triangle.abstractSyntaxTrees.formals.FuncFormalParameter; |
||||
import triangle.abstractSyntaxTrees.formals.MultipleFormalParameterSequence; |
||||
import triangle.abstractSyntaxTrees.formals.ProcFormalParameter; |
||||
import triangle.abstractSyntaxTrees.formals.SingleFormalParameterSequence; |
||||
import triangle.abstractSyntaxTrees.formals.VarFormalParameter; |
||||
import triangle.abstractSyntaxTrees.terminals.CharacterLiteral; |
||||
import triangle.abstractSyntaxTrees.terminals.Identifier; |
||||
import triangle.abstractSyntaxTrees.terminals.IntegerLiteral; |
||||
import triangle.abstractSyntaxTrees.terminals.Operator; |
||||
import triangle.abstractSyntaxTrees.types.AnyTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.ArrayTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.BoolTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.CharTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.ErrorTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.IntTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.MultipleFieldTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.RecordTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.SimpleTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.SingleFieldTypeDenoter; |
||||
import triangle.abstractSyntaxTrees.types.TypeDeclaration; |
||||
import triangle.abstractSyntaxTrees.visitors.ActualParameterSequenceVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.ActualParameterVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.ArrayAggregateVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.CommandVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.DeclarationVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.ExpressionVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.FormalParameterSequenceVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.IdentifierVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.LiteralVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.OperatorVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.ProgramVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.RecordAggregateVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.TypeDenoterVisitor; |
||||
import triangle.abstractSyntaxTrees.visitors.VnameVisitor; |
||||
import triangle.abstractSyntaxTrees.vnames.DotVname; |
||||
import triangle.abstractSyntaxTrees.vnames.SimpleVname; |
||||
import triangle.abstractSyntaxTrees.vnames.SubscriptVname; |
||||
import triangle.codeGenerator.entities.RuntimeEntity; |
||||
|
||||
public class ConstantFolder implements ActualParameterVisitor<Void, AbstractSyntaxTree>, |
||||
ActualParameterSequenceVisitor<Void, AbstractSyntaxTree>, ArrayAggregateVisitor<Void, AbstractSyntaxTree>, |
||||
CommandVisitor<Void, AbstractSyntaxTree>, DeclarationVisitor<Void, AbstractSyntaxTree>, |
||||
ExpressionVisitor<Void, AbstractSyntaxTree>, FormalParameterSequenceVisitor<Void, AbstractSyntaxTree>, |
||||
IdentifierVisitor<Void, AbstractSyntaxTree>, LiteralVisitor<Void, AbstractSyntaxTree>, |
||||
OperatorVisitor<Void, AbstractSyntaxTree>, ProgramVisitor<Void, AbstractSyntaxTree>, |
||||
RecordAggregateVisitor<Void, AbstractSyntaxTree>, TypeDenoterVisitor<Void, AbstractSyntaxTree>, |
||||
VnameVisitor<Void, RuntimeEntity> { |
||||
{ |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitConstFormalParameter(ConstFormalParameter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitFuncFormalParameter(FuncFormalParameter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitProcFormalParameter(ProcFormalParameter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.FPS.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitVarFormalParameter(VarFormalParameter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitMultipleFieldTypeDenoter(MultipleFieldTypeDenoter ast, Void arg) { |
||||
ast.FT.visit(this); |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSingleFieldTypeDenoter(SingleFieldTypeDenoter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public RuntimeEntity visitDotVname(DotVname ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.V.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public RuntimeEntity visitSimpleVname(SimpleVname ast, Void arg) { |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public RuntimeEntity visitSubscriptVname(SubscriptVname ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
ast.V.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitAnyTypeDenoter(AnyTypeDenoter ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitArrayTypeDenoter(ArrayTypeDenoter ast, Void arg) { |
||||
ast.IL.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitBoolTypeDenoter(BoolTypeDenoter ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitCharTypeDenoter(CharTypeDenoter ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitErrorTypeDenoter(ErrorTypeDenoter ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSimpleTypeDenoter(SimpleTypeDenoter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitIntTypeDenoter(IntTypeDenoter ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitRecordTypeDenoter(RecordTypeDenoter ast, Void arg) { |
||||
ast.FT.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitMultipleRecordAggregate(MultipleRecordAggregate ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
ast.I.visit(this); |
||||
ast.RA.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSingleRecordAggregate(SingleRecordAggregate ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitProgram(Program ast, Void arg) { |
||||
ast.C.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitOperator(Operator ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitCharacterLiteral(CharacterLiteral ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitIntegerLiteral(IntegerLiteral ast, Void arg) { |
||||
return ast; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitIdentifier(Identifier ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitEmptyFormalParameterSequence(EmptyFormalParameterSequence ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitMultipleFormalParameterSequence(MultipleFormalParameterSequence ast, Void arg) { |
||||
ast.FP.visit(this); |
||||
ast.FPS.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSingleFormalParameterSequence(SingleFormalParameterSequence ast, Void arg) { |
||||
ast.FP.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitArrayExpression(ArrayExpression ast, Void arg) { |
||||
ast.AA.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitBinaryExpression(BinaryExpression ast, Void arg) { |
||||
AbstractSyntaxTree replacement1 = ast.E1.visit(this); |
||||
AbstractSyntaxTree replacement2 = ast.E2.visit(this); |
||||
ast.O.visit(this); |
||||
|
||||
// if visiting a child node returns something, it's either the original constant
|
||||
// (IntegerLiteral) or a folded version replacing the expression at that child
|
||||
// node
|
||||
// If both child nodes are not null; return a folded version of this
|
||||
// BinaryExpression
|
||||
// Otherwise, at least one child node isn't constant (foldable) so just replace
|
||||
// the
|
||||
// foldable child nodes with their folded equivalent and return null
|
||||
if (replacement1 != null && replacement2 != null) { |
||||
return foldBinaryExpression(replacement1, replacement2, ast.O); |
||||
} else if (replacement1 != null) { |
||||
ast.E1 = (Expression) replacement1; |
||||
} else if (replacement2 != null) { |
||||
ast.E2 = (Expression) replacement2; |
||||
} |
||||
|
||||
// if we get here, we can't fold any higher than this level
|
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitCallExpression(CallExpression ast, Void arg) { |
||||
ast.APS.visit(this); |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitCharacterExpression(CharacterExpression ast, Void arg) { |
||||
ast.CL.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitEmptyExpression(EmptyExpression ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitIfExpression(IfExpression ast, Void arg) { |
||||
AbstractSyntaxTree replacement1 = ast.E1.visit(this); |
||||
if (replacement1 != null) { |
||||
ast.E1 = (Expression) replacement1; |
||||
} |
||||
AbstractSyntaxTree replacement2 = ast.E2.visit(this); |
||||
if (replacement2 != null) { |
||||
ast.E2 = (Expression) replacement2; |
||||
} |
||||
AbstractSyntaxTree replacement3 = ast.E3.visit(this); |
||||
if (replacement3 != null) { |
||||
ast.E3 = (Expression) replacement3; |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitIntegerExpression(IntegerExpression ast, Void arg) { |
||||
return ast; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitLetExpression(LetExpression ast, Void arg) { |
||||
ast.D.visit(this); |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitRecordExpression(RecordExpression ast, Void arg) { |
||||
ast.RA.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitUnaryExpression(UnaryExpression ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
|
||||
ast.O.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitVnameExpression(VnameExpression ast, Void arg) { |
||||
ast.V.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitBinaryOperatorDeclaration(BinaryOperatorDeclaration ast, Void arg) { |
||||
ast.ARG1.visit(this); |
||||
ast.ARG2.visit(this); |
||||
ast.O.visit(this); |
||||
ast.RES.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitConstDeclaration(ConstDeclaration ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitFuncDeclaration(FuncDeclaration ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
ast.FPS.visit(this); |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitProcDeclaration(ProcDeclaration ast, Void arg) { |
||||
ast.C.visit(this); |
||||
ast.FPS.visit(this); |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSequentialDeclaration(SequentialDeclaration ast, Void arg) { |
||||
ast.D1.visit(this); |
||||
ast.D2.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitTypeDeclaration(TypeDeclaration ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitUnaryOperatorDeclaration(UnaryOperatorDeclaration ast, Void arg) { |
||||
ast.ARG.visit(this); |
||||
ast.O.visit(this); |
||||
ast.RES.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitVarDeclaration(VarDeclaration ast, Void arg) { |
||||
ast.I.visit(this); |
||||
ast.T.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitAssignCommand(AssignCommand ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
ast.V.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitCallCommand(CallCommand ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitEmptyCommand(EmptyCommand ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitIfCommand(IfCommand ast, Void arg) { |
||||
ast.C1.visit(this); |
||||
ast.C2.visit(this); |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitLetCommand(LetCommand ast, Void arg) { |
||||
ast.C.visit(this); |
||||
ast.D.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSequentialCommand(SequentialCommand ast, Void arg) { |
||||
ast.C1.visit(this); |
||||
ast.C2.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitWhileCommand(WhileCommand ast, Void arg) { |
||||
ast.C.visit(this); |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
// TODO uncomment if you've implemented the repeat command
|
||||
// @Override
|
||||
// public AbstractSyntaxTree visitRepeatCommand(RepeatCommand ast, Void arg) {
|
||||
// ast.C.visit(this);
|
||||
// AbstractSyntaxTree replacement = ast.E.visit(this);
|
||||
// if (replacement != null) {
|
||||
// ast.E = (Expression) replacement;
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitMultipleArrayAggregate(MultipleArrayAggregate ast, Void arg) { |
||||
ast.AA.visit(this); |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSingleArrayAggregate(SingleArrayAggregate ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitEmptyActualParameterSequence(EmptyActualParameterSequence ast, Void arg) { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitMultipleActualParameterSequence(MultipleActualParameterSequence ast, Void arg) { |
||||
ast.AP.visit(this); |
||||
ast.APS.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitSingleActualParameterSequence(SingleActualParameterSequence ast, Void arg) { |
||||
ast.AP.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitConstActualParameter(ConstActualParameter ast, Void arg) { |
||||
AbstractSyntaxTree replacement = ast.E.visit(this); |
||||
if (replacement != null) { |
||||
ast.E = (Expression) replacement; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitFuncActualParameter(FuncActualParameter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitProcActualParameter(ProcActualParameter ast, Void arg) { |
||||
ast.I.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public AbstractSyntaxTree visitVarActualParameter(VarActualParameter ast, Void arg) { |
||||
ast.V.visit(this); |
||||
return null; |
||||
} |
||||
|
||||
public AbstractSyntaxTree foldBinaryExpression(AbstractSyntaxTree node1, AbstractSyntaxTree node2, Operator o) { |
||||
// the only case we know how to deal with for now is two IntegerExpressions
|
||||
if ((node1 instanceof IntegerExpression) && (node2 instanceof IntegerExpression)) { |
||||
int int1 = (Integer.parseInt(((IntegerExpression) node1).IL.spelling)); |
||||
int int2 = (Integer.parseInt(((IntegerExpression) node2).IL.spelling)); |
||||
Object foldedValue = null; |
||||
|
||||
if (o.decl == StdEnvironment.addDecl) { |
||||
foldedValue = int1 + int2; |
||||
} |
||||
|
||||
if (foldedValue instanceof Integer) { |
||||
IntegerLiteral il = new IntegerLiteral(foldedValue.toString(), node1.getPosition()); |
||||
IntegerExpression ie = new IntegerExpression(il, node1.getPosition()); |
||||
ie.type = StdEnvironment.integerType; |
||||
return ie; |
||||
} else if (foldedValue instanceof Boolean) { |
||||
/* currently not handled! */ |
||||
} |
||||
} |
||||
|
||||
// any unhandled situation (i.e., not foldable) is ignored
|
||||
return null; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,90 @@ |
||||
package triangle.syntacticAnalyser; |
||||
|
||||
import static org.junit.Assert.assertEquals; |
||||
import static org.junit.Assert.assertNotEquals; |
||||
import static org.junit.Assert.assertThrows; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.function.ThrowingRunnable; |
||||
|
||||
import triangle.ErrorReporter; |
||||
import triangle.syntacticAnalyzer.Parser; |
||||
import triangle.syntacticAnalyzer.Scanner; |
||||
import triangle.syntacticAnalyzer.SourceFile; |
||||
|
||||
public class TestScanner { |
||||
|
||||
@Test |
||||
public void testHi() { |
||||
compileExpectSuccess("/hi.tri"); |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void testHiNewComment() { |
||||
compileExpectSuccess("/hi-newcomment.tri"); |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void testHiNewComment2() { |
||||
compileExpectSuccess("/hi-newcomment2.tri"); |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void testBarDemo() { |
||||
compileExpectSuccess("/bardemo.tri"); //TODO: Change this to failure
|
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void testRepeatUntil() { |
||||
compileExpectSuccess("/repeatuntil.tri"); |
||||
} |
||||
|
||||
@Test |
||||
public void testAdd() { |
||||
//compileExpectFailure("/addd.tri"); //fail here!
|
||||
compileExpectFailure("/add.tri"); |
||||
} |
||||
|
||||
|
||||
|
||||
private void compileExpectSuccess(String filename) { |
||||
// build.gradle has a line sourceSets.test.resources.srcDir file("$rootDir/programs")
|
||||
// which adds the programs directory to the list of places Java can easily find files
|
||||
// getResource() below searches for a file, which is in /programs
|
||||
//SourceFile source = SourceFile.ofPath(this.getClass().getResource(filename).getFile().toString());
|
||||
SourceFile source = SourceFile.fromResource(filename); |
||||
|
||||
Scanner scanner = new Scanner(source); |
||||
ErrorReporter reporter = new ErrorReporter(true); |
||||
Parser parser = new Parser(scanner, reporter); |
||||
|
||||
parser.parseProgram(); |
||||
|
||||
// we should get to here with no exceptions
|
||||
|
||||
assertEquals("Problem compiling " + filename, 0, reporter.getNumErrors()); |
||||
} |
||||
|
||||
private void compileExpectFailure(String filename) { |
||||
//SourceFile source = SourceFile.ofPath(this.getClass().getResource(filename).getFile().toString());
|
||||
SourceFile source = SourceFile.fromResource(filename); |
||||
Scanner scanner = new Scanner(source); |
||||
ErrorReporter reporter = new ErrorReporter(true); |
||||
Parser parser = new Parser(scanner, reporter); |
||||
|
||||
// we expect an exception here as the program has invalid syntax
|
||||
assertThrows(RuntimeException.class, new ThrowingRunnable() { |
||||
public void run(){ |
||||
parser.parseProgram(); |
||||
} |
||||
}); |
||||
|
||||
// currently this program will fail
|
||||
assertNotEquals("Problem compiling " + filename, 0, reporter.getNumErrors()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,11 @@ |
||||
apply plugin: 'java' |
||||
|
||||
sourceCompatibility = 11 |
||||
|
||||
subprojects.each { subproject -> |
||||
evaluationDependsOn(subproject.path) |
||||
} |
||||
|
||||
jar { |
||||
from subprojects.sourceSets.main.output |
||||
} |
Binary file not shown.
@ -0,0 +1,46 @@ |
||||
! Program that will: read two ints, print their sum and their product. If they are the same, print "Same" |
||||
|
||||
! Global Consts, Funcs. |
||||
let |
||||
type String ~ array 6 of Char; ! String type implemented, not used yet |
||||
|
||||
var num1 : Integer; |
||||
var num2 : Integer; |
||||
|
||||
|
||||
func sum(x : Integer, y : Integer) : Integer ~ |
||||
x + y; ! Return x + y |
||||
|
||||
func product(x : Integer, y : Integer) : Integer ~ |
||||
x * y; ! Return x * y |
||||
|
||||
func isSame(x : Integer, y : Integer) : Boolean ~ |
||||
if x = y then true else false |
||||
|
||||
! Main Loop |
||||
in |
||||
begin |
||||
num1 := 0; |
||||
num2 := 0; ! Init. values to 0 |
||||
|
||||
getint(var num1); |
||||
getint(var num2); ! Get user input |
||||
|
||||
|
||||
! Sum |
||||
putint(num1); put('+'); put(' '); putint(num2); put(' '); put('='); put(' '); |
||||
putint(sum(num1, num2)); puteol(); |
||||
|
||||
puteol(); |
||||
|
||||
! Product |
||||
putint(num1); put(' '); put('*'); put(' '); putint(num2); put(' '); put('='); put(' '); |
||||
putint(product(num1, num2)); puteol(); |
||||
|
||||
|
||||
if isSame(num1, num2) = true then |
||||
put('S'); put('a'); put('m'); put('e'); puteol(); |
||||
else |
||||
puteol(); |
||||
|
||||
end |
@ -0,0 +1,12 @@ |
||||
let |
||||
var a: Integer |
||||
in |
||||
begin |
||||
a := 10 + 20 * 2 / 3; |
||||
putint(a); |
||||
|
||||
puteol(); |
||||
|
||||
a := 5 + 8; |
||||
putint(a) |
||||
end |
@ -0,0 +1,27 @@ |
||||
! this won't work until after some work in the practicals |
||||
let |
||||
var a : Integer; |
||||
var b : Integer |
||||
|
||||
in |
||||
begin |
||||
a := 1; |
||||
b := 2; |
||||
|
||||
putint(a); |
||||
<<<<<<< HEAD |
||||
puteol(); |
||||
======= |
||||
puteol(); |
||||
>>>>>>> ce307a11a6c71de9c69bd0a4c91205bb6437f6e9 |
||||
putint(b); |
||||
puteol(); |
||||
putint(|a); |
||||
puteol(); |
||||
putint(|b); |
||||
puteol() |
||||
<<<<<<< HEAD |
||||
|
||||
======= |
||||
>>>>>>> ce307a11a6c71de9c69bd0a4c91205bb6437f6e9 |
||||
end |
@ -0,0 +1,30 @@ |
||||
! Program with a variety of contextual errors. |
||||
|
||||
let |
||||
type String ~ array 4 of Char; |
||||
type Name ~ array 3 of String; |
||||
type Rec ~ record x: Integer, x: Integer end; |
||||
|
||||
var me: Name; |
||||
var silly : maxint; |
||||
var silly: Rec; |
||||
|
||||
proc putstr (s: String) ~ |
||||
let var i: Integer |
||||
in |
||||
begin |
||||
s[4] := ' '; |
||||
i := 0; |
||||
while i do |
||||
begin i := i+true; |
||||
put (s[\i]) |
||||
end |
||||
end |
||||
|
||||
in |
||||
begin |
||||
me[true] := ['T','i','n','y']; |
||||
me[2][2] := 0; |
||||
put (me[1]); put (4); put (); |
||||
putstr (initials (me)); puteol () |
||||
end |
@ -0,0 +1,7 @@ |
||||
! this won't work until after some work in the practicals |
||||
|
||||
# new comment |
||||
|
||||
begin |
||||
put('H'); put('i'); put('!') |
||||
end |
@ -0,0 +1,14 @@ |
||||
! this won't work until after some work in the practicals |
||||
|
||||
# new comment |
||||
|
||||
$ |
||||
another new comment |
||||
another new comment |
||||
another new comment |
||||
another new comment |
||||
$ |
||||
|
||||
begin |
||||
put('H'); put('i'); put('!') |
||||
end |
@ -0,0 +1,14 @@ |
||||
! this won't compile without implementing the bonus material in Practical 3 |
||||
|
||||
let |
||||
var a: Integer |
||||
in |
||||
begin |
||||
getint(var a); |
||||
a++; |
||||
putint(a); |
||||
puteol(); |
||||
a++; |
||||
putint(a); |
||||
puteol(); |
||||
end |
@ -0,0 +1,14 @@ |
||||
! this won't work until after some lab work |
||||
|
||||
let |
||||
var a : Integer |
||||
in |
||||
begin |
||||
a := 0; |
||||
repeat |
||||
begin |
||||
put('a'); |
||||
a := a + 1; |
||||
end |
||||
until a >= 5 |
||||
end |
@ -0,0 +1,22 @@ |
||||
let |
||||
var a : Integer; |
||||
var b : Integer; |
||||
var c : Integer |
||||
in |
||||
begin |
||||
put('1'); |
||||
puteol(); |
||||
a := 0; |
||||
while a < 5000 do |
||||
begin |
||||
b := 0; |
||||
while b < 3000 do |
||||
begin |
||||
c := c + a; |
||||
c := c / (1 + b); |
||||
b := b + 1; |
||||
end; |
||||
a := a + 1; |
||||
end; |
||||
putint(c); |
||||
end |
@ -0,0 +1,11 @@ |
||||
let |
||||
var a : Integer |
||||
in |
||||
begin |
||||
a := 0; |
||||
while a < 5 do |
||||
begin |
||||
put('a'); |
||||
a := a + 1; |
||||
end |
||||
end |
@ -0,0 +1,29 @@ |
||||
#!/bin/bash |
||||
|
||||
RED='\033[0;31m' # Red |
||||
GRN='\033[0;32m' # Green |
||||
NC='\033[0m' # No Color |
||||
|
||||
file="" |
||||
|
||||
if [ -z "$1" ] |
||||
then |
||||
printf "${RED}Usage: $0 file${NC}" |
||||
exit 1 # Exit with code 1, failure |
||||
else |
||||
file=$1 |
||||
fi |
||||
|
||||
printf "${GRN}[INFO] Compiling file: $1.tri to $1.tam ...${NC}\n" |
||||
|
||||
# Compile to tam |
||||
if java -cp build/libs/Triangle-Tools.jar triangle.Compiler programs/$1.tri -o=$1.tam &> /dev/null #quiet |
||||
then |
||||
printf "${GRN}[INFO] Running file: $1.tam ...${NC}\n" |
||||
java -cp build/libs/Triangle-Tools.jar triangle.abstractMachine.Interpreter $1.tam |
||||
else |
||||
printf "${RED}[ERROR] Could not complie $1.tri ...${NC}" |
||||
err=$(java -cp build/libs/Triangle-Tools.jar triangle.Compiler programs/$1.tri -o=$1.tam) |
||||
printf "${RED}\n$err\n${NC}" |
||||
exit 1 |
||||
fi |
Reference in new issue