From 6c0ccf10486fd9202e06a7b1f3b7ef4d0d3d4202 Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Thu, 13 Jun 2024 14:15:12 -0400 Subject: [PATCH] Implemented hash and array access and assignment --- cerise-c.m | 13 +++++++++---- cerise-c.rb | 44 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/cerise-c.m b/cerise-c.m index 832155a..aa00b71 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -89,15 +89,20 @@ TestStringOps() TestArrayOps() { def array = [1,2,3] - set item = array[0] -# set array[0] = item + def item = 42 + set array[0] = item + assert array[0] == 42 + assert array[1] == 2 + assert array[2] == 3 } TestHashOps() { def hash = {foo: "bar", "baz": "boo"} - set item = hash["foo"] -# set hash["foo"] = item + def item = 42 + set hash["foo"] = item + assert hash["foo"] == 42 + assert hash["baz"] == "boo" } Main() diff --git a/cerise-c.rb b/cerise-c.rb index c7245b5..633bf84 100755 --- a/cerise-c.rb +++ b/cerise-c.rb @@ -363,6 +363,9 @@ class Parser loc = location expect(:set) name = identifier() + if matches("[") + name = array_or_hash_access(name) + end expect ("=") value = expression() IR::Set.new(loc, nil, name, value) @@ -483,6 +486,8 @@ class Parser # Check for function call if matches("(") expr = func_call(expr) + elsif matches("[") + expr = array_or_hash_access(expr) end expr end @@ -498,6 +503,26 @@ class Parser call end + def array_or_hash_access(expr) + expect("[") + loc = location + key = expression() + expect("]") + make_binop(loc, "[", expr, key) + +# def make_binop(loc, op, left, right) + +# call = IR::Call.new(location, nil, expr, []) +# expect("(") +# while !matches(")") +# call.args << expression() +# expect(",") if !matches(")") +# end +# expect(")") +# call + end + + def const_or_ident() if matches("[") array_literal() @@ -1179,6 +1204,11 @@ module Codegen putln state, "#{result} = #{rvar};" state.indent -= 1 putln state, "}" + elsif v.op == "[" + lvar = emit(state, v.left) + rvar = emit(state, v.right) + result = mktemp(state); + putln state, "Value #{result} = ArrayOrHashGet(#{lvar}, #{rvar});" else lvar = emit(state, v.left) rvar = emit(state, v.right) @@ -1239,9 +1269,17 @@ module Codegen end def self.emit_set(state, v) - temp = emit(state, v.value) - raise "invalid local definition: #{v.name.name}" if not state.locals.index(v.name.name) - putln state, "#{v.name.name} = #{temp};" + if v.name.is_a? IR::Op + raise "not a valid array or hash access expression" if v.name.op != "[" + object = emit(state, v.name.left) + key = emit(state, v.name.right) + value = emit(state, v.value) + putln state, "ArrayOrHashSet(#{object}, #{key}, #{value});" + else + temp = emit(state, v.value) + raise "invalid local definition: #{v.name.name}" if not state.locals.index(v.name.name) + putln state, "#{v.name.name} = #{temp};" + end end def self.emit_assert(state, v) -- 2.54.0