diff --git a/src/qir/ast/data/QIRRcons.java b/src/qir/ast/data/QIRRcons.java index 7400735b53804e521632a80d454d28cefc57b87e..c01acf6862f16e24f4bc40b9ebbe2c7aa5c46152 100644 --- a/src/qir/ast/data/QIRRcons.java +++ b/src/qir/ast/data/QIRRcons.java @@ -45,7 +45,7 @@ public final class QIRRcons extends QIRRecord { @Override public final String toString() { - return "{ " + id + ":" + value + "; " + tail + "}"; + return "{ " + id + ":" + value + "; " + tail + "}" + (type == null ? "" : " : " + type); } @Override diff --git a/src/qir/ast/data/QIRRecord.java b/src/qir/ast/data/QIRRecord.java index 00da67be72e030b495d78ea45ccfc0759994344d..8732c73700ef68fd57d24197631eeb1c305896b9 100644 --- a/src/qir/ast/data/QIRRecord.java +++ b/src/qir/ast/data/QIRRecord.java @@ -4,11 +4,14 @@ import com.oracle.truffle.api.source.SourceSection; import qir.ast.QIRNode; import qir.driver.IQIRVisitor; +import qir.types.QIRType; /** * {@link QIRRecord} is the generic representation of a tuple in QIR. */ public abstract class QIRRecord extends QIRNode { + public QIRType type; + public QIRRecord(final SourceSection source) { super(source); } diff --git a/src/qir/parser/Parser.frame b/src/qir/parser/Parser.frame index 96864c46557fd5de6b98bc5b143d0fab8de56499..d66a70ae4b57f7e74c2baf26133e515c707af9a8 100644 --- a/src/qir/parser/Parser.frame +++ b/src/qir/parser/Parser.frame @@ -30,6 +30,8 @@ Coco/R itself) does not fall under the GNU General Public License. import java.math.BigInteger; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; import java.util.Arrays; import com.oracle.truffle.api.frame.FrameDescriptor; diff --git a/src/qir/parser/Parser.java b/src/qir/parser/Parser.java index d30feda5d8e6ea9b8341b939786012e6371102f1..175a78cf9141f517724028100d4ac69e71ce06fc 100644 --- a/src/qir/parser/Parser.java +++ b/src/qir/parser/Parser.java @@ -3,6 +3,8 @@ package qir.parser; import java.math.BigInteger; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; import java.util.Arrays; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -271,12 +273,12 @@ public class Parser { res = result; break; } - case 34: { + case 25: { QIRIf result = Ifexpr(); res = result; break; } - case 37: { + case 28: { QIRRecord result = Tuplecons(); res = result; break; @@ -413,7 +415,7 @@ public class Parser { Expect(21); final Token srcToken = t; Token funName = null; - QIRType type = new FunctionType(Arrays.asList(QIRConstantType.ANY, QIRConstantType.ANY)); + QIRType type = new QIRFunctionType(Arrays.asList(QIRConstantType.ANY, QIRConstantType.ANY)); if (la.kind == 22) { Get(); Expect(1); @@ -432,12 +434,12 @@ public class Parser { QIRIf Ifexpr() { QIRIf res; - Expect(34); + Expect(25); final Token srcToken = t; QIRNode cond = QIR(); - Expect(35); + Expect(26); QIRNode thenNode = QIR(); - Expect(36); + Expect(27); QIRNode elseNode = QIR(); res = new QIRIf(srcFromToken(srcToken), cond, thenNode, elseNode); return res; @@ -445,26 +447,32 @@ public class Parser { QIRRecord Tuplecons() { QIRRecord res; - Expect(37); + Expect(28); res = QIRRnil.getInstance(); final Token srcToken = t; - Token idToken; + Token idToken; + QIRType type = QIRConstantType.ANY; if (la.kind == 1) { Get(); idToken = t; - Expect(38); + Expect(29); QIRNode value = QIR(); res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); - while (la.kind == 39) { + while (la.kind == 30) { Get(); Expect(1); idToken = t; - Expect(38); + Expect(29); value = QIR(); res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); } } - Expect(40); + Expect(31); + if (la.kind == 23) { + Get(); + type = RecordType(); + } + res.type = type; return res; } @@ -476,7 +484,7 @@ public class Parser { if (StartOf(1)) { QIRNode value = QIR(); res = new QIRLcons(srcFromToken(srcToken), value, res); - while (la.kind == 39) { + while (la.kind == 30) { Get(); value = QIR(); res = new QIRLcons(srcFromToken(srcToken), value, res); @@ -495,7 +503,7 @@ public class Parser { Expect(45); Expect(24); QIRNode ifEmpty = QIR(); - Expect(36); + Expect(27); Expect(24); QIRNode handler = QIR(); Expect(20); @@ -686,16 +694,45 @@ public class Parser { QIRType Type() { QIRType res; - QIRType first = ConstantType(); - final List<QIRType> types = new ArrayList<>(); - types.add(first); - QIRType type; - while (la.kind == 24) { + res = null; + if (StartOf(2)) { + QIRType first = ConstantType(); + final List<QIRType> types = new ArrayList<>(); + types.add(first); + QIRType type; + while (la.kind == 24) { + Get(); + type = ConstantType(); + types.add(type); + } + res = types.size() == 1 ? first : new QIRFunctionType(types); + } else if (la.kind == 28) { + res = RecordType(); + } else SynErr(63); + return res; + } + + QIRRecordType RecordType() { + QIRRecordType res; + Expect(28); + final Map<String, QIRType> types = new HashMap<>(); + if (la.kind == 1) { Get(); - type = ConstantType(); - types.add(type); + Token idToken = t; + Expect(23); + QIRType type = Type(); + types.put(idToken.val, type); + while (la.kind == 30) { + Get(); + Expect(1); + idToken = t; + Expect(23); + type = Type(); + types.put(idToken.val, type); + } } - res = types.size() == 1 ? first : new FunctionType(types); + Expect(31); + res = new QIRRecordType(types); return res; } @@ -703,52 +740,52 @@ public class Parser { QIRType res; res = null; switch (la.kind) { - case 25: { + case 32: { Get(); res = QIRConstantType.ANY; break; } - case 26: { + case 33: { Get(); res = QIRConstantType.NUMBER; break; } - case 27: { + case 34: { Get(); res = QIRConstantType.BIG_NUMBER; break; } - case 28: { + case 35: { Get(); res = QIRConstantType.DOUBLE; break; } - case 29: { + case 36: { Get(); res = QIRConstantType.BOOLEAN; break; } - case 30: { + case 37: { Get(); res = QIRConstantType.STRING; break; } - case 31: { + case 38: { Get(); res = QIRConstantType.NULL; break; } - case 32: { + case 39: { Get(); res = QIRConstantType.LIST; break; } - case 33: { + case 40: { Get(); res = QIRConstantType.RECORD; break; } - default: SynErr(63); break; + default: SynErr(64); break; } return res; } @@ -768,7 +805,8 @@ public class Parser { private static final boolean[][] set = { {_T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x}, - {_x,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_T,_x, _x,_T,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_x, _x,_T,_x,_x, _x,_T,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x} + {_x,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_T,_T, _x,_x,_T,_x, _x,_T,_x,_x, _x,_T,_x,_x, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_T,_x,_T, _x,_x,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _T,_T,_T,_T, _x,_x}, + {_x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _T,_T,_T,_T, _T,_T,_T,_T, _T,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x,_x,_x, _x,_x} }; @@ -826,22 +864,22 @@ class Errors { case 22: s = "\"#\" expected"; break; case 23: s = "\":\" expected"; break; case 24: s = "\"->\" expected"; break; - case 25: s = "\"any\" expected"; break; - case 26: s = "\"int\" expected"; break; - case 27: s = "\"big_int\" expected"; break; - case 28: s = "\"double\" expected"; break; - case 29: s = "\"bool\" expected"; break; - case 30: s = "\"string\" expected"; break; - case 31: s = "\"null\" expected"; break; - case 32: s = "\"list\" expected"; break; - case 33: s = "\"record\" expected"; break; - case 34: s = "\"if\" expected"; break; - case 35: s = "\"then\" expected"; break; - case 36: s = "\"else\" expected"; break; - case 37: s = "\"{\" expected"; break; - case 38: s = "\"=\" expected"; break; - case 39: s = "\";\" expected"; break; - case 40: s = "\"}\" expected"; break; + case 25: s = "\"if\" expected"; break; + case 26: s = "\"then\" expected"; break; + case 27: s = "\"else\" expected"; break; + case 28: s = "\"{\" expected"; break; + case 29: s = "\"=\" expected"; break; + case 30: s = "\";\" expected"; break; + case 31: s = "\"}\" expected"; break; + case 32: s = "\"any\" expected"; break; + case 33: s = "\"int\" expected"; break; + case 34: s = "\"big_int\" expected"; break; + case 35: s = "\"double\" expected"; break; + case 36: s = "\"bool\" expected"; break; + case 37: s = "\"string\" expected"; break; + case 38: s = "\"null\" expected"; break; + case 39: s = "\"list\" expected"; break; + case 40: s = "\"record\" expected"; break; case 41: s = "\"[\" expected"; break; case 42: s = "\"]\" expected"; break; case 43: s = "\"match\" expected"; break; @@ -864,7 +902,8 @@ class Errors { case 60: s = "??? expected"; break; case 61: s = "invalid Expression"; break; case 62: s = "invalid Boolean"; break; - case 63: s = "invalid ConstantType"; break; + case 63: s = "invalid Type"; break; + case 64: s = "invalid ConstantType"; break; default: s = "error " + n; break; } printMsg(line, col, s); diff --git a/src/qir/parser/Scanner.java b/src/qir/parser/Scanner.java index 7b48bd38042324073f796df7da0a4d7685618587..26e55b7e796b39a62e6294dcdb2573d5505cc03d 100644 --- a/src/qir/parser/Scanner.java +++ b/src/qir/parser/Scanner.java @@ -314,18 +314,18 @@ public class Scanner { start.set(66, 102); start.set(Buffer.EOF, -1); literals.put("fun", new Integer(21)); - literals.put("any", new Integer(25)); - literals.put("int", new Integer(26)); - literals.put("big_int", new Integer(27)); - literals.put("double", new Integer(28)); - literals.put("bool", new Integer(29)); - literals.put("string", new Integer(30)); - literals.put("null", new Integer(31)); - literals.put("list", new Integer(32)); - literals.put("record", new Integer(33)); - literals.put("if", new Integer(34)); - literals.put("then", new Integer(35)); - literals.put("else", new Integer(36)); + literals.put("if", new Integer(25)); + literals.put("then", new Integer(26)); + literals.put("else", new Integer(27)); + literals.put("any", new Integer(32)); + literals.put("int", new Integer(33)); + literals.put("big_int", new Integer(34)); + literals.put("double", new Integer(35)); + literals.put("bool", new Integer(36)); + literals.put("string", new Integer(37)); + literals.put("null", new Integer(38)); + literals.put("list", new Integer(39)); + literals.put("record", new Integer(40)); literals.put("match", new Integer(43)); literals.put("with", new Integer(44)); literals.put("empty", new Integer(45)); @@ -549,11 +549,11 @@ public class Scanner { case 30: {t.kind = 24; break loop;} case 31: - {t.kind = 37; break loop;} + {t.kind = 28; break loop;} case 32: - {t.kind = 39; break loop;} + {t.kind = 30; break loop;} case 33: - {t.kind = 40; break loop;} + {t.kind = 31; break loop;} case 34: {t.kind = 41; break loop;} case 35: @@ -734,9 +734,9 @@ public class Scanner { else if (ch == '>') {AddCh(); state = 30; break;} else {t.kind = 11; break loop;} case 97: - recEnd = pos; recKind = 38; + recEnd = pos; recKind = 29; if (ch == '=') {AddCh(); state = 17; break;} - else {t.kind = 38; break loop;} + else {t.kind = 29; break loop;} case 98: recEnd = pos; recKind = 8; if (ch == '=') {AddCh(); state = 18; break;} diff --git a/src/qir/parser/qir.atg b/src/qir/parser/qir.atg index 6d7b68dd297cb2bae4a7bc99874996936611dd35..a99306738657646fb044b801158d941f95384459 100644 --- a/src/qir/parser/qir.atg +++ b/src/qir/parser/qir.atg @@ -153,18 +153,52 @@ identifier (. res = new QIRVariable(srcFromToken(t), t.val); .) Lambda<out QIRLambda res> = "fun" (. final Token srcToken = t; Token funName = null; - QIRType type = new FunctionType(Arrays.asList(QIRConstantType.ANY, QIRConstantType.ANY)); .) + QIRType type = new QIRFunctionType(Arrays.asList(QIRConstantType.ANY, QIRConstantType.ANY)); .) [ "#" identifier (. funName = t; .) ] [ ":" Type<out type> ] Variable<out QIRVariable var> "->" QIR<out QIRNode body> (. res = new QIRLambda(srcFromToken(srcToken), funName == null ? null : funName.val, type, var, body, new FrameDescriptor()); .) . -Type<out QIRType res> = +Ifexpr<out QIRIf res> = +"if" (. final Token srcToken = t; .) +QIR<out QIRNode cond> "then" QIR<out QIRNode thenNode> "else" +QIR<out QIRNode elseNode> (. res = new QIRIf(srcFromToken(srcToken), cond, thenNode, elseNode); .) +. + +Tuplecons<out QIRRecord res> = +"{" (. res = QIRRnil.getInstance(); + final Token srcToken = t; + Token idToken; + QIRType type = QIRConstantType.ANY; .) +[ +identifier (. idToken = t; .) +"=" QIR<out QIRNode value> (. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .) +{ +";" identifier (. idToken = t; .) +"=" QIR<out value> (. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .) +} ] "}" [ ":" RecordType<out type> ] (. res.type = type; .) +. + +Type<out QIRType res> = (. res = null; .) +( ConstantType<out QIRType first> (. final List<QIRType> types = new ArrayList<>(); types.add(first); QIRType type; .) { "->" ConstantType<out type> (. types.add(type); .) -} (. res = types.size() == 1 ? first : new FunctionType(types); .) +} (. res = types.size() == 1 ? first : new QIRFunctionType(types); .) +| RecordType<out res> +) +. + +RecordType<out QIRRecordType res> = +"{" (. final Map<String, QIRType> types = new HashMap<>(); .) +[ +identifier (. Token idToken = t; .) +":" Type<out QIRType type> (. types.put(idToken.val, type); .) +{ ";" identifier (. idToken = t; .) +":" Type<out type> (. types.put(idToken.val, type); .) +} ] +"}" (. res = new QIRRecordType(types); .) . ConstantType<out QIRType res> = (. res = null; .) @@ -181,25 +215,6 @@ ConstantType<out QIRType res> = (. res = null; .) ) . -Ifexpr<out QIRIf res> = -"if" (. final Token srcToken = t; .) -QIR<out QIRNode cond> "then" QIR<out QIRNode thenNode> "else" -QIR<out QIRNode elseNode> (. res = new QIRIf(srcFromToken(srcToken), cond, thenNode, elseNode); .) -. - -Tuplecons<out QIRRecord res> = -"{" (. res = QIRRnil.getInstance(); - final Token srcToken = t; - Token idToken; .) -[ -identifier (. idToken = t; .) -"=" QIR<out QIRNode value> (. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .) -{ -";" identifier (. idToken = t; .) -"=" QIR<out value> (. res = new QIRRcons(srcFromToken(srcToken), idToken.val, value, res); .) -} ] "}" -. - Listcons<out QIRList res> = "[" (. res = QIRLnil.getInstance(); final Token srcToken = t; .) diff --git a/src/qir/parser/test.qir b/src/qir/parser/test.qir index a52991ef0ffcbbd2f8c63a56b01a84fdbd6e1028..20890fd2412c21d50065b846a63eeccb993424a6 100644 --- a/src/qir/parser/test.qir +++ b/src/qir/parser/test.qir @@ -1 +1 @@ -(fun : any -> any x -> x) @ [ { x = 2; y = 3 + 4 }; "toto"; (fun : int -> int x -> x + 2) ] +(fun x -> x) @ [ { x = 2; y = 3 + 4 } : { x : int; y : int }; "toto"; (fun : int -> int x -> x + 2) ] diff --git a/src/qir/types/FunctionType.java b/src/qir/types/QIRFunctionType.java similarity index 80% rename from src/qir/types/FunctionType.java rename to src/qir/types/QIRFunctionType.java index 677830c5e80ada6bdd1d08a09fa569b9a85c0682..d48fea9f06307a20b2cde018ab833d184172821b 100644 --- a/src/qir/types/FunctionType.java +++ b/src/qir/types/QIRFunctionType.java @@ -4,10 +4,10 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -public final class FunctionType implements QIRType { +public final class QIRFunctionType implements QIRType { private final List<QIRType> types; - public FunctionType(final List<QIRType> types) { + public QIRFunctionType(final List<QIRType> types) { this.types = types; } diff --git a/src/qir/types/QIRRecordType.java b/src/qir/types/QIRRecordType.java new file mode 100644 index 0000000000000000000000000000000000000000..32597a03ff19cb2aaafae8edab948b3e324f1065 --- /dev/null +++ b/src/qir/types/QIRRecordType.java @@ -0,0 +1,17 @@ +package qir.types; + +import java.util.Map; +import java.util.stream.Collectors; + +public class QIRRecordType implements QIRType { + private Map<String, QIRType> types; + + public QIRRecordType(final Map<String, QIRType> types) { + this.types = types; + } + + @Override + public final String toString() { + return "{ " + types.entrySet().stream().map(e -> e.getKey() + " : " + e.getValue()).collect(Collectors.joining(" -> ")) + " }"; + } +}