From 630d011dab534e3da95f02e966c8a8a31f070029 Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Wed, 8 Jan 2025 15:04:10 -0500 Subject: [PATCH] implemented record definition, initialization, and access syntax --- Records.m | 1 - cerise-c.m | 2 +- lib/parser.rb | 9 +++++++++ lib/type_checker.rb | 12 ++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Records.m b/Records.m index 07db8d8..614fe02 100644 --- a/Records.m +++ b/Records.m @@ -7,5 +7,4 @@ Rec1 is record { Rec2 is record (Rec1) { bar = int baz = Rec2 - foo = Rec2 } \ No newline at end of file diff --git a/cerise-c.m b/cerise-c.m index 05d842f..5a46ca3 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -190,7 +190,7 @@ TestIfBlocks(){ TestRecords(){ def foo = new Records:Rec1 { foo = 42 } -# assert foo.foo == 42 + assert foo.foo == 42 # set foo.foo = 43 # assert foo.foo == 43 } diff --git a/lib/parser.rb b/lib/parser.rb index f3cea9a..7f3a4d0 100644 --- a/lib/parser.rb +++ b/lib/parser.rb @@ -485,6 +485,8 @@ class Parser expr = func_call(expr) elsif matches("[") expr = array_or_hash_access(expr) + elsif matches(".") + expr = record_access(expr) end expr end @@ -508,6 +510,13 @@ class Parser make_binop(loc, "[", expr, key) end + def record_access(expr) + expect(".") + loc = location + field = identifier() + make_binop(loc, ".", expr, field) + end + def const_or_ident() if matches(:new) record_literal() diff --git a/lib/type_checker.rb b/lib/type_checker.rb index 69f3085..f682d2b 100644 --- a/lib/type_checker.rb +++ b/lib/type_checker.rb @@ -492,6 +492,18 @@ class TypeChecker else error(expr.loc, "don't know how to index into type: #{left_type}") end + elsif expr.op == "." + rec_type = lookup_type(env, infer(env, expr.left)) + if rec_type.form != :record + error(expr.loc, "left hand side of the '.' operator is not a record type") + end + if not expr.right.is_a? IR::Var + error(expr.loc, "right hand side of '.' operator is not an identifier") + end + if expr.right.module != nil + error(expr.loc, "qualified identifier is not valid right hand operand for the '.' operator") + end + expr.type = rec_type.fields[expr.right.name] else tname = typename(vtype) optype = BinaryOps[expr.op][tname] -- 2.55.0