From 0e008be7e97ffba3bce55b9ebeca26af65810d00 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Mon, 20 Mar 2017 11:01:23 -0300 Subject: [PATCH 01/20] add type declarations --- src/main/java/absyn/DecType.java | 7 ++++ src/main/java/absyn/DecTypeMutual.java | 46 ++++++++++++++++++++++++++ src/main/java/absyn/Ty.java | 16 +++++++++ src/main/java/absyn/TyName.java | 7 ++++ 4 files changed, 76 insertions(+) create mode 100644 src/main/java/absyn/DecType.java create mode 100644 src/main/java/absyn/DecTypeMutual.java create mode 100644 src/main/java/absyn/Ty.java create mode 100644 src/main/java/absyn/TyName.java diff --git a/src/main/java/absyn/DecType.java b/src/main/java/absyn/DecType.java new file mode 100644 index 0000000..7a4b26e --- /dev/null +++ b/src/main/java/absyn/DecType.java @@ -0,0 +1,7 @@ +package absyn; + +/** + * Created by mvosouza on 15/03/17. + */ +public class DecType { +} diff --git a/src/main/java/absyn/DecTypeMutual.java b/src/main/java/absyn/DecTypeMutual.java new file mode 100644 index 0000000..aff4870 --- /dev/null +++ b/src/main/java/absyn/DecTypeMutual.java @@ -0,0 +1,46 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import parse.Loc; +import semantic.SemanticHelper; +import types.Type; + +public class DecVar extends Dec { + + public final String name; + public final String typeName; + public final Exp init; + + public DecVar(Loc loc, String name, String typeName, Exp init) { + super(loc); + this.name = name; + this.typeName = typeName; + this.init = init; + } + + @Override + public Tree.Node toTree() { + List> children = List.of(Tree.of(name)); + if (typeName != null) + children = children.append(Tree.of(typeName)); + children = children.append(init.toTree()); + return Tree.of("DecVar", children); + } + + @Override + public void semantic(Env env) { + Type t_init = init.semantic(env); + Type t_var = t_init; + if (typeName != null) { + Type t_typeName = env.tenv.get(typeName); + if (t_typeName == null) + throw SemanticHelper.undefined(loc, "type", typeName); + if (!t_init.is(t_typeName)) + throw SemanticHelper.typeMismatch(init.loc, t_init, t_typeName); + t_var = t_typeName; + } + env.venv.put(name, t_var); + } +} diff --git a/src/main/java/absyn/Ty.java b/src/main/java/absyn/Ty.java new file mode 100644 index 0000000..f29bb85 --- /dev/null +++ b/src/main/java/absyn/Ty.java @@ -0,0 +1,16 @@ +package absyn; + +import env.Env; +import parse.Loc; +import types.Type; + +public abstract class Dec extends AST { + + public Dec(Loc loc) { + super(loc); + } + + // Do semantic analysis of the declaraction + public abstract void semantic(Env env); + +} diff --git a/src/main/java/absyn/TyName.java b/src/main/java/absyn/TyName.java new file mode 100644 index 0000000..3d22728 --- /dev/null +++ b/src/main/java/absyn/TyName.java @@ -0,0 +1,7 @@ +package absyn; + +/** + * Created by mvosouza on 15/03/17. + */ +public class TyName { +} From f64caa829215350245548944e34ecbc3961eee2c Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Fri, 24 Mar 2017 20:09:59 -0300 Subject: [PATCH 02/20] add command while, break and the relational operators --- src/main/cup/parser.cup | 16 ++- src/main/java/absyn/DecFunction.java | 46 +++++++ src/main/java/absyn/DecFunctionMutual.java | 38 ++++++ src/main/java/absyn/ExpBinOp.java | 136 ++++++++++++--------- src/main/java/absyn/ExpBreak.java | 41 +++++++ src/main/java/absyn/ExpWhile.java | 51 ++++++++ src/main/java/absyn/Parameter.java | 7 ++ src/main/java/types/NAME.java | 7 ++ src/main/jflex/lexer.jflex | 10 ++ 9 files changed, 295 insertions(+), 57 deletions(-) create mode 100644 src/main/java/absyn/DecFunction.java create mode 100644 src/main/java/absyn/DecFunctionMutual.java create mode 100644 src/main/java/absyn/ExpBreak.java create mode 100644 src/main/java/absyn/ExpWhile.java create mode 100644 src/main/java/absyn/Parameter.java create mode 100644 src/main/java/types/NAME.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index e076a7e..f4c00d9 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -51,6 +51,8 @@ terminal LET, IN; terminal ASSIGN; terminal IF, THEN, ELSE; terminal TYPE; +terminal EQT, NEQ, LT, LE, GT, GE; +terminal WHILE, DO, BREAK; non terminal Exp program; non terminal Exp exp; @@ -64,8 +66,10 @@ non terminal List decs_beg_with_variable, decs_beg_with_type; non terminal Var var; non terminal Ty ty; + precedence left OR; precedence left AND; +precedence nonassoc EQT, NEQ, LT, LE, GT, GE; precedence left PLUS, MINUS; precedence left TIMES, DIV; precedence left UMINUS; @@ -84,6 +88,12 @@ exp ::= | exp:x DIV exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.DIV, x, y); :} | exp:x AND exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.AND, x, y); :} | exp:x OR exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.OR, x, y); :} +| exp:x EQT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.EQT, x, y); :} +| exp:x NEQ exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.NEQ, x, y); :} +| exp:x LT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.LT, x, y); :} +| exp:x LE exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.LE, x, y); :} +| exp:x GT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.GT, x, y); :} +| exp:x GE exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.GE, x, y); :} | LITINT:x {: RESULT = new ExpInt(loc(xxleft,xxright), x); :} | LITREAL:x {: RESULT = new ExpReal(loc(xxleft,xxright), x); :} | LITBOOL:x {: RESULT = new ExpBool(loc(xxleft,xxright), x); :} @@ -95,6 +105,8 @@ exp ::= | LPAREN:l expseq:es RPAREN:r {: RESULT = new ExpSeq(loc(lxleft,rxright), es); :} | IF:i exp:t THEN exp:a ELSE exp:b {: RESULT = new ExpIf(loc(ixleft,bxright), t, a, b); :} | IF:i exp:t THEN exp:a {: RESULT = new ExpIf(loc(ixleft,axright), t, a, null); :} +| WHILE:w exp:t DO exp:b {: RESULT = new ExpWhile(loc(wxleft,bxright), t, b); :} +| BREAK:b {: RESULT = new ExpBreak(loc(bxleft,bxright)); :} ; exps ::= @@ -152,5 +164,7 @@ var ::= ; ty ::= - ID:id {: RESULT = new TyName(loc(idxleft,idxright), id); :} + ID:id {: RESULT = new TyName(loc(idxleft,idxright), id); :} ; + + diff --git a/src/main/java/absyn/DecFunction.java b/src/main/java/absyn/DecFunction.java new file mode 100644 index 0000000..aff4870 --- /dev/null +++ b/src/main/java/absyn/DecFunction.java @@ -0,0 +1,46 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import parse.Loc; +import semantic.SemanticHelper; +import types.Type; + +public class DecVar extends Dec { + + public final String name; + public final String typeName; + public final Exp init; + + public DecVar(Loc loc, String name, String typeName, Exp init) { + super(loc); + this.name = name; + this.typeName = typeName; + this.init = init; + } + + @Override + public Tree.Node toTree() { + List> children = List.of(Tree.of(name)); + if (typeName != null) + children = children.append(Tree.of(typeName)); + children = children.append(init.toTree()); + return Tree.of("DecVar", children); + } + + @Override + public void semantic(Env env) { + Type t_init = init.semantic(env); + Type t_var = t_init; + if (typeName != null) { + Type t_typeName = env.tenv.get(typeName); + if (t_typeName == null) + throw SemanticHelper.undefined(loc, "type", typeName); + if (!t_init.is(t_typeName)) + throw SemanticHelper.typeMismatch(init.loc, t_init, t_typeName); + t_var = t_typeName; + } + env.venv.put(name, t_var); + } +} diff --git a/src/main/java/absyn/DecFunctionMutual.java b/src/main/java/absyn/DecFunctionMutual.java new file mode 100644 index 0000000..1268433 --- /dev/null +++ b/src/main/java/absyn/DecFunctionMutual.java @@ -0,0 +1,38 @@ +package absyn; + +import env.Env; +import error.CompilerError; +import javaslang.collection.List; +import javaslang.collection.Tree; +import parse.Loc; +import types.NAME; +import types.Type; + + +public class DecTypeMutual extends Dec { + + public final List decs; + + public DecTypeMutual(Loc loc, List decs) { + super(loc); + this.decs = decs; + } + + @Override + public Tree.Node toTree() { + return Tree.of("DecTypeMutual", decs.map(DecType::toTree)); + } + + @Override + public void semantic(Env env) { + for (DecType d : decs) + env.tenv.put(d.name, new NAME(d.name)); + for (DecType d : decs){ + Type t = d.ty.semantic(env); + Type tname = env.tenv.get(d.name); + if (!(tname instanceof NAME)) + throw new CompilerError("bug!!!!!!"); + ((NAME) tname).binding = t; + } + } +} diff --git a/src/main/java/absyn/ExpBinOp.java b/src/main/java/absyn/ExpBinOp.java index dce0d7d..cd11956 100644 --- a/src/main/java/absyn/ExpBinOp.java +++ b/src/main/java/absyn/ExpBinOp.java @@ -14,61 +14,85 @@ public class ExpBinOp extends Exp { - public enum Op { - PLUS, MINUS, TIMES, DIV, - AND, OR - } - - public final Op op; - public final Exp left; - public final Exp right; - - public ExpBinOp(Loc loc, Op op, Exp left, Exp right) { - super(loc); - this.op = op; - this.left = left; - this.right = right; - } - - @Override - public Tree.Node toTree() { - return Tree.of(annotateType("ExpBinOp: " + op), left.toTree(), right.toTree()); - } - - @Override - protected Type semantic_(Env env) { - final Type t_left = left.semantic(env); - final Type t_right = right.semantic(env); - - switch (op) { - case PLUS: - case MINUS: - case TIMES: - case DIV: - if (!t_left.is(INT.T, REAL.T)) - throw typeMismatch(left.loc, t_left, INT.T, REAL.T); - - if (!t_right.is(INT.T, REAL.T)) - throw typeMismatch(right.loc, t_right, INT.T, REAL.T); - - if (t_left.is(REAL.T) || t_right.is(REAL.T)) - return REAL.T; - - return INT.T; - - case AND: - case OR: - if (!t_left.is(BOOL.T)) - throw typeMismatch(left.loc, t_left, BOOL.T); - - if (!t_right.is(BOOL.T)) - throw typeMismatch(right.loc, t_right, BOOL.T); - - return BOOL.T; - - default: - throw fatal("unexpected invalid operator: %s", op); - } - } + public enum Op { + PLUS, MINUS, TIMES, DIV, + AND, OR, EQT, NEQ, LT, LE, GT, GE + } + + public final Op op; + public final Exp left; + public final Exp right; + + public ExpBinOp(Loc loc, Op op, Exp left, Exp right) { + super(loc); + this.op = op; + this.left = left; + this.right = right; + } + + @Override + public Tree.Node toTree() { + return Tree.of(annotateType("ExpBinOp: " + op), left.toTree(), right.toTree()); + } + + @Override + protected Type semantic_(Env env) { + final Type t_left = left.semantic(env); + final Type t_right = right.semantic(env); + + switch (op) { + case PLUS: + case MINUS: + case TIMES: + case DIV: + if (!t_left.is(INT.T, REAL.T)) + throw typeMismatch(left.loc, t_left, INT.T, REAL.T); + + if (!t_right.is(INT.T, REAL.T)) + throw typeMismatch(right.loc, t_right, INT.T, REAL.T); + + if (t_left.is(REAL.T) || t_right.is(REAL.T)) + return REAL.T; + + return INT.T; + + case AND: + case OR: + if (!t_left.is(BOOL.T)) + throw typeMismatch(left.loc, t_left, BOOL.T); + + if (!t_right.is(BOOL.T)) + throw typeMismatch(right.loc, t_right, BOOL.T); + + return BOOL.T; + + case EQT: + case NEQ: + if (!t_left.is(BOOL.T, INT.T, REAL.T)) + throw typeMismatch(left.loc, t_left, BOOL.T, INT.T, REAL.T); + + if (!t_right.is(t_left)) { + if (t_right.is(INT.T) || t_right.is(REAL.T)) + return BOOL.T; + + throw typeMismatch(right.loc, t_right, t_left); + } + return BOOL.T; + case LT: + case LE: + case GT: + case GE: + if (!t_left.is(INT.T, REAL.T)) + throw typeMismatch(left.loc, t_left, INT.T, REAL.T); + + if (!t_right.is(INT.T, REAL.T)) + throw typeMismatch(right.loc, t_right, INT.T, REAL.T); + + return BOOL.T; + + default: + throw fatal("unexpected invalid operator: %s", op); + } + } } diff --git a/src/main/java/absyn/ExpBreak.java b/src/main/java/absyn/ExpBreak.java new file mode 100644 index 0000000..a07a1c8 --- /dev/null +++ b/src/main/java/absyn/ExpBreak.java @@ -0,0 +1,41 @@ +package absyn; + +import env.Env; +import javaslang.collection.Tree; +import parse.Loc; +import types.BOOL; +import types.Type; +import types.UNIT; + +import static semantic.SemanticHelper.typeMismatch; + +public class ExpWhile extends Exp { + + public final Exp test; + public final Exp body; + + + public ExpWhile(Loc loc, Exp test, Exp body) { + super(loc); + this.test = test; + this.body = body; + } + + @Override + public Tree.Node toTree() { + return Tree.of(annotateType("ExpWhile: "), test.toTree(), body.toTree()); + } + + @Override + protected Type semantic_(Env env) { + //Verificando a expressão teste + final Type t_test = test.semantic(env); + if (!t_test.is(BOOL.T)) + throw typeMismatch(test.loc, t_test, BOOL.T); + + body.semantic(env); + + return UNIT.T; + } + +} diff --git a/src/main/java/absyn/ExpWhile.java b/src/main/java/absyn/ExpWhile.java new file mode 100644 index 0000000..c0ffd04 --- /dev/null +++ b/src/main/java/absyn/ExpWhile.java @@ -0,0 +1,51 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import parse.Loc; +import types.*; + +import static semantic.SemanticHelper.typeMismatch; + +public class ExpIf extends Exp { + + public final Exp test; + public final Exp alt1; + public final Exp alt2; + + public ExpIf(Loc loc, Exp test, Exp alt1, Exp alt2) { + super(loc); + this.test = test; + this.alt1 = alt1; + this.alt2 = alt2; + } + + @Override + public Tree.Node toTree() { + List> children = List.of(test.toTree(), alt1.toTree()); + if (alt2 != null) + children = children.append(alt2.toTree()); + return Tree.of(annotateType("ExpIf: "), children); + } + + @Override + protected Type semantic_(Env env) { + final Type t_test = test.semantic(env); + if (!t_test.is(BOOL.T)) + throw typeMismatch(test.loc, t_test, BOOL.T); + final Type t_alt1 = alt1.semantic(env); + if (alt2 == null) { + if (!t_alt1.is(UNIT.T)) + throw typeMismatch(alt1.loc, t_alt1, UNIT.T); + return UNIT.T; + } + final Type t_alt2 = alt2.semantic(env); + if (t_alt2.is(t_alt1)) + return t_alt1; + if (t_alt1.is(t_alt2)) + return t_alt2; + throw typeMismatch(alt2.loc, t_alt2, t_alt1); + } + +} diff --git a/src/main/java/absyn/Parameter.java b/src/main/java/absyn/Parameter.java new file mode 100644 index 0000000..e8111a6 --- /dev/null +++ b/src/main/java/absyn/Parameter.java @@ -0,0 +1,7 @@ +package absyn; + +/** + * Created by mvosouza on 24/03/17. + */ +public class parameter { +} diff --git a/src/main/java/types/NAME.java b/src/main/java/types/NAME.java new file mode 100644 index 0000000..82ad305 --- /dev/null +++ b/src/main/java/types/NAME.java @@ -0,0 +1,7 @@ +package types; + +/** + * Created by mvosouza on 20/03/17. + */ +public class NAME { +} diff --git a/src/main/jflex/lexer.jflex b/src/main/jflex/lexer.jflex index 395a079..05cb00a 100644 --- a/src/main/jflex/lexer.jflex +++ b/src/main/jflex/lexer.jflex @@ -84,6 +84,10 @@ in { return tok(IN); } if { return tok(IF); } then { return tok(THEN); } else { return tok(ELSE); } +while { return tok(WHILE); } +do { return tok(DO); } +break { return tok(BREAK); } + {id} { return tok(ID, yytext().intern()); } @@ -100,5 +104,11 @@ else { return tok(ELSE); } ":" { return tok(COLON); } "=" { return tok(EQ); } ":=" { return tok(ASSIGN); } +"==" { return tok(EQT); } +"!=" { return tok(NEQ); } +"<" { return tok(LT); } +"<=" { return tok(LE); } +">" { return tok(GT); } +">=" { return tok(GE); } . { throw error(Loc.loc(locLeft()), "unexpected char '%s'", yytext()); } From e09629a36cbbeca193a418eb2f16ec2e732bda3e Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Fri, 24 Mar 2017 20:14:10 -0300 Subject: [PATCH 03/20] Merge branch type-declaration with master --- doc/eplan-compiler.tex | 2 +- src/main/java/absyn/Dec.java | 2 +- src/main/java/absyn/DecFunction.java | 53 ++++++---------- src/main/java/absyn/DecFunctionMutual.java | 54 +++++++++++----- src/main/java/absyn/DecTypeMutual.java | 39 ++++++++---- src/main/java/absyn/DecVar.java | 3 +- src/main/java/absyn/ExpBreak.java | 22 ++----- src/main/java/absyn/ExpWhile.java | 74 ++++++++++------------ src/main/java/absyn/Parameter.java | 33 ++++++++-- src/main/java/absyn/Ty.java | 3 +- src/main/java/absyn/TyName.java | 10 ++- src/main/java/env/Env.java | 73 +++++++++++---------- src/main/java/semantic/SemanticHelper.java | 66 ++++++++++--------- src/main/java/types/NAME.java | 28 ++++++-- src/main/java/types/Type.java | 40 ++++++------ 15 files changed, 289 insertions(+), 213 deletions(-) diff --git a/doc/eplan-compiler.tex b/doc/eplan-compiler.tex index 33119f5..0e71f42 100644 --- a/doc/eplan-compiler.tex +++ b/doc/eplan-compiler.tex @@ -1526,7 +1526,7 @@ \section{Análise semântica} % \begin{pygmented}[] % // declarações % Dec(Loc loc) // classe abstrata -% VarDec(Loc loc, Symbol name, Symbol type, Exp init) +% VarDec(Loc loc, Symbol name, Symbol type, Exp body) % // variáveis % Var(Loc loc) // classe abstrata diff --git a/src/main/java/absyn/Dec.java b/src/main/java/absyn/Dec.java index f29bb85..f2860ee 100644 --- a/src/main/java/absyn/Dec.java +++ b/src/main/java/absyn/Dec.java @@ -11,6 +11,6 @@ public Dec(Loc loc) { } // Do semantic analysis of the declaraction - public abstract void semantic(Env env); + public abstract Type semantic(Env env); } diff --git a/src/main/java/absyn/DecFunction.java b/src/main/java/absyn/DecFunction.java index aff4870..d362faf 100644 --- a/src/main/java/absyn/DecFunction.java +++ b/src/main/java/absyn/DecFunction.java @@ -4,43 +4,30 @@ import javaslang.collection.List; import javaslang.collection.Tree; import parse.Loc; -import semantic.SemanticHelper; import types.Type; -public class DecVar extends Dec { +public class DecFunction extends AST { - public final String name; - public final String typeName; - public final Exp init; + public final String name; + public final List parameters; + public final String typeName; + public final Exp body; - public DecVar(Loc loc, String name, String typeName, Exp init) { - super(loc); - this.name = name; - this.typeName = typeName; - this.init = init; - } + public DecFunction(Loc loc, String name, List parameters, String typeName, Exp body) { + super(loc); + this.name = name; + this.parameters = parameters; + this.typeName = typeName; + this.body = body; + } - @Override - public Tree.Node toTree() { - List> children = List.of(Tree.of(name)); - if (typeName != null) - children = children.append(Tree.of(typeName)); - children = children.append(init.toTree()); - return Tree.of("DecVar", children); - } + @Override + public Tree.Node toTree() { + return Tree.of("DecFunction: " + name, + Tree.of("Parameters", parameters.map(Parameter::toTree)), + Tree.of(typeName == null ? "" : typeName), + body.toTree() + ); + } - @Override - public void semantic(Env env) { - Type t_init = init.semantic(env); - Type t_var = t_init; - if (typeName != null) { - Type t_typeName = env.tenv.get(typeName); - if (t_typeName == null) - throw SemanticHelper.undefined(loc, "type", typeName); - if (!t_init.is(t_typeName)) - throw SemanticHelper.typeMismatch(init.loc, t_init, t_typeName); - t_var = t_typeName; - } - env.venv.put(name, t_var); - } } diff --git a/src/main/java/absyn/DecFunctionMutual.java b/src/main/java/absyn/DecFunctionMutual.java index 1268433..f114948 100644 --- a/src/main/java/absyn/DecFunctionMutual.java +++ b/src/main/java/absyn/DecFunctionMutual.java @@ -1,38 +1,62 @@ package absyn; import env.Env; -import error.CompilerError; import javaslang.collection.List; import javaslang.collection.Tree; import parse.Loc; -import types.NAME; +import semantic.SemanticHelper; +import types.FUNCTION; import types.Type; +import types.UNIT; -public class DecTypeMutual extends Dec { +public class DecFunctionMutual extends Dec { - public final List decs; + public final List decs; - public DecTypeMutual(Loc loc, List decs) { + public DecFunctionMutual(Loc loc, List decs) { super(loc); this.decs = decs; } @Override public Tree.Node toTree() { - return Tree.of("DecTypeMutual", decs.map(DecType::toTree)); + return Tree.of("DecFunctionMutual", decs.map(DecFunction::toTree)); } @Override - public void semantic(Env env) { - for (DecType d : decs) - env.tenv.put(d.name, new NAME(d.name)); - for (DecType d : decs){ - Type t = d.ty.semantic(env); - Type tname = env.tenv.get(d.name); - if (!(tname instanceof NAME)) - throw new CompilerError("bug!!!!!!"); - ((NAME) tname).binding = t; + public Type semantic(Env env) { + for (DecFunction d : decs) { + List t_params = d.parameters.map(p -> p.semantic(env)); + + Type t_result = UNIT.T; + if (d.typeName != null) { + t_result = env.tenv.get(d.name); + if (t_result == null) { + throw SemanticHelper.undefined(d.loc, "type", d.name); + } + } + + env.venv.put(d.name, new FUNCTION(t_result, t_params)); + } + for (DecFunction d : decs) { + env.venv.beginScope(); + + FUNCTION func = (FUNCTION) env.venv.get(d.name); + List t_params = func.formals; + List parameters = d.parameters; + + while (!parameters.isEmpty()) { + env.venv.put(parameters.head().name, t_params.head()); + parameters = parameters.tail(); + t_params = t_params.tail(); + } + + Type t_body = d.body.semantic(env); + if (!t_body.is(func.result)) + throw SemanticHelper.functionTypeMismatch(d.loc, func.result, t_body); + env.venv.endScope(); } + return null; } } diff --git a/src/main/java/absyn/DecTypeMutual.java b/src/main/java/absyn/DecTypeMutual.java index 3d0ba5f..0bc3a76 100644 --- a/src/main/java/absyn/DecTypeMutual.java +++ b/src/main/java/absyn/DecTypeMutual.java @@ -1,28 +1,39 @@ package absyn; import env.Env; +import error.CompilerError; import javaslang.collection.List; import javaslang.collection.Tree; import parse.Loc; -import semantic.SemanticHelper; +import types.NAME; import types.Type; -public class DecTypeMutual extends Dec { - public final List decs; +public class DecTypeMutual extends Dec { - public DecTypeMutual(Loc loc, List decs) { - super(loc); - this.decs = decs; - } + public final List decs; - @Override - public Tree.Node toTree() { - return Tree.of("DecTypeMutual", decs.map(DecType::toTree)); - } + public DecTypeMutual(Loc loc, List decs) { + super(loc); + this.decs = decs; + } - @Override - public void semantic(Env env) { + @Override + public Tree.Node toTree() { + return Tree.of("DecTypeMutual", decs.map(DecType::toTree)); + } - } + @Override + public Type semantic(Env env) { + for (DecType d : decs) + env.tenv.put(d.name, new NAME(d.name)); + for (DecType d : decs){ + Type t = d.ty.semantic(env); + Type tname = env.tenv.get(d.name); + if (!(tname instanceof NAME)) + throw new CompilerError("bug!!!!!!"); + ((NAME) tname).binding = t; + } + return null; + } } diff --git a/src/main/java/absyn/DecVar.java b/src/main/java/absyn/DecVar.java index aff4870..f869ca9 100644 --- a/src/main/java/absyn/DecVar.java +++ b/src/main/java/absyn/DecVar.java @@ -30,7 +30,7 @@ public Tree.Node toTree() { } @Override - public void semantic(Env env) { + public Type semantic(Env env) { Type t_init = init.semantic(env); Type t_var = t_init; if (typeName != null) { @@ -42,5 +42,6 @@ public void semantic(Env env) { t_var = t_typeName; } env.venv.put(name, t_var); + return t_init; } } diff --git a/src/main/java/absyn/ExpBreak.java b/src/main/java/absyn/ExpBreak.java index a07a1c8..b96460c 100644 --- a/src/main/java/absyn/ExpBreak.java +++ b/src/main/java/absyn/ExpBreak.java @@ -7,34 +7,24 @@ import types.Type; import types.UNIT; +import static semantic.SemanticHelper.breakOutWhile; import static semantic.SemanticHelper.typeMismatch; -public class ExpWhile extends Exp { +public class ExpBreak extends Exp { - public final Exp test; - public final Exp body; - - - public ExpWhile(Loc loc, Exp test, Exp body) { + public ExpBreak(Loc loc) { super(loc); - this.test = test; - this.body = body; } @Override public Tree.Node toTree() { - return Tree.of(annotateType("ExpWhile: "), test.toTree(), body.toTree()); + return Tree.of(annotateType("ExpBreak")); } @Override protected Type semantic_(Env env) { - //Verificando a expressão teste - final Type t_test = test.semantic(env); - if (!t_test.is(BOOL.T)) - throw typeMismatch(test.loc, t_test, BOOL.T); - - body.semantic(env); - + if (env.isWhile.size() == 0) + throw breakOutWhile(loc); return UNIT.T; } diff --git a/src/main/java/absyn/ExpWhile.java b/src/main/java/absyn/ExpWhile.java index c0ffd04..12f4abf 100644 --- a/src/main/java/absyn/ExpWhile.java +++ b/src/main/java/absyn/ExpWhile.java @@ -1,51 +1,43 @@ package absyn; import env.Env; -import javaslang.collection.List; import javaslang.collection.Tree; import parse.Loc; -import types.*; +import types.BOOL; +import types.Type; +import types.UNIT; import static semantic.SemanticHelper.typeMismatch; -public class ExpIf extends Exp { - - public final Exp test; - public final Exp alt1; - public final Exp alt2; - - public ExpIf(Loc loc, Exp test, Exp alt1, Exp alt2) { - super(loc); - this.test = test; - this.alt1 = alt1; - this.alt2 = alt2; - } - - @Override - public Tree.Node toTree() { - List> children = List.of(test.toTree(), alt1.toTree()); - if (alt2 != null) - children = children.append(alt2.toTree()); - return Tree.of(annotateType("ExpIf: "), children); - } - - @Override - protected Type semantic_(Env env) { - final Type t_test = test.semantic(env); - if (!t_test.is(BOOL.T)) - throw typeMismatch(test.loc, t_test, BOOL.T); - final Type t_alt1 = alt1.semantic(env); - if (alt2 == null) { - if (!t_alt1.is(UNIT.T)) - throw typeMismatch(alt1.loc, t_alt1, UNIT.T); - return UNIT.T; - } - final Type t_alt2 = alt2.semantic(env); - if (t_alt2.is(t_alt1)) - return t_alt1; - if (t_alt1.is(t_alt2)) - return t_alt2; - throw typeMismatch(alt2.loc, t_alt2, t_alt1); - } +public class ExpWhile extends Exp { + + public final Exp test; + public final Exp body; + + + public ExpWhile(Loc loc, Exp test, Exp body) { + super(loc); + this.test = test; + this.body = body; + } + + @Override + public Tree.Node toTree() { + return Tree.of(annotateType("ExpWhile: "), test.toTree(), body.toTree()); + } + + @Override + protected Type semantic_(Env env) { + //Verificando a expressão teste + final Type t_test = test.semantic(env); + if (!t_test.is(BOOL.T)) + throw typeMismatch(test.loc, t_test, BOOL.T); + + env.isWhile.add(new Boolean(true)); + body.semantic(env); + env.isWhile.remove(env.isWhile.size()-1); + + return UNIT.T; + } } diff --git a/src/main/java/absyn/Parameter.java b/src/main/java/absyn/Parameter.java index e8111a6..9e73fc3 100644 --- a/src/main/java/absyn/Parameter.java +++ b/src/main/java/absyn/Parameter.java @@ -1,7 +1,32 @@ package absyn; -/** - * Created by mvosouza on 24/03/17. - */ -public class parameter { +import env.Env; +import javaslang.collection.Tree; +import parse.Loc; +import semantic.SemanticHelper; +import types.Type; + +public class Parameter extends Exp { + + public final String name; + public final String typeName; + + public Parameter(Loc loc, String name, String typeName) { + super(loc); + this.name = name; + this.typeName = typeName; + } + + @Override + public Tree.Node toTree() { + return Tree.of("Parameter", Tree.of(name), Tree.of(typeName)); + } + + @Override + protected Type semantic_(Env env) { + Type t_type = env.tenv.get(typeName); + if (t_type == null) + throw SemanticHelper.undefined(loc, "type", typeName); + return t_type; + } } diff --git a/src/main/java/absyn/Ty.java b/src/main/java/absyn/Ty.java index 7da3412..937f2f5 100644 --- a/src/main/java/absyn/Ty.java +++ b/src/main/java/absyn/Ty.java @@ -2,6 +2,7 @@ import env.Env; import parse.Loc; +import types.Type; public abstract class Ty extends AST { @@ -10,6 +11,6 @@ public Ty(Loc loc) { } // Do semantic analysis of the declaraction - public abstract void semantic(Env env); + public abstract Type semantic(Env env); } diff --git a/src/main/java/absyn/TyName.java b/src/main/java/absyn/TyName.java index 8ed2469..3410c6b 100644 --- a/src/main/java/absyn/TyName.java +++ b/src/main/java/absyn/TyName.java @@ -3,6 +3,9 @@ import env.Env; import javaslang.collection.Tree; import parse.Loc; +import types.Type; + +import static semantic.SemanticHelper.undefined; public class TyName extends Ty { @@ -14,8 +17,11 @@ public TyName(Loc loc, String name) { } @Override - public void semantic(Env env) { - + public Type semantic(Env env) { + Type t = env.tenv.get(name); + if (t == null) + throw undefined(loc,"type",name); + return t; } @Override diff --git a/src/main/java/env/Env.java b/src/main/java/env/Env.java index dcb3547..d9e166b 100644 --- a/src/main/java/env/Env.java +++ b/src/main/java/env/Env.java @@ -2,40 +2,47 @@ import types.*; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + public class Env { - public Table tenv; - public Table venv; - - public Env() { - tenv = new Table(); - put(tenv, "unit", UNIT.T); - put(tenv, "int", INT.T); - put(tenv, "real", REAL.T); - put(tenv, "bool", BOOL.T); - - venv = new Table(); - put(venv, "print_int", new FUNCTION(UNIT.T, INT.T)); - put(venv, "print_real", new FUNCTION(UNIT.T, REAL.T)); - put(venv, "print_unit", new FUNCTION(UNIT.T, UNIT.T)); - put(venv, "print_bool", new FUNCTION(UNIT.T, BOOL.T)); - put(venv, "round", new FUNCTION(INT.T, REAL.T)); - put(venv, "ceil", new FUNCTION(INT.T, REAL.T)); - put(venv, "floor", new FUNCTION(INT.T, REAL.T)); - put(venv, "real", new FUNCTION(REAL.T, INT.T)); - put(venv, "not", new FUNCTION(BOOL.T, BOOL.T)); - } - - @Override - public String toString() { - return "Env{" + - "tenv=" + tenv + - ", venv=" + venv + - '}'; - } - - private static void put(Table table, String name, E value) { - table.put(name.intern(), value); - } + public Table tenv; + public Table venv; + public List isWhile; + + public Env() { + isWhile = new ArrayList<>(); + + tenv = new Table(); + put(tenv, "unit", UNIT.T); + put(tenv, "int", INT.T); + put(tenv, "real", REAL.T); + put(tenv, "bool", BOOL.T); + + venv = new Table(); + put(venv, "print_int", new FUNCTION(UNIT.T, INT.T)); + put(venv, "print_real", new FUNCTION(UNIT.T, REAL.T)); + put(venv, "print_unit", new FUNCTION(UNIT.T, UNIT.T)); + put(venv, "print_bool", new FUNCTION(UNIT.T, BOOL.T)); + put(venv, "round", new FUNCTION(INT.T, REAL.T)); + put(venv, "ceil", new FUNCTION(INT.T, REAL.T)); + put(venv, "floor", new FUNCTION(INT.T, REAL.T)); + put(venv, "real", new FUNCTION(REAL.T, INT.T)); + put(venv, "not", new FUNCTION(BOOL.T, BOOL.T)); + } + + @Override + public String toString() { + return "Env{" + + "tenv=" + tenv + + ", venv=" + venv + + '}'; + } + + private static void put(Table table, String name, E value) { + table.put(name.intern(), value); + } } diff --git a/src/main/java/semantic/SemanticHelper.java b/src/main/java/semantic/SemanticHelper.java index 7009f97..14504cc 100644 --- a/src/main/java/semantic/SemanticHelper.java +++ b/src/main/java/semantic/SemanticHelper.java @@ -7,34 +7,42 @@ public interface SemanticHelper { - static CompilerError typeMismatch(Loc loc, Type found, Type... expected) { - final StringBuilder builder = new StringBuilder(); - final int n = expected.length; - if (n > 0) { - builder.append(expected[0]); - if (n > 1) { - for (int i = 1; i < n - 2; i++) - builder.append(", ").append(expected[i]); - builder.append(" or ").append(expected[n - 1]); - } - } - return new CompilerError(loc, "type mismatch: found %s but expected %s", found, builder); - } - - static CompilerError undefined(Loc loc, String category, String name) { - return new CompilerError(loc, "undefined %s '%s'", category, name); - } - - static CompilerError notAFunction(Loc loc, String name) { - return new CompilerError(loc, "'%s' is not a function", name); - } - - static CompilerError tooFewArguments(Loc loc, String name) { - return new CompilerError(loc, "too few arguments in call to '%s'", name); - } - - static CompilerError tooMuchArguments(Loc loc, String name) { - return new CompilerError(loc, "too much arguments in call to '%s'", name); - } + static CompilerError typeMismatch(Loc loc, Type found, Type... expected) { + final StringBuilder builder = new StringBuilder(); + final int n = expected.length; + if (n > 0) { + builder.append(expected[0]); + if (n > 1) { + for (int i = 1; i < n - 2; i++) + builder.append(", ").append(expected[i]); + builder.append(" or ").append(expected[n - 1]); + } + } + return new CompilerError(loc, "type mismatch: found %s but expected %s", found, builder); + } + + static CompilerError undefined(Loc loc, String category, String name) { + return new CompilerError(loc, "undefined %s '%s'", category, name); + } + + static CompilerError notAFunction(Loc loc, String name) { + return new CompilerError(loc, "'%s' is not a function", name); + } + + static CompilerError tooFewArguments(Loc loc, String name) { + return new CompilerError(loc, "too few arguments in call to '%s'", name); + } + + static CompilerError tooMuchArguments(Loc loc, String name) { + return new CompilerError(loc, "too much arguments in call to '%s'", name); + } + + static CompilerError breakOutWhile(Loc loc) { + return new CompilerError(loc, "break ins't in loop."); + } + + static CompilerError functionTypeMismatch(Loc loc, Type result, Type found) { + return new CompilerError(loc, "function type mismatch: found %s in body but expected %s",found,result); + } } diff --git a/src/main/java/types/NAME.java b/src/main/java/types/NAME.java index 82ad305..733dc1a 100644 --- a/src/main/java/types/NAME.java +++ b/src/main/java/types/NAME.java @@ -1,7 +1,27 @@ package types; -/** - * Created by mvosouza on 20/03/17. - */ -public class NAME { +import javaslang.collection.Tree; + +public class NAME extends Type { + public final String name; + public Type binding; + + public NAME(String name) { + this.name = name; + } + + @Override + public Tree.Node toTree() { + return Tree.of("NAME: " + name); + } + + @Override + public boolean is(Type type) { + return actual().is(type); + } + + @Override + public Type actual() { + return binding.actual(); + } } diff --git a/src/main/java/types/Type.java b/src/main/java/types/Type.java index 0abb24f..aea4373 100644 --- a/src/main/java/types/Type.java +++ b/src/main/java/types/Type.java @@ -9,25 +9,29 @@ public abstract class Type implements ToTree { - @Override - public Node toTree() { - return Tree.of(toString()); - } + @Override + public Node toTree() { + return Tree.of(toString()); + } - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); - } + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } - // Verify if this type can be coerced to the given type. In - // general one type can be coerced to another type if and only if the - // types are the same. - public boolean is(Type type) { - return type == this; - } + public Type actual(){ + return this; + } - // Verify if this type can be coerced to any of the given types. - public boolean is(Type... types) { - return List.of(types).exists(t -> this.is(t)); - } + // Verify if this type can be coerced to the given type. In + // general one type can be coerced to another type if and only if the + // types are the same. + public boolean is(Type type) { + return type.actual() == this; + } + + // Verify if this type can be coerced to any of the given types. + public boolean is(Type... types) { + return List.of(types).exists(t -> this.is(t)); + } } From fbd807ca6ed1009f784beb5fdc715e36a93aaa6c Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Fri, 24 Mar 2017 22:56:49 -0300 Subject: [PATCH 04/20] correction of break command class Env --- src/main/java/absyn/ExpBreak.java | 2 +- src/main/java/absyn/ExpWhile.java | 6 +++--- src/main/java/env/Env.java | 8 ++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/absyn/ExpBreak.java b/src/main/java/absyn/ExpBreak.java index b96460c..b35fcc1 100644 --- a/src/main/java/absyn/ExpBreak.java +++ b/src/main/java/absyn/ExpBreak.java @@ -23,7 +23,7 @@ public Tree.Node toTree() { @Override protected Type semantic_(Env env) { - if (env.isWhile.size() == 0) + if (env.isWhile == false) throw breakOutWhile(loc); return UNIT.T; } diff --git a/src/main/java/absyn/ExpWhile.java b/src/main/java/absyn/ExpWhile.java index 12f4abf..c4d9a0b 100644 --- a/src/main/java/absyn/ExpWhile.java +++ b/src/main/java/absyn/ExpWhile.java @@ -32,10 +32,10 @@ protected Type semantic_(Env env) { final Type t_test = test.semantic(env); if (!t_test.is(BOOL.T)) throw typeMismatch(test.loc, t_test, BOOL.T); - - env.isWhile.add(new Boolean(true)); + boolean localIsWhile = env.isWhile; + env.isWhile = true; body.semantic(env); - env.isWhile.remove(env.isWhile.size()-1); + env.isWhile = localIsWhile; return UNIT.T; } diff --git a/src/main/java/env/Env.java b/src/main/java/env/Env.java index d9e166b..7d6b921 100644 --- a/src/main/java/env/Env.java +++ b/src/main/java/env/Env.java @@ -2,18 +2,14 @@ import types.*; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - public class Env { public Table tenv; public Table venv; - public List isWhile; + public boolean isWhile; public Env() { - isWhile = new ArrayList<>(); + isWhile = false; tenv = new Table(); put(tenv, "unit", UNIT.T); From 065a1e59853888da7bf1a3d26075b22b12fb6991 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Fri, 24 Mar 2017 23:44:51 -0300 Subject: [PATCH 05/20] declarations of functions was added on Eplan language --- src/main/cup/parser.cup | 58 ++++++++++++++++++---- src/main/java/absyn/DecFunctionMutual.java | 2 +- src/main/jflex/lexer.jflex | 2 +- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index f4c00d9..84ffb83 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -53,18 +53,23 @@ terminal IF, THEN, ELSE; terminal TYPE; terminal EQT, NEQ, LT, LE, GT, GE; terminal WHILE, DO, BREAK; - -non terminal Exp program; -non terminal Exp exp; -non terminal List exps, expsRest; -non terminal List expseq, expseqRest; -non terminal DecVar decvar; -non terminal DecType dectype; +terminal FUNCTION; + +non terminal Exp program; +non terminal Exp exp; +non terminal List exps, expsRest; +non terminal List expseq, expseqRest; +non terminal DecVar decvar; +non terminal DecType dectype; +non terminal DecFunction decfunc; non terminal List dectypes; -non terminal List decs; -non terminal List decs_beg_with_variable, decs_beg_with_type; -non terminal Var var; -non terminal Ty ty; +non terminal List decs; +non terminal List decs_beg_with_variable, decs_beg_with_type, decs_beg_with_func; +non terminal Var var; +non terminal Ty ty; +non terminal Parameter parameter; +non terminal List parameters, parametersRest; +non terminal List decfuncs; precedence left OR; @@ -146,17 +151,20 @@ dectypes ::= decs ::= decs_beg_with_variable:ds {: RESULT = ds; :} | decs_beg_with_type:ds {: RESULT = ds; :} +| decs_beg_with_func:ds {: RESULT = ds; :} ; decs_beg_with_variable ::= decvar:d {: RESULT = List.of(d); :} | decvar:d decs_beg_with_variable:ds {: RESULT = ds.prepend(d); :} | decvar:d decs_beg_with_type:ds {: RESULT = ds.prepend(d); :} +| decvar:d decs_beg_with_func:ds {: RESULT = ds.prepend(d); :} ; decs_beg_with_type ::= dectypes:dt {: RESULT = List.of(new DecTypeMutual(loc(dtxleft,dtxright), dt)); :} | dectypes:dt decs_beg_with_variable:ds {: RESULT = ds.prepend(new DecTypeMutual(loc(dtxleft,dtxright), dt)); :} +| dectypes:dt decs_beg_with_func:ds {: RESULT = ds.prepend(new DecTypeMutual(loc(dtxleft,dtxright), dt)); :} ; var ::= @@ -167,4 +175,32 @@ ty ::= ID:id {: RESULT = new TyName(loc(idxleft,idxright), id); :} ; +parameter ::= + ID:n COLON ID:t {: RESULT = new Parameter(loc(nxleft,txright),n,t); :} +; + +parameters ::= + /* empty */ {: RESULT = List.empty(); :} +| parameter:p parametersRest:ps {: RESULT = ps.prepend(p); :} +; + +parametersRest ::= + /* empty */ {: RESULT = List.empty(); :} +| COMMA parameter:p parametersRest:ps {: RESULT = ps.prepend(p); :} +; + +decfunc ::= + FUNCTION:f ID:n LPAREN parameters:p RPAREN COLON ID:t EQ exp:b {: RESULT = new DecFunction(loc(fxleft,bxright),n,p,t,b); :} +| FUNCTION:f ID:n LPAREN parameters:p RPAREN EQ exp:b {: RESULT = new DecFunction(loc(fxleft,bxright),n,p,null,b); :} +; + +decfuncs ::= + decfunc:d {: RESULT = List.of(d); :} +| decfunc:d decfuncs:ds {: RESULT = ds.prepend(d); :} +; +decs_beg_with_func ::= + decfuncs:d {: RESULT = List.of(new DecFunctionMutual(loc(dxleft,dxright), d)); :} +| decfuncs:d decs_beg_with_variable:ds {: RESULT = ds.prepend(new DecFunctionMutual(loc(dxleft,dxright), d)); :} +| decfuncs:d decs_beg_with_type:ds {: RESULT = ds.prepend(new DecFunctionMutual(loc(dxleft,dxright), d)); :} +; \ No newline at end of file diff --git a/src/main/java/absyn/DecFunctionMutual.java b/src/main/java/absyn/DecFunctionMutual.java index f114948..f3e7ff1 100644 --- a/src/main/java/absyn/DecFunctionMutual.java +++ b/src/main/java/absyn/DecFunctionMutual.java @@ -31,7 +31,7 @@ public Type semantic(Env env) { Type t_result = UNIT.T; if (d.typeName != null) { - t_result = env.tenv.get(d.name); + t_result = env.tenv.get(d.typeName); if (t_result == null) { throw SemanticHelper.undefined(d.loc, "type", d.name); } diff --git a/src/main/jflex/lexer.jflex b/src/main/jflex/lexer.jflex index 05cb00a..e7a8d10 100644 --- a/src/main/jflex/lexer.jflex +++ b/src/main/jflex/lexer.jflex @@ -87,7 +87,7 @@ else { return tok(ELSE); } while { return tok(WHILE); } do { return tok(DO); } break { return tok(BREAK); } - +function { return tok(FUNCTION); } {id} { return tok(ID, yytext().intern()); } From ea0f841d661371892a905ab98c723e721415a9b0 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sat, 25 Mar 2017 16:31:49 -0300 Subject: [PATCH 06/20] The ARRAY type was added - but miss the expression (var x = v[2+3]) --- src/main/cup/parser.cup | 53 ++++++++++++---------- src/main/java/absyn/ExpArray.java | 48 ++++++++++++++++++++ src/main/java/absyn/TyArray.java | 35 ++++++++++++++ src/main/java/semantic/SemanticHelper.java | 3 ++ src/main/java/types/ARRAY.java | 15 ++++++ src/main/jflex/lexer.jflex | 5 ++ 6 files changed, 134 insertions(+), 25 deletions(-) create mode 100644 src/main/java/absyn/ExpArray.java create mode 100644 src/main/java/absyn/TyArray.java create mode 100644 src/main/java/types/ARRAY.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index 84ffb83..a6e7002 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -54,6 +54,7 @@ terminal TYPE; terminal EQT, NEQ, LT, LE, GT, GE; terminal WHILE, DO, BREAK; terminal FUNCTION; +terminal LBRACK, RBRACK, AT; non terminal Exp program; non terminal Exp exp; @@ -87,31 +88,32 @@ program ::= ; exp ::= - exp:x PLUS exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.PLUS, x, y); :} -| exp:x MINUS exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.MINUS, x, y); :} -| exp:x TIMES exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.TIMES, x, y); :} -| exp:x DIV exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.DIV, x, y); :} -| exp:x AND exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.AND, x, y); :} -| exp:x OR exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.OR, x, y); :} -| exp:x EQT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.EQT, x, y); :} -| exp:x NEQ exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.NEQ, x, y); :} -| exp:x LT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.LT, x, y); :} -| exp:x LE exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.LE, x, y); :} -| exp:x GT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.GT, x, y); :} -| exp:x GE exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.GE, x, y); :} -| LITINT:x {: RESULT = new ExpInt(loc(xxleft,xxright), x); :} -| LITREAL:x {: RESULT = new ExpReal(loc(xxleft,xxright), x); :} -| LITBOOL:x {: RESULT = new ExpBool(loc(xxleft,xxright), x); :} -| MINUS:m exp:x {: RESULT = new ExpNegate(loc(mxleft,xxright), x); :} %prec UMINUS -| ID:f LPAREN exps:x RPAREN:r {: RESULT = new ExpCall(loc(fxleft,rxright), f, x); :} -| var:v {: RESULT = new ExpVar(loc(vxleft,vxright), v); :} -| var:v ASSIGN exp:e {: RESULT = new ExpAssign(loc(vxleft,exright), v, e); :} -| LET:l decs:ds IN exp:b {: RESULT = new ExpLet(loc(lxleft,bxright), ds, b); :} -| LPAREN:l expseq:es RPAREN:r {: RESULT = new ExpSeq(loc(lxleft,rxright), es); :} -| IF:i exp:t THEN exp:a ELSE exp:b {: RESULT = new ExpIf(loc(ixleft,bxright), t, a, b); :} -| IF:i exp:t THEN exp:a {: RESULT = new ExpIf(loc(ixleft,axright), t, a, null); :} -| WHILE:w exp:t DO exp:b {: RESULT = new ExpWhile(loc(wxleft,bxright), t, b); :} -| BREAK:b {: RESULT = new ExpBreak(loc(bxleft,bxright)); :} + exp:x PLUS exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.PLUS, x, y); :} +| exp:x MINUS exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.MINUS, x, y); :} +| exp:x TIMES exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.TIMES, x, y); :} +| exp:x DIV exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.DIV, x, y); :} +| exp:x AND exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.AND, x, y); :} +| exp:x OR exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.OR, x, y); :} +| exp:x EQT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.EQT, x, y); :} +| exp:x NEQ exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.NEQ, x, y); :} +| exp:x LT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.LT, x, y); :} +| exp:x LE exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.LE, x, y); :} +| exp:x GT exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.GT, x, y); :} +| exp:x GE exp:y {: RESULT = new ExpBinOp(loc(xxleft,yxright), ExpBinOp.Op.GE, x, y); :} +| LITINT:x {: RESULT = new ExpInt(loc(xxleft,xxright), x); :} +| LITREAL:x {: RESULT = new ExpReal(loc(xxleft,xxright), x); :} +| LITBOOL:x {: RESULT = new ExpBool(loc(xxleft,xxright), x); :} +| MINUS:m exp:x {: RESULT = new ExpNegate(loc(mxleft,xxright), x); :} %prec UMINUS +| ID:f LPAREN exps:x RPAREN:r {: RESULT = new ExpCall(loc(fxleft,rxright), f, x); :} +| var:v {: RESULT = new ExpVar(loc(vxleft,vxright), v); :} +| var:v ASSIGN exp:e {: RESULT = new ExpAssign(loc(vxleft,exright), v, e); :} +| LET:l decs:ds IN exp:b {: RESULT = new ExpLet(loc(lxleft,bxright), ds, b); :} +| LPAREN:l expseq:es RPAREN:r {: RESULT = new ExpSeq(loc(lxleft,rxright), es); :} +| IF:i exp:t THEN exp:a ELSE exp:b {: RESULT = new ExpIf(loc(ixleft,bxright), t, a, b); :} +| IF:i exp:t THEN exp:a {: RESULT = new ExpIf(loc(ixleft,axright), t, a, null); :} +| WHILE:w exp:t DO exp:b {: RESULT = new ExpWhile(loc(wxleft,bxright), t, b); :} +| BREAK:b {: RESULT = new ExpBreak(loc(bxleft,bxright)); :} +| AT:a ID:id LBRACK exps:e RBRACK:r {: RESULT = new ExpArray(loc(axleft,rxright),id,e); :} ; exps ::= @@ -173,6 +175,7 @@ var ::= ty ::= ID:id {: RESULT = new TyName(loc(idxleft,idxright), id); :} +| LBRACK:l ID:id RBRACK:r {: RESULT = new TyArray(loc(idxleft,idxright), id); :} ; parameter ::= diff --git a/src/main/java/absyn/ExpArray.java b/src/main/java/absyn/ExpArray.java new file mode 100644 index 0000000..8ec3d97 --- /dev/null +++ b/src/main/java/absyn/ExpArray.java @@ -0,0 +1,48 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import parse.Loc; +import semantic.SemanticHelper; +import types.ARRAY; +import types.Type; + +public class ExpArray extends Exp{ + + public final String typeName; + public final List elements; + + public ExpArray(Loc loc, String typeName, List elements) { + super(loc); + this.typeName = typeName; + this.elements = elements; + } + + @Override + public Tree.Node toTree() { + return Tree.of("ArrayExp",Tree.of(typeName),Tree.of("Elements", elements.map(Exp::toTree))); + } + + @Override + protected Type semantic_(Env env) { + Type t_typeName = env.tenv.get(typeName); + if (t_typeName == null) + throw SemanticHelper.undefined(loc,"type",typeName); + else{ + t_typeName = t_typeName.actual(); + if (!(t_typeName instanceof ARRAY)) + throw SemanticHelper.arrayMismatch(loc,t_typeName); + } + + Type t_elements = ((ARRAY) t_typeName).typeName; + + for (Exp e: elements) { + Type t_aux = e.semantic(env); + if (!t_aux.is(t_elements)) + throw SemanticHelper.typeMismatch(loc,t_aux,t_elements); + } + + return t_typeName; + } +} diff --git a/src/main/java/absyn/TyArray.java b/src/main/java/absyn/TyArray.java new file mode 100644 index 0000000..3ba0d07 --- /dev/null +++ b/src/main/java/absyn/TyArray.java @@ -0,0 +1,35 @@ +package absyn; + +import env.Env; +import javaslang.collection.Tree; +import parse.Loc; +import types.ARRAY; +import types.Type; + +import static semantic.SemanticHelper.undefined; + +public class TyArray extends Ty { + + public final String name; + + public TyArray(Loc loc, String name) { + super(loc); + this.name = name; + } + + @Override + public Tree.Node toTree() { + return Tree.of("TyArray: " + name); + } + + @Override + public Type semantic(Env env) { + Type t = env.tenv.get(name); + if (t == null) + throw undefined(loc, "type", name); + + return new ARRAY(t); + } + + +} diff --git a/src/main/java/semantic/SemanticHelper.java b/src/main/java/semantic/SemanticHelper.java index 14504cc..0b23956 100644 --- a/src/main/java/semantic/SemanticHelper.java +++ b/src/main/java/semantic/SemanticHelper.java @@ -45,4 +45,7 @@ static CompilerError functionTypeMismatch(Loc loc, Type result, Type found) { return new CompilerError(loc, "function type mismatch: found %s in body but expected %s",found,result); } + static CompilerError arrayMismatch(Loc loc, Type found) { + return new CompilerError(loc, "type mismatch: found %s but expected array type",found); + } } diff --git a/src/main/java/types/ARRAY.java b/src/main/java/types/ARRAY.java new file mode 100644 index 0000000..02aa19e --- /dev/null +++ b/src/main/java/types/ARRAY.java @@ -0,0 +1,15 @@ +package types; + +public class ARRAY extends Type { + + public final Type typeName; + + public ARRAY(Type typeName) { + this.typeName = typeName; + } + + @Override + public String toString() { + return "Array of "+ typeName; + } +} diff --git a/src/main/jflex/lexer.jflex b/src/main/jflex/lexer.jflex index e7a8d10..76f8878 100644 --- a/src/main/jflex/lexer.jflex +++ b/src/main/jflex/lexer.jflex @@ -97,8 +97,12 @@ function { return tok(FUNCTION); } "/" { return tok(DIV); } "&&" { return tok(AND); } "||" { return tok(OR); } + "(" { return tok(LPAREN); } ")" { return tok(RPAREN); } +"[" { return tok(LBRACK); } +"]" { return tok(RBRACK); } + "," { return tok(COMMA); } ";" { return tok(SEMICOLON); } ":" { return tok(COLON); } @@ -110,5 +114,6 @@ function { return tok(FUNCTION); } "<=" { return tok(LE); } ">" { return tok(GT); } ">=" { return tok(GE); } +"@" { return tok(AT); } . { throw error(Loc.loc(locLeft()), "unexpected char '%s'", yytext()); } From d424fdeb0c7052726601c24372508077fdaa527d Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sat, 25 Mar 2017 22:47:43 -0300 Subject: [PATCH 07/20] The RECORD type was added - but miss the expression (var x:real = p.x) --- src/main/cup/parser.cup | 23 +++++++- src/main/java/absyn/ExpArray.java | 2 +- src/main/java/absyn/ExpRecord.java | 66 ++++++++++++++++++++++ src/main/java/absyn/ParameterWithExp.java | 29 ++++++++++ src/main/java/absyn/TyRecord.java | 34 +++++++++++ src/main/java/semantic/SemanticHelper.java | 35 +++++++++++- src/main/java/types/RECORD.java | 24 ++++++++ src/main/jflex/lexer.jflex | 2 + 8 files changed, 210 insertions(+), 5 deletions(-) create mode 100644 src/main/java/absyn/ExpRecord.java create mode 100644 src/main/java/absyn/ParameterWithExp.java create mode 100644 src/main/java/absyn/TyRecord.java create mode 100644 src/main/java/types/RECORD.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index a6e7002..f7494d9 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -55,6 +55,7 @@ terminal EQT, NEQ, LT, LE, GT, GE; terminal WHILE, DO, BREAK; terminal FUNCTION; terminal LBRACK, RBRACK, AT; +terminal LBRACE, RBRACE; non terminal Exp program; non terminal Exp exp; @@ -71,6 +72,8 @@ non terminal Ty ty; non terminal Parameter parameter; non terminal List parameters, parametersRest; non terminal List decfuncs; +non terminal ParameterWithExp parameterexp; +non terminal List parameterexps, parameterexpsRest; precedence left OR; @@ -114,6 +117,7 @@ exp ::= | WHILE:w exp:t DO exp:b {: RESULT = new ExpWhile(loc(wxleft,bxright), t, b); :} | BREAK:b {: RESULT = new ExpBreak(loc(bxleft,bxright)); :} | AT:a ID:id LBRACK exps:e RBRACK:r {: RESULT = new ExpArray(loc(axleft,rxright),id,e); :} +| AT:a ID:id LBRACE parameterexps:f RBRACE:r{: RESULT = new ExpRecord(loc(axleft,rxright),id,f); :} ; exps ::= @@ -174,8 +178,9 @@ var ::= ; ty ::= - ID:id {: RESULT = new TyName(loc(idxleft,idxright), id); :} -| LBRACK:l ID:id RBRACK:r {: RESULT = new TyArray(loc(idxleft,idxright), id); :} + ID:id {: RESULT = new TyName(loc(idxleft,idxright), id); :} +| LBRACK:l ID:id RBRACK:r {: RESULT = new TyArray(loc(idxleft,idxright), id); :} +| LBRACE:l parameters:p RBRACE:r {: RESULT = new TyRecord(loc(lxleft,rxright), p); :} ; parameter ::= @@ -192,6 +197,20 @@ parametersRest ::= | COMMA parameter:p parametersRest:ps {: RESULT = ps.prepend(p); :} ; +parameterexp ::= + ID:n EQ exp:e {: RESULT = new ParameterWithExp(loc(nxleft,exright),n,e); :} +; + +parameterexps ::= + /* empty */ {: RESULT = List.empty(); :} +| parameterexp:p parameterexpsRest:ps {: RESULT = ps.prepend(p); :} +; + +parameterexpsRest ::= + /* empty */ {: RESULT = List.empty(); :} +| COMMA parameterexp:p parameterexpsRest:ps {: RESULT = ps.prepend(p); :} +; + decfunc ::= FUNCTION:f ID:n LPAREN parameters:p RPAREN COLON ID:t EQ exp:b {: RESULT = new DecFunction(loc(fxleft,bxright),n,p,t,b); :} | FUNCTION:f ID:n LPAREN parameters:p RPAREN EQ exp:b {: RESULT = new DecFunction(loc(fxleft,bxright),n,p,null,b); :} diff --git a/src/main/java/absyn/ExpArray.java b/src/main/java/absyn/ExpArray.java index 8ec3d97..88fa986 100644 --- a/src/main/java/absyn/ExpArray.java +++ b/src/main/java/absyn/ExpArray.java @@ -21,7 +21,7 @@ public ExpArray(Loc loc, String typeName, List elements) { @Override public Tree.Node toTree() { - return Tree.of("ArrayExp",Tree.of(typeName),Tree.of("Elements", elements.map(Exp::toTree))); + return Tree.of("ExpArray",Tree.of(typeName),Tree.of("Elements", elements.map(Exp::toTree))); } @Override diff --git a/src/main/java/absyn/ExpRecord.java b/src/main/java/absyn/ExpRecord.java new file mode 100644 index 0000000..97c0025 --- /dev/null +++ b/src/main/java/absyn/ExpRecord.java @@ -0,0 +1,66 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import javaslang.control.Option; +import parse.Loc; +import semantic.SemanticHelper; +import types.RECORD; +import types.Type; + +public class ExpRecord extends Exp{ + + public final String typeName; + public final List elements; + + public ExpRecord(Loc loc, String typeName, List elements) { + super(loc); + this.typeName = typeName; + this.elements = elements; + } + + @Override + public Tree.Node toTree() { + return Tree.of("ExpRecord",Tree.of(typeName),Tree.of("Elements", elements.map(ParameterWithExp::toTree))); + } + + @Override + protected Type semantic_(Env env) { + Type t_typeName = env.tenv.get(typeName); + if (t_typeName == null) + throw SemanticHelper.undefined(loc,"type",typeName); + else { + t_typeName = t_typeName.actual(); + if (!(t_typeName instanceof RECORD)) + throw SemanticHelper.recordMismatch(loc,t_typeName); + } + + List t_parameters = ((RECORD) t_typeName).elements; + //Lista para verificar a duplicidade entre variaveis + List verify = List.empty(); + + for (ParameterWithExp parameterWithExp: elements ) { + Type t_parameterWithExp = parameterWithExp.semantic_(env); + + if (verify.contains(parameterWithExp.name)) + throw SemanticHelper.duplicatedParameter(loc,parameterWithExp.name); + else{ + Option t_p = t_parameters.find(p -> p.name == parameterWithExp.name); + if (t_p.isEmpty()) + throw SemanticHelper.unknownRecordParameter(loc,parameterWithExp.name); + else{ + Type t_aux = t_p.get().semantic_(env); + if (!t_parameterWithExp.is(t_aux)) + throw SemanticHelper.recordTypeMismatch(loc, parameterWithExp.name, t_aux, t_parameterWithExp); + t_parameters = t_parameters.remove(t_p.get()); + } + verify = verify.prepend(parameterWithExp.name); + } + } + if (! t_parameters.isEmpty()) + throw SemanticHelper.missingParametersRecord(loc, t_parameters.map(p -> p.name)); + + return t_typeName; + } +} diff --git a/src/main/java/absyn/ParameterWithExp.java b/src/main/java/absyn/ParameterWithExp.java new file mode 100644 index 0000000..5b89836 --- /dev/null +++ b/src/main/java/absyn/ParameterWithExp.java @@ -0,0 +1,29 @@ +package absyn; + +import env.Env; +import javaslang.collection.Tree; +import parse.Loc; +import semantic.SemanticHelper; +import types.Type; + +public class ParameterWithExp extends Exp { + + public final String name; + public final Exp body; + + public ParameterWithExp(Loc loc, String name, Exp body) { + super(loc); + this.name = name; + this.body = body; + } + + @Override + public Tree.Node toTree() { + return Tree.of("Parameter", Tree.of(name), body.toTree()); + } + + @Override + protected Type semantic_(Env env) { + return body.semantic(env); + } +} diff --git a/src/main/java/absyn/TyRecord.java b/src/main/java/absyn/TyRecord.java new file mode 100644 index 0000000..2407f03 --- /dev/null +++ b/src/main/java/absyn/TyRecord.java @@ -0,0 +1,34 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import parse.Loc; +import types.ARRAY; +import types.RECORD; +import types.Type; + +import static semantic.SemanticHelper.undefined; + +public class TyRecord extends Ty { + + public final List elements; + + public TyRecord(Loc loc, List elements) { + super(loc); + this.elements = elements; + } + + @Override + public Tree.Node toTree() { + return Tree.of("TyRecord: ",elements.map(Parameter::toTree)); + } + + @Override + public Type semantic(Env env) { + List t_elements = elements.map(parameter -> parameter.semantic_(env)); + return new RECORD(elements); + } + + +} diff --git a/src/main/java/semantic/SemanticHelper.java b/src/main/java/semantic/SemanticHelper.java index 0b23956..e2dbc56 100644 --- a/src/main/java/semantic/SemanticHelper.java +++ b/src/main/java/semantic/SemanticHelper.java @@ -2,6 +2,7 @@ import error.CompilerError; +import javaslang.collection.List; import parse.Loc; import types.Type; @@ -42,10 +43,40 @@ static CompilerError breakOutWhile(Loc loc) { } static CompilerError functionTypeMismatch(Loc loc, Type result, Type found) { - return new CompilerError(loc, "function type mismatch: found %s in body but expected %s",found,result); + return new CompilerError(loc, "function type mismatch: found %s in body but expected %s", found, result); } static CompilerError arrayMismatch(Loc loc, Type found) { - return new CompilerError(loc, "type mismatch: found %s but expected array type",found); + return new CompilerError(loc, "type mismatch: found %s but expected array type", found); + } + + static CompilerError recordMismatch(Loc loc, Type found) { + return new CompilerError(loc, "type mismatch: found %s but expected record type", found); + } + + static CompilerError duplicatedParameter(Loc loc, String parameter) { + return new CompilerError(loc, "parameter %s is duplicated", parameter); + } + + static CompilerError unknownRecordParameter(Loc loc, String parameter) { + return new CompilerError(loc, "record parameter %s is unknown", parameter); + } + + static CompilerError recordTypeMismatch(Loc loc, String name, Type found, Type... expected) { + final StringBuilder builder = new StringBuilder(); + final int n = expected.length; + if (n > 0) { + builder.append(expected[0]); + if (n > 1) { + for (int i = 1; i < n - 2; i++) + builder.append(", ").append(expected[i]); + builder.append(" or ").append(expected[n - 1]); + } + } + return new CompilerError(loc, "type mismatch in record parameter %s: found %s but expected %S", name, found, builder); + } + + static CompilerError missingParametersRecord(Loc loc, List s) { + return new CompilerError(loc, "missing parameters %s in record", s.toString()); } } diff --git a/src/main/java/types/RECORD.java b/src/main/java/types/RECORD.java new file mode 100644 index 0000000..c426666 --- /dev/null +++ b/src/main/java/types/RECORD.java @@ -0,0 +1,24 @@ +package types; + +import absyn.Parameter; +import javaslang.collection.List; +import javaslang.collection.Tree; + +public class RECORD extends Type { + + public final List elements; + + public RECORD(List elements) { + this.elements = elements; + } + + @Override + public String toString() { + return "RECORD [" + elements + "]"; + } + + @Override + public Tree.Node toTree() { + return Tree.of("RECORD", elements.map(Parameter::toTree)); + } +} diff --git a/src/main/jflex/lexer.jflex b/src/main/jflex/lexer.jflex index 76f8878..ef2d120 100644 --- a/src/main/jflex/lexer.jflex +++ b/src/main/jflex/lexer.jflex @@ -102,6 +102,8 @@ function { return tok(FUNCTION); } ")" { return tok(RPAREN); } "[" { return tok(LBRACK); } "]" { return tok(RBRACK); } +"{" { return tok(LBRACE); } +"}" { return tok(RBRACE); } "," { return tok(COMMA); } ";" { return tok(SEMICOLON); } From 9bb1c6f77c8d16eec3143264d3f0d6bdc7897043 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sun, 26 Mar 2017 00:12:52 -0300 Subject: [PATCH 08/20] added the expression and semantics of RECORD assignment --- src/main/cup/parser.cup | 22 ++++++-- src/main/java/absyn/DecVarRecord.java | 72 +++++++++++++++++++++++++++ src/main/jflex/lexer.jflex | 1 + 3 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 src/main/java/absyn/DecVarRecord.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index f7494d9..616dcb8 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -56,6 +56,7 @@ terminal WHILE, DO, BREAK; terminal FUNCTION; terminal LBRACK, RBRACK, AT; terminal LBRACE, RBRACE; +terminal DOT; non terminal Exp program; non terminal Exp exp; @@ -74,7 +75,8 @@ non terminal List parameters, parametersRest; non terminal List decfuncs; non terminal ParameterWithExp parameterexp; non terminal List parameterexps, parameterexpsRest; - +non terminal Dec decsvar; +non terminal DecVarRecord decvarrecord; precedence left OR; precedence left AND; @@ -145,6 +147,16 @@ decvar ::= | VAR:v ID:x EQ exp:e {: RESULT = new DecVar(loc(vxleft,exright), x, null, e); :} ; +decvarrecord ::= + VAR:v ID:x COLON ID:t EQ ID:bv DOT ID:br {: RESULT = new DecVarRecord(loc(vxleft,brxright),x,t,bv,br); :} +| VAR:v ID:x EQ ID:bv DOT ID:br {: RESULT = new DecVarRecord(loc(vxleft,brxright),x,null,bv,br); :} +; + +decsvar ::= + decvar:d {: RESULT = d; :} +| decvarrecord:d {: RESULT = d; :} +; + dectype ::= TYPE:t ID:id EQ ty:ty {: RESULT = new DecType(loc(txleft,tyxright), id,ty); :} ; @@ -161,10 +173,10 @@ decs ::= ; decs_beg_with_variable ::= - decvar:d {: RESULT = List.of(d); :} -| decvar:d decs_beg_with_variable:ds {: RESULT = ds.prepend(d); :} -| decvar:d decs_beg_with_type:ds {: RESULT = ds.prepend(d); :} -| decvar:d decs_beg_with_func:ds {: RESULT = ds.prepend(d); :} + decsvar:d {: RESULT = List.of(d); :} +| decsvar:d decs_beg_with_variable:ds {: RESULT = ds.prepend(d); :} +| decsvar:d decs_beg_with_type:ds {: RESULT = ds.prepend(d); :} +| decsvar:d decs_beg_with_func:ds {: RESULT = ds.prepend(d); :} ; decs_beg_with_type ::= diff --git a/src/main/java/absyn/DecVarRecord.java b/src/main/java/absyn/DecVarRecord.java new file mode 100644 index 0000000..3e41ada --- /dev/null +++ b/src/main/java/absyn/DecVarRecord.java @@ -0,0 +1,72 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import javaslang.control.Option; +import parse.Loc; +import semantic.SemanticHelper; +import types.RECORD; +import types.Type; + +public class DecVarRecord extends Dec { + + public final String name; + public final String typeName; + public final String bodyVarName; + public final String bodyRegisterName; + + public DecVarRecord(Loc loc, String name, String typeName, String bodyVarName, String bodyRegisterName) { + super(loc); + this.name = name; + this.typeName = typeName; + this.bodyVarName = bodyVarName; + this.bodyRegisterName = bodyRegisterName; + } + + @Override + public Tree.Node toTree() { + return Tree.of("DecVarRecord", + (typeName != null)? Tree.of(name, + Tree.of(typeName)):Tree.of(name), + Tree.of(bodyVarName, + Tree.of(bodyRegisterName))); + } + + @Override + public Type semantic(Env env) { + if (typeName != null) { + Type t_typeName = env.tenv.get(typeName); + + if (t_typeName == null) + throw SemanticHelper.undefined(loc, "type", typeName); + else { + Type t_bodyVar = env.venv.get(bodyVarName); + t_bodyVar = t_bodyVar.actual(); + + List t_bodyParams = ((RECORD) t_bodyVar).elements; + Option t_p = t_bodyParams.find(p -> p.name == bodyRegisterName); + if (t_p.isEmpty()) + throw SemanticHelper.unknownRecordParameter(loc, bodyRegisterName); + else { + Type t_aux = t_p.get().semantic_(env); + if (!t_aux.is(t_typeName)) + throw SemanticHelper.typeMismatch(loc, t_typeName, t_aux); + } + } + env.venv.put(name, t_typeName); + return t_typeName; + } + else{ + Type t_bodyVar = env.venv.get(bodyVarName); + t_bodyVar = t_bodyVar.actual(); + + List t_bodyParams = ((RECORD) t_bodyVar).elements; + Option t_p = t_bodyParams.find(p -> p.name == bodyRegisterName); + if (t_p.isEmpty()) + throw SemanticHelper.unknownRecordParameter(loc, bodyRegisterName); + return t_p.get().semantic_(env); + } + + } +} diff --git a/src/main/jflex/lexer.jflex b/src/main/jflex/lexer.jflex index ef2d120..3b07801 100644 --- a/src/main/jflex/lexer.jflex +++ b/src/main/jflex/lexer.jflex @@ -108,6 +108,7 @@ function { return tok(FUNCTION); } "," { return tok(COMMA); } ";" { return tok(SEMICOLON); } ":" { return tok(COLON); } +"." { return tok(DOT); } "=" { return tok(EQ); } ":=" { return tok(ASSIGN); } "==" { return tok(EQT); } From 9fb9d55feb8da06a78835a601ad6b69a43cbd079 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sun, 26 Mar 2017 00:16:54 -0300 Subject: [PATCH 09/20] correction of DecVarRecord file --- src/main/java/absyn/DecVarRecord.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/absyn/DecVarRecord.java b/src/main/java/absyn/DecVarRecord.java index 3e41ada..c28599f 100644 --- a/src/main/java/absyn/DecVarRecord.java +++ b/src/main/java/absyn/DecVarRecord.java @@ -65,7 +65,10 @@ public Type semantic(Env env) { Option t_p = t_bodyParams.find(p -> p.name == bodyRegisterName); if (t_p.isEmpty()) throw SemanticHelper.unknownRecordParameter(loc, bodyRegisterName); - return t_p.get().semantic_(env); + + Type t_aux = t_p.get().semantic_(env); + env.venv.put(name, t_aux); + return t_aux; } } From e4b32ae8583c8893cc186e3d5df788450d1175b6 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sun, 26 Mar 2017 01:05:50 -0300 Subject: [PATCH 10/20] added the expression and semantics of ARRAY assignment --- src/main/cup/parser.cup | 7 +++ src/main/java/absyn/DecVarArray.java | 66 +++++++++++++++++++++++++++ src/main/java/absyn/DecVarRecord.java | 13 +++--- 3 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 src/main/java/absyn/DecVarArray.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index 616dcb8..f379837 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -76,6 +76,7 @@ non terminal List decfuncs; non terminal ParameterWithExp parameterexp; non terminal List parameterexps, parameterexpsRest; non terminal Dec decsvar; +non terminal DecVarArray devvararray; non terminal DecVarRecord decvarrecord; precedence left OR; @@ -152,8 +153,14 @@ decvarrecord ::= | VAR:v ID:x EQ ID:bv DOT ID:br {: RESULT = new DecVarRecord(loc(vxleft,brxright),x,null,bv,br); :} ; +devvararray ::= + VAR:v ID:x COLON ID:t EQ ID:bv LBRACK exp:e RBRACK:r {: RESULT = new DecVarArray(loc(vxleft,rxright),x,t,bv,e); :} +| VAR:v ID:x EQ ID:bv LBRACK exp:e RBRACK:r {: RESULT = new DecVarArray(loc(vxleft,rxright),x,null,bv,e); :} +; + decsvar ::= decvar:d {: RESULT = d; :} +| devvararray:d {: RESULT = d; :} | decvarrecord:d {: RESULT = d; :} ; diff --git a/src/main/java/absyn/DecVarArray.java b/src/main/java/absyn/DecVarArray.java new file mode 100644 index 0000000..df074ba --- /dev/null +++ b/src/main/java/absyn/DecVarArray.java @@ -0,0 +1,66 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import javaslang.control.Option; +import parse.Loc; +import semantic.SemanticHelper; +import types.ARRAY; +import types.INT; +import types.RECORD; +import types.Type; + +public class DecVarArray extends Dec { + + public final String name; + public final String typeName; + public final String arrayName; + public final Exp init; + + public DecVarArray(Loc loc, String name, String typeName, String arrayName, Exp init) { + super(loc); + this.name = name; + this.typeName = typeName; + this.arrayName = arrayName; + this.init = init; + } + + @Override + public Tree.Node toTree() { + return Tree.of("DecVarArray", + (typeName != null)? Tree.of(name, + Tree.of(typeName)):Tree.of(name), + Tree.of(arrayName), + init.toTree()); + } + + @Override + public Type semantic(Env env) { + Type t_init = init.semantic(env); + if (!t_init.is(INT.T)) + throw SemanticHelper.typeMismatch(init.loc,t_init, INT.T); + + Type t_typeName; + if (typeName != null){ + t_typeName = env.tenv.get(typeName); + if (t_typeName == null) + throw SemanticHelper.undefined(loc, "type", typeName); + else{ + Type t_array = env.venv.get(arrayName); + t_array = t_array.actual(); + t_array = ((ARRAY)t_array).typeName; + if (!t_array.is(t_typeName)) + throw SemanticHelper.typeMismatch(loc, t_typeName, t_array); + } + } + else{ + Type t_array = env.venv.get(arrayName); + t_array = t_array.actual(); + t_array = ((ARRAY)t_array).typeName; + t_typeName = t_array; + } + env.venv.put(name, t_typeName); + return t_typeName; + } +} diff --git a/src/main/java/absyn/DecVarRecord.java b/src/main/java/absyn/DecVarRecord.java index c28599f..c994c71 100644 --- a/src/main/java/absyn/DecVarRecord.java +++ b/src/main/java/absyn/DecVarRecord.java @@ -35,8 +35,9 @@ public Tree.Node toTree() { @Override public Type semantic(Env env) { + Type t_typeName; if (typeName != null) { - Type t_typeName = env.tenv.get(typeName); + t_typeName = env.tenv.get(typeName); if (t_typeName == null) throw SemanticHelper.undefined(loc, "type", typeName); @@ -54,8 +55,7 @@ public Type semantic(Env env) { throw SemanticHelper.typeMismatch(loc, t_typeName, t_aux); } } - env.venv.put(name, t_typeName); - return t_typeName; + } else{ Type t_bodyVar = env.venv.get(bodyVarName); @@ -66,10 +66,9 @@ public Type semantic(Env env) { if (t_p.isEmpty()) throw SemanticHelper.unknownRecordParameter(loc, bodyRegisterName); - Type t_aux = t_p.get().semantic_(env); - env.venv.put(name, t_aux); - return t_aux; + t_typeName = t_p.get().semantic_(env); } - + env.venv.put(name, t_typeName); + return t_typeName; } } From ad0d801ed9f513978b2fd44afff2e941085ed7b1 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sun, 26 Mar 2017 01:21:18 -0300 Subject: [PATCH 11/20] Corrections on SemanticHelper --- src/main/java/semantic/SemanticHelper.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/semantic/SemanticHelper.java b/src/main/java/semantic/SemanticHelper.java index e2dbc56..c4f80ab 100644 --- a/src/main/java/semantic/SemanticHelper.java +++ b/src/main/java/semantic/SemanticHelper.java @@ -76,7 +76,16 @@ static CompilerError recordTypeMismatch(Loc loc, String name, Type found, Type.. return new CompilerError(loc, "type mismatch in record parameter %s: found %s but expected %S", name, found, builder); } - static CompilerError missingParametersRecord(Loc loc, List s) { - return new CompilerError(loc, "missing parameters %s in record", s.toString()); + static CompilerError missingParametersRecord(Loc loc, List list) { + final StringBuilder builder = new StringBuilder(); + final int n = list.size(); + if (n > 0) { + builder.append(list.get()); + if (n > 1) { + for (int i = 1; i < n; i++) + builder.append(", ").append(list.get(i)); + } + } + return new CompilerError(loc, "missing parameters %s in record", builder); } } From f302f0991d415e49a87e108c080b97575c3eeab5 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Sun, 26 Mar 2017 01:33:09 -0300 Subject: [PATCH 12/20] Corrections on ExpRecord --- src/main/java/absyn/ExpRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/absyn/ExpRecord.java b/src/main/java/absyn/ExpRecord.java index 97c0025..37c43ba 100644 --- a/src/main/java/absyn/ExpRecord.java +++ b/src/main/java/absyn/ExpRecord.java @@ -52,7 +52,7 @@ protected Type semantic_(Env env) { else{ Type t_aux = t_p.get().semantic_(env); if (!t_parameterWithExp.is(t_aux)) - throw SemanticHelper.recordTypeMismatch(loc, parameterWithExp.name, t_aux, t_parameterWithExp); + throw SemanticHelper.recordTypeMismatch(loc, parameterWithExp.name, t_parameterWithExp, t_aux); t_parameters = t_parameters.remove(t_p.get()); } verify = verify.prepend(parameterWithExp.name); From 3d831d6e6fe6479b466cfed78153f99c7451e097 Mon Sep 17 00:00:00 2001 From: jotapeter Date: Sun, 26 Mar 2017 17:30:28 -0300 Subject: [PATCH 13/20] =?UTF-8?q?test=20modificado=20at=C3=A9=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/Test/SemantTest.java | 67 ++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/test/java/Test/SemantTest.java b/src/test/java/Test/SemantTest.java index 9b17199..180dbf7 100644 --- a/src/test/java/Test/SemantTest.java +++ b/src/test/java/Test/SemantTest.java @@ -113,4 +113,71 @@ public void testIf() throws Exception { "error.CompilerError: 1/14-1/17 type mismatch: found real but expected unit"); } + @Test + public void testBooleanArguments() throws Exception { + trun("2 == 2", BOOL.T); + trun("2 > 2", BOOL.T); + trun("2 < 2", BOOL.T); + trun("2 >= 2", BOOL.T); + trun("2 <= 2", BOOL.T); + trun("2 != 2", BOOL.T); + erun("2 => 2", "error.CompilerError: 1/3-1/4 Syntax error at '='"); + erun("2 =< 2", "error.CompilerError: 1/3-1/4 Syntax error at '='"); + erun("2 =! 2", "error.CompilerError: 1/3-1/4 Syntax error at '='"); + erun("2 == test", "error.CompilerError: 1/6-1/10 undefined variable 'test'"); + } + + @Test + public void testWhile() throws Exception { + trun("while true do 1", UNIT.T); + trun("while false do 1", UNIT.T); + trun("while 2 == 2 do 1", UNIT.T); + trun("while 2 > 2 do print_int(2)", UNIT.T); + trun("while 2 > 2 do let var x = 2 in x", UNIT.T); + trun("let var x = 2 var y = 2 in while x > y do print_int(x)", UNIT.T); + erun("while 2 do 1", "error.CompilerError: 1/7-1/8 type mismatch: found int but expected bool"); + erun("while print_int(2) do print_int(2)", "error.CompilerError: 1/7-1/19 type mismatch: found unit but expected bool"); + } + + @Test + public void testBreak() throws Exception { + trun("while true do break", UNIT.T); + trun("while true do let var x = 2 in break", UNIT.T); + erun("let var x = 2 in break", "error.CompilerError: 1/18-1/23 break ins't in loop."); + erun("break", "error.CompilerError: 1/1-1/6 break ins't in loop."); + erun("while true do let var x = 2 break in break", "error.CompilerError: 1/29-1/34 Syntax error at 'break'"); + } + + @Test + public void testFunction() throws Exception { + trun("let function teste(x:int):int = x in teste(2)", INT.T); + trun("let function teste(x:real):real = x in teste(2.2)", REAL.T); + trun("let function teste(x:bool):bool = x in teste(true)", BOOL.T); + trun("let function teste(x:unit):unit = x in teste(())", UNIT.T); + trun("let function teste(x:unit, y:unit):unit = x in teste((),())", UNIT.T); + trun("let function teste(x:int, y:int):int = x in teste(2 , 2)", INT.T); + trun("let function teste(x:real, y:real):real = x in teste(2.2 , 2.2)", REAL.T); + erun("let function teste(x:int):int = x in teste(2.2)", "error.CompilerError: 1/44-1/47 type mismatch: found real but expected int"); + erun("let function teste(x:int):real = x in teste(2)", "error.CompilerError: 1/5-1/35 function type mismatch: found int in body but expected real"); + erun("let function teste(x:real):int = x in teste(2)", "error.CompilerError: 1/5-1/35 function type mismatch: found real in body but expected int"); + erun("let function teste(x:int):int = x in teste(())", "error.CompilerError: 1/44-1/46 type mismatch: found unit but expected int"); + erun("let function teste(x:unit):unit = x in teste()", "error.CompilerError: 1/40-1/47 too few arguments in call to 'teste'"); + erun("let function teste(x:unit):unit = x in teste(2)", "error.CompilerError: 1/46-1/47 type mismatch: found int but expected unit"); + erun("let function teste(x:unit):int = x in teste(2)", "error.CompilerError: 1/5-1/35 function type mismatch: found unit in body but expected int"); + erun("let function teste(x:unit):int = x in teste(2.2)", "error.CompilerError: 1/5-1/35 function type mismatch: found unit in body but expected int"); + erun("let function teste(x:real):real = x in teste(2)", "error.CompilerError: 1/46-1/47 type mismatch: found int but expected real"); + erun("let function teste(x:real):real = x in teste(())", "error.CompilerError: 1/46-1/48 type mismatch: found unit but expected real"); + erun("let function teste(x:real):unit = x in teste(())", "error.CompilerError: 1/5-1/36 function type mismatch: found real in body but expected unit"); + erun("let function teste(x:unit):real = x in teste(())", "error.CompilerError: 1/5-1/36 function type mismatch: found unit in body but expected real"); + erun("let function teste(x:unit):real = x in teste(2.2)", "error.CompilerError: 1/5-1/36 function type mismatch: found unit in body but expected real"); + erun("let function teste(x:real, y:real):int = x in teste(2.2, 2.2)", "error.CompilerError: 1/5-1/43 function type mismatch: found real in body but expected int"); + erun("let function teste(x:real, y:real):real = x in teste(2.2, 2)", "error.CompilerError: 1/59-1/60 type mismatch: found int but expected real"); + erun("let function teste(x:real, y:real):real = x in teste(2, 2)", "error.CompilerError: 1/54-1/55 type mismatch: found int but expected real"); + erun("let function teste(x:unit, y:real):real = x in teste((), 2)", "error.CompilerError: 1/5-1/44 function type mismatch: found unit in body but expected real"); + } + + @Test + public void testArray() throws Exception { + + } } From 1400c1223288c581c3834379f5cc4409d200add2 Mon Sep 17 00:00:00 2001 From: jotapeter Date: Sun, 26 Mar 2017 18:11:25 -0300 Subject: [PATCH 14/20] =?UTF-8?q?test=20modificado=20at=C3=A9=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/Test/SemantTest.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/test/java/Test/SemantTest.java b/src/test/java/Test/SemantTest.java index 180dbf7..0ba0e11 100644 --- a/src/test/java/Test/SemantTest.java +++ b/src/test/java/Test/SemantTest.java @@ -178,6 +178,30 @@ public void testFunction() throws Exception { @Test public void testArray() throws Exception { + trun("let type t = [int] var v:t = @t[10,20,30] var x:int = v[1] var y:int = v[x] in x", INT.T); + trun("let type t = [int] var v:t = @t[10,20,30] var x :int= v[2+3] in 2", INT.T); + trun("let type t = [int] var v:t = @t[10,20,30] var x :int= v[2+3] in x", INT.T); + trun("let type t = [int] var v:t = @t[10,20] var x:int = v[2] in x", INT.T); + trun("let type t = [real] var v:t = @t[10.0,20.0] var x:real = v[2] in x", REAL.T); + trun("let type t = [unit] var v:t = @t[()] var x:unit = v[2] in x", UNIT.T); + erun("let type t = [unit] var v:t = @t[(),1] var x:unit = v[2] in x", "error.CompilerError: 1/31-1/39 type mismatch: found int but expected unit"); + erun("let type t = [real] var v:t = @t[10.0,20.0] var x:int = v[2] in x", "error.CompilerError: 1/45-1/61 type mismatch: found int but expected real"); + erun("let type t = [real] var v:t = @t[10.0,20.0] var x:real = v[2.0] in x", "error.CompilerError: 1/60-1/63 type mismatch: found real but expected int"); + erun("let type t = [int] var v:t = @t[10,20,()] var x :int= v[2+3] in 2", "error.CompilerError: 1/30-1/42 type mismatch: found unit but expected int"); + erun("let type t = [int] var v:t = @t[10,20,30] var x:int = v[y] var y:int = v[1] in x", "error.CompilerError: 1/57-1/58 undefined variable 'y'"); + } + @Test + public void testRegisters() throws Exception { + trun("let type ponto = {x:real, y:int} var p:ponto = @ponto{x=2.3,y=8} var x : int = p.y in x", INT.T); + trun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : real = p.x in 2", INT.T); + trun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : real = p.x in x", REAL.T); + trun("let type ponto = {x:int, y:int} var p:ponto = @ponto{x=2,y=0} var x : int = p.x in 2", INT.T); + trun("let type ponto = {x:unit, y:unit} var p:ponto = @ponto{x=(),y=()} var x : unit = p.x in 2", INT.T); + trun("let type ponto = {x:unit, y:unit} var p:ponto = @ponto{x=(),y=()} var x : unit = p.x in ()", UNIT.T); + trun("let type ponto = {x:unit, y:unit} var p:ponto = @ponto{x=(),y=()} var x : unit = p.x in x", UNIT.T); + erun("let type ponto = {x:int, y:int} var p:ponto = @ponto{x=2,y=0} var x : real = p.x in 2", "error.CompilerError: 1/63-1/81 type mismatch: found real but expected int"); + erun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : int = p.x in ()", "error.CompilerError: 1/69-1/86 type mismatch: found int but expected real"); + erun("let type ponto = {x:real, y:int} var p:ponto = @ponto{x=2.3,y=8} var x : real = p.y in x", "error.CompilerError: 1/66-1/84 type mismatch: found real but expected int"); } } From 550d0d9d222e9f2d8a31b5e7e30c877c6035d121 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Mon, 27 Mar 2017 15:02:43 -0300 Subject: [PATCH 15/20] Correction of ARRAYs type --- src/main/cup/parser.cup | 7 +-- src/main/java/absyn/DecVarArray.java | 66 --------------------------- src/main/java/absyn/VarSubscript.java | 47 +++++++++++++++++++ 3 files changed, 48 insertions(+), 72 deletions(-) delete mode 100644 src/main/java/absyn/DecVarArray.java create mode 100644 src/main/java/absyn/VarSubscript.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index f379837..7534e08 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -76,7 +76,6 @@ non terminal List decfuncs; non terminal ParameterWithExp parameterexp; non terminal List parameterexps, parameterexpsRest; non terminal Dec decsvar; -non terminal DecVarArray devvararray; non terminal DecVarRecord decvarrecord; precedence left OR; @@ -153,14 +152,9 @@ decvarrecord ::= | VAR:v ID:x EQ ID:bv DOT ID:br {: RESULT = new DecVarRecord(loc(vxleft,brxright),x,null,bv,br); :} ; -devvararray ::= - VAR:v ID:x COLON ID:t EQ ID:bv LBRACK exp:e RBRACK:r {: RESULT = new DecVarArray(loc(vxleft,rxright),x,t,bv,e); :} -| VAR:v ID:x EQ ID:bv LBRACK exp:e RBRACK:r {: RESULT = new DecVarArray(loc(vxleft,rxright),x,null,bv,e); :} -; decsvar ::= decvar:d {: RESULT = d; :} -| devvararray:d {: RESULT = d; :} | decvarrecord:d {: RESULT = d; :} ; @@ -194,6 +188,7 @@ decs_beg_with_type ::= var ::= ID:v {: RESULT = new VarSimple(loc(vxleft,vxright), v); :} +| var:x LBRACK exp:e RBRACK:r {: RESULT = new VarSubscript(loc(xxleft,rxright), x, e); :} ; ty ::= diff --git a/src/main/java/absyn/DecVarArray.java b/src/main/java/absyn/DecVarArray.java deleted file mode 100644 index df074ba..0000000 --- a/src/main/java/absyn/DecVarArray.java +++ /dev/null @@ -1,66 +0,0 @@ -package absyn; - -import env.Env; -import javaslang.collection.List; -import javaslang.collection.Tree; -import javaslang.control.Option; -import parse.Loc; -import semantic.SemanticHelper; -import types.ARRAY; -import types.INT; -import types.RECORD; -import types.Type; - -public class DecVarArray extends Dec { - - public final String name; - public final String typeName; - public final String arrayName; - public final Exp init; - - public DecVarArray(Loc loc, String name, String typeName, String arrayName, Exp init) { - super(loc); - this.name = name; - this.typeName = typeName; - this.arrayName = arrayName; - this.init = init; - } - - @Override - public Tree.Node toTree() { - return Tree.of("DecVarArray", - (typeName != null)? Tree.of(name, - Tree.of(typeName)):Tree.of(name), - Tree.of(arrayName), - init.toTree()); - } - - @Override - public Type semantic(Env env) { - Type t_init = init.semantic(env); - if (!t_init.is(INT.T)) - throw SemanticHelper.typeMismatch(init.loc,t_init, INT.T); - - Type t_typeName; - if (typeName != null){ - t_typeName = env.tenv.get(typeName); - if (t_typeName == null) - throw SemanticHelper.undefined(loc, "type", typeName); - else{ - Type t_array = env.venv.get(arrayName); - t_array = t_array.actual(); - t_array = ((ARRAY)t_array).typeName; - if (!t_array.is(t_typeName)) - throw SemanticHelper.typeMismatch(loc, t_typeName, t_array); - } - } - else{ - Type t_array = env.venv.get(arrayName); - t_array = t_array.actual(); - t_array = ((ARRAY)t_array).typeName; - t_typeName = t_array; - } - env.venv.put(name, t_typeName); - return t_typeName; - } -} diff --git a/src/main/java/absyn/VarSubscript.java b/src/main/java/absyn/VarSubscript.java new file mode 100644 index 0000000..b0f725c --- /dev/null +++ b/src/main/java/absyn/VarSubscript.java @@ -0,0 +1,47 @@ +package absyn; + +import env.Env; +import javaslang.collection.Tree; +import parse.Loc; +import semantic.SemanticHelper; +import types.ARRAY; +import types.INT; +import types.Type; + +public class VarSubscript extends Var { + + public final Var base; + public final Exp indice; + + public VarSubscript(Loc loc, Var base, Exp indice) { + super(loc); + this.base = base; + this.indice = indice; + } + + @Override + public Tree.Node toTree() { + return Tree.of(annotateType("VarSubscript: "), + base.toTree(), + indice.toTree()); + } + + @Override + protected Type semantic_(Env env) { + Type t_init = indice.semantic(env); + if (!t_init.is(INT.T)) + throw SemanticHelper.typeMismatch(indice.loc,t_init, INT.T); + + Type t_base = base.semantic(env); + + t_base = t_base.actual(); + if (!(t_base instanceof ARRAY)) + throw SemanticHelper.arrayMismatch(loc,t_base); + + t_base = ((ARRAY)t_base).typeName; + + System.out.println("VarSubscript: "+t_base); + return t_base; + } + +} From 3f1f5bb710b7557c286eaac851cc3aa2b452e2df Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Mon, 27 Mar 2017 15:48:31 -0300 Subject: [PATCH 16/20] Corrections of RECORD type --- src/main/cup/parser.cup | 24 +++------ src/main/java/absyn/DecVarRecord.java | 74 --------------------------- src/main/java/absyn/Parameter.java | 5 ++ src/main/java/absyn/VarField.java | 49 ++++++++++++++++++ src/main/java/absyn/VarSubscript.java | 1 - src/main/java/types/RECORD.java | 11 +++- 6 files changed, 70 insertions(+), 94 deletions(-) delete mode 100644 src/main/java/absyn/DecVarRecord.java create mode 100644 src/main/java/absyn/VarField.java diff --git a/src/main/cup/parser.cup b/src/main/cup/parser.cup index 7534e08..72e7725 100644 --- a/src/main/cup/parser.cup +++ b/src/main/cup/parser.cup @@ -75,8 +75,6 @@ non terminal List parameters, parametersRest; non terminal List decfuncs; non terminal ParameterWithExp parameterexp; non terminal List parameterexps, parameterexpsRest; -non terminal Dec decsvar; -non terminal DecVarRecord decvarrecord; precedence left OR; precedence left AND; @@ -147,17 +145,6 @@ decvar ::= | VAR:v ID:x EQ exp:e {: RESULT = new DecVar(loc(vxleft,exright), x, null, e); :} ; -decvarrecord ::= - VAR:v ID:x COLON ID:t EQ ID:bv DOT ID:br {: RESULT = new DecVarRecord(loc(vxleft,brxright),x,t,bv,br); :} -| VAR:v ID:x EQ ID:bv DOT ID:br {: RESULT = new DecVarRecord(loc(vxleft,brxright),x,null,bv,br); :} -; - - -decsvar ::= - decvar:d {: RESULT = d; :} -| decvarrecord:d {: RESULT = d; :} -; - dectype ::= TYPE:t ID:id EQ ty:ty {: RESULT = new DecType(loc(txleft,tyxright), id,ty); :} ; @@ -174,10 +161,10 @@ decs ::= ; decs_beg_with_variable ::= - decsvar:d {: RESULT = List.of(d); :} -| decsvar:d decs_beg_with_variable:ds {: RESULT = ds.prepend(d); :} -| decsvar:d decs_beg_with_type:ds {: RESULT = ds.prepend(d); :} -| decsvar:d decs_beg_with_func:ds {: RESULT = ds.prepend(d); :} + decvar:d {: RESULT = List.of(d); :} +| decvar:d decs_beg_with_variable:ds {: RESULT = ds.prepend(d); :} +| decvar:d decs_beg_with_type:ds {: RESULT = ds.prepend(d); :} +| decvar:d decs_beg_with_func:ds {: RESULT = ds.prepend(d); :} ; decs_beg_with_type ::= @@ -187,8 +174,9 @@ decs_beg_with_type ::= ; var ::= - ID:v {: RESULT = new VarSimple(loc(vxleft,vxright), v); :} + ID:v {: RESULT = new VarSimple(loc(vxleft,vxright), v); :} | var:x LBRACK exp:e RBRACK:r {: RESULT = new VarSubscript(loc(xxleft,rxright), x, e); :} +| var:x DOT ID:id {: RESULT = new VarField(loc(xxleft,idxright), x, id); :} ; ty ::= diff --git a/src/main/java/absyn/DecVarRecord.java b/src/main/java/absyn/DecVarRecord.java deleted file mode 100644 index c994c71..0000000 --- a/src/main/java/absyn/DecVarRecord.java +++ /dev/null @@ -1,74 +0,0 @@ -package absyn; - -import env.Env; -import javaslang.collection.List; -import javaslang.collection.Tree; -import javaslang.control.Option; -import parse.Loc; -import semantic.SemanticHelper; -import types.RECORD; -import types.Type; - -public class DecVarRecord extends Dec { - - public final String name; - public final String typeName; - public final String bodyVarName; - public final String bodyRegisterName; - - public DecVarRecord(Loc loc, String name, String typeName, String bodyVarName, String bodyRegisterName) { - super(loc); - this.name = name; - this.typeName = typeName; - this.bodyVarName = bodyVarName; - this.bodyRegisterName = bodyRegisterName; - } - - @Override - public Tree.Node toTree() { - return Tree.of("DecVarRecord", - (typeName != null)? Tree.of(name, - Tree.of(typeName)):Tree.of(name), - Tree.of(bodyVarName, - Tree.of(bodyRegisterName))); - } - - @Override - public Type semantic(Env env) { - Type t_typeName; - if (typeName != null) { - t_typeName = env.tenv.get(typeName); - - if (t_typeName == null) - throw SemanticHelper.undefined(loc, "type", typeName); - else { - Type t_bodyVar = env.venv.get(bodyVarName); - t_bodyVar = t_bodyVar.actual(); - - List t_bodyParams = ((RECORD) t_bodyVar).elements; - Option t_p = t_bodyParams.find(p -> p.name == bodyRegisterName); - if (t_p.isEmpty()) - throw SemanticHelper.unknownRecordParameter(loc, bodyRegisterName); - else { - Type t_aux = t_p.get().semantic_(env); - if (!t_aux.is(t_typeName)) - throw SemanticHelper.typeMismatch(loc, t_typeName, t_aux); - } - } - - } - else{ - Type t_bodyVar = env.venv.get(bodyVarName); - t_bodyVar = t_bodyVar.actual(); - - List t_bodyParams = ((RECORD) t_bodyVar).elements; - Option t_p = t_bodyParams.find(p -> p.name == bodyRegisterName); - if (t_p.isEmpty()) - throw SemanticHelper.unknownRecordParameter(loc, bodyRegisterName); - - t_typeName = t_p.get().semantic_(env); - } - env.venv.put(name, t_typeName); - return t_typeName; - } -} diff --git a/src/main/java/absyn/Parameter.java b/src/main/java/absyn/Parameter.java index 9e73fc3..b6971d0 100644 --- a/src/main/java/absyn/Parameter.java +++ b/src/main/java/absyn/Parameter.java @@ -29,4 +29,9 @@ protected Type semantic_(Env env) { throw SemanticHelper.undefined(loc, "type", typeName); return t_type; } + + @Override + public String toString() { + return name + " : " + typeName; + } } diff --git a/src/main/java/absyn/VarField.java b/src/main/java/absyn/VarField.java new file mode 100644 index 0000000..3c90851 --- /dev/null +++ b/src/main/java/absyn/VarField.java @@ -0,0 +1,49 @@ +package absyn; + +import env.Env; +import javaslang.collection.List; +import javaslang.collection.Tree; +import javaslang.control.Option; +import parse.Loc; +import semantic.SemanticHelper; +import types.INT; +import types.RECORD; +import types.Type; + +public class VarField extends Var { + + public final Var base; + public final String field; + + public VarField(Loc loc, Var base, String field) { + super(loc); + this.base = base; + this.field = field; + } + + @Override + public Tree.Node toTree() { + return Tree.of(annotateType("VarSubscript: "), + base.toTree(), + Tree.of(field)); + } + + @Override + protected Type semantic_(Env env) { + Type t_base = base.semantic(env); + + t_base = t_base.actual(); + if (!(t_base instanceof RECORD)) + throw SemanticHelper.recordMismatch(loc, t_base); + + List t_bodyParams = ((RECORD) t_base).elements; + Option t_p = t_bodyParams.find(p -> p.name == field); + if (t_p.isEmpty()) + throw SemanticHelper.unknownRecordParameter(loc, field); + + Type t_aux = t_p.get().semantic_(env); + t_aux = t_aux.actual(); + return t_aux; + } + +} diff --git a/src/main/java/absyn/VarSubscript.java b/src/main/java/absyn/VarSubscript.java index b0f725c..1a4627e 100644 --- a/src/main/java/absyn/VarSubscript.java +++ b/src/main/java/absyn/VarSubscript.java @@ -40,7 +40,6 @@ protected Type semantic_(Env env) { t_base = ((ARRAY)t_base).typeName; - System.out.println("VarSubscript: "+t_base); return t_base; } diff --git a/src/main/java/types/RECORD.java b/src/main/java/types/RECORD.java index c426666..35bd5b9 100644 --- a/src/main/java/types/RECORD.java +++ b/src/main/java/types/RECORD.java @@ -14,7 +14,16 @@ public RECORD(List elements) { @Override public String toString() { - return "RECORD [" + elements + "]"; + final StringBuilder builder = new StringBuilder(); + final int n = elements.size(); + if (n > 0) { + builder.append(elements.get()); + if (n > 1) { + for (int i = 1; i < n; i++) + builder.append(", ").append(elements.get(i)); + } + } + return "RECORD {" + builder + "}"; } @Override From ee41862507a55c62e5b22f9418831fb2f6b30baf Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Mon, 27 Mar 2017 16:11:05 -0300 Subject: [PATCH 17/20] Final corrections, missing the tests --- src/main/java/absyn/VarField.java | 2 +- src/main/java/types/NAME.java | 5 +++++ src/main/java/types/RECORD.java | 14 -------------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/main/java/absyn/VarField.java b/src/main/java/absyn/VarField.java index 3c90851..8ff59a4 100644 --- a/src/main/java/absyn/VarField.java +++ b/src/main/java/absyn/VarField.java @@ -42,7 +42,7 @@ protected Type semantic_(Env env) { throw SemanticHelper.unknownRecordParameter(loc, field); Type t_aux = t_p.get().semantic_(env); - t_aux = t_aux.actual(); + //t_aux = t_aux.actual(); return t_aux; } diff --git a/src/main/java/types/NAME.java b/src/main/java/types/NAME.java index 733dc1a..a9d4165 100644 --- a/src/main/java/types/NAME.java +++ b/src/main/java/types/NAME.java @@ -24,4 +24,9 @@ public boolean is(Type type) { public Type actual() { return binding.actual(); } + + @Override + public String toString() { + return name; + } } diff --git a/src/main/java/types/RECORD.java b/src/main/java/types/RECORD.java index 35bd5b9..ddc979f 100644 --- a/src/main/java/types/RECORD.java +++ b/src/main/java/types/RECORD.java @@ -12,20 +12,6 @@ public RECORD(List elements) { this.elements = elements; } - @Override - public String toString() { - final StringBuilder builder = new StringBuilder(); - final int n = elements.size(); - if (n > 0) { - builder.append(elements.get()); - if (n > 1) { - for (int i = 1; i < n; i++) - builder.append(", ").append(elements.get(i)); - } - } - return "RECORD {" + builder + "}"; - } - @Override public Tree.Node toTree() { return Tree.of("RECORD", elements.map(Parameter::toTree)); From 36c00c45b5d1a9ac19126bb8376ce2afa6fc5776 Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Mon, 27 Mar 2017 16:16:33 -0300 Subject: [PATCH 18/20] add a file with the members of project --- Alunos.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Alunos.txt diff --git a/Alunos.txt b/Alunos.txt new file mode 100644 index 0000000..3190ce8 --- /dev/null +++ b/Alunos.txt @@ -0,0 +1,2 @@ +Marcos Vinicius Oliveira Souza +João Pedro Lonczynski \ No newline at end of file From 910cd95c27e9ffd11ec1d6034d5680e661f4a8eb Mon Sep 17 00:00:00 2001 From: Marcos Souza Date: Mon, 27 Mar 2017 16:38:33 -0300 Subject: [PATCH 19/20] Correction of ARRAY result --- src/main/java/absyn/ExpArray.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/absyn/ExpArray.java b/src/main/java/absyn/ExpArray.java index 88fa986..e28cd68 100644 --- a/src/main/java/absyn/ExpArray.java +++ b/src/main/java/absyn/ExpArray.java @@ -27,6 +27,7 @@ public Tree.Node toTree() { @Override protected Type semantic_(Env env) { Type t_typeName = env.tenv.get(typeName); + Type t_test = t_typeName; if (t_typeName == null) throw SemanticHelper.undefined(loc,"type",typeName); else{ @@ -43,6 +44,6 @@ protected Type semantic_(Env env) { throw SemanticHelper.typeMismatch(loc,t_aux,t_elements); } - return t_typeName; + return t_test; } } From bfc03ed10258ee08c1e1899ecd0310dc59f1efdf Mon Sep 17 00:00:00 2001 From: jotapeter Date: Tue, 28 Mar 2017 19:00:35 -0300 Subject: [PATCH 20/20] acrescentado os testes que romildo passou --- src/test/java/Test/SemantTest.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/test/java/Test/SemantTest.java b/src/test/java/Test/SemantTest.java index 0ba0e11..0c33ab4 100644 --- a/src/test/java/Test/SemantTest.java +++ b/src/test/java/Test/SemantTest.java @@ -178,14 +178,21 @@ public void testFunction() throws Exception { @Test public void testArray() throws Exception { + trun("let type t1 = [int] var a1:t1 = @t1[10,20,30] in print_int(a1[2])", UNIT.T); trun("let type t = [int] var v:t = @t[10,20,30] var x:int = v[1] var y:int = v[x] in x", INT.T); trun("let type t = [int] var v:t = @t[10,20,30] var x :int= v[2+3] in 2", INT.T); trun("let type t = [int] var v:t = @t[10,20,30] var x :int= v[2+3] in x", INT.T); trun("let type t = [int] var v:t = @t[10,20] var x:int = v[2] in x", INT.T); trun("let type t = [real] var v:t = @t[10.0,20.0] var x:real = v[2] in x", REAL.T); trun("let type t = [unit] var v:t = @t[()] var x:unit = v[2] in x", UNIT.T); + trun("let type t1 = [int] type t2 = [t1] var a1 = @t2 [@t1[10,20], @t1[30]] in (a1[1][0]:=18; print_int(a1[1][0]))", UNIT.T); + erun("let var a1 = 2.3 var x = a[1] in print_int(x)", "error.CompilerError: 1/26-1/27 undefined variable 'a'"); + erun("let type t1 = [int] var a1 = @int[10,20,30] in print_int(a1)", "error.CompilerError: 1/30-1/44 type mismatch: found int but expected array type"); + erun("let type t1 = [abobrinha] var a1:t1 = @t1[10,20,30] in print_int(a1)", "error.CompilerError: 1/16-1/25 undefined type 'abobrinha'"); + erun("let type t = [int] var v:t = @t[10,20,30] var x = b[1] in x", "error.CompilerError: 1/51-1/52 undefined variable 'b'"); + erun("let type t1 = [int] var a1 = @t2[10,20,30] in print_int(a1[2])", "error.CompilerError: 1/30-1/43 undefined type 't2'"); erun("let type t = [unit] var v:t = @t[(),1] var x:unit = v[2] in x", "error.CompilerError: 1/31-1/39 type mismatch: found int but expected unit"); - erun("let type t = [real] var v:t = @t[10.0,20.0] var x:int = v[2] in x", "error.CompilerError: 1/45-1/61 type mismatch: found int but expected real"); + erun("let type t = [real] var v:t = @t[10.0,20.0] var x:int = v[2] in x", "error.CompilerError: 1/57-1/61 type mismatch: found real but expected int"); erun("let type t = [real] var v:t = @t[10.0,20.0] var x:real = v[2.0] in x", "error.CompilerError: 1/60-1/63 type mismatch: found real but expected int"); erun("let type t = [int] var v:t = @t[10,20,()] var x :int= v[2+3] in 2", "error.CompilerError: 1/30-1/42 type mismatch: found unit but expected int"); erun("let type t = [int] var v:t = @t[10,20,30] var x:int = v[y] var y:int = v[1] in x", "error.CompilerError: 1/57-1/58 undefined variable 'y'"); @@ -193,6 +200,7 @@ public void testArray() throws Exception { @Test public void testRegisters() throws Exception { + trun("let type t1 = [int] type t2 = {x:int, y:t1} var k = @t2{x=10, y=@t1[10,20,30]} in k.y[1]", INT.T); trun("let type ponto = {x:real, y:int} var p:ponto = @ponto{x=2.3,y=8} var x : int = p.y in x", INT.T); trun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : real = p.x in 2", INT.T); trun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : real = p.x in x", REAL.T); @@ -200,8 +208,8 @@ public void testRegisters() throws Exception { trun("let type ponto = {x:unit, y:unit} var p:ponto = @ponto{x=(),y=()} var x : unit = p.x in 2", INT.T); trun("let type ponto = {x:unit, y:unit} var p:ponto = @ponto{x=(),y=()} var x : unit = p.x in ()", UNIT.T); trun("let type ponto = {x:unit, y:unit} var p:ponto = @ponto{x=(),y=()} var x : unit = p.x in x", UNIT.T); - erun("let type ponto = {x:int, y:int} var p:ponto = @ponto{x=2,y=0} var x : real = p.x in 2", "error.CompilerError: 1/63-1/81 type mismatch: found real but expected int"); - erun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : int = p.x in ()", "error.CompilerError: 1/69-1/86 type mismatch: found int but expected real"); - erun("let type ponto = {x:real, y:int} var p:ponto = @ponto{x=2.3,y=8} var x : real = p.y in x", "error.CompilerError: 1/66-1/84 type mismatch: found real but expected int"); + erun("let type ponto = {x:int, y:int} var p:ponto = @ponto{x=2,y=0} var x : real = p.x in 2", "error.CompilerError: 1/78-1/81 type mismatch: found int but expected real"); + erun("let type ponto = {x:real, y:real} var p:ponto = @ponto{x=2.3,y=0.8} var x : int = p.x in ()", "error.CompilerError: 1/83-1/86 type mismatch: found real but expected int"); + erun("let type ponto = {x:real, y:int} var p:ponto = @ponto{x=2.3,y=8} var x : real = p.y in x", "error.CompilerError: 1/81-1/84 type mismatch: found int but expected real"); } }