From: Michael D. Lowis Date: Tue, 11 Jun 2024 01:29:16 +0000 (-0400) Subject: added array literal parsing and code generation X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=b242c647c6eb5d45b5fed8dbe701275af63382ce;p=proto%2Fcerise-c.git added array literal parsing and code generation --- diff --git a/cerise-c.m b/cerise-c.m index 9af7d03..d8d91c4 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -88,7 +88,7 @@ TestStringOps() Main() { - def foo = 123 + def foo = [1,2,3] def bar = foo TestLiterals() TestBoolOps() diff --git a/cerise-c.rb b/cerise-c.rb index ac0e260..6f1b1c6 100755 --- a/cerise-c.rb +++ b/cerise-c.rb @@ -499,22 +499,52 @@ class Parser end def const_or_ident() - tok = consume() - if tok.type == :bool - IR::Const.new(tok.pos, Value::Bool, tok.text == "true") - elsif tok.type == :string - IR::Const.new(tok.pos, Value::String, tok.text) - elsif tok.type == :int - IR::Const.new(tok.pos, Value::Int, tok.text.to_i) - elsif tok.type == :float - IR::Const.new(tok.pos, Value::Float, tok.text.to_f) - elsif tok.type == :void - IR::Const.new(tok.pos, Value::Void, :void) - elsif tok.type == :ident - IR::Var.new(tok.pos, nil, tok.text.to_sym) + if matches("[") + array_literal() + elsif matches("{") + hash_literal() else - error("invalid constant #{tok}") + tok = consume() + if tok.type == :bool + IR::Const.new(tok.pos, Value::Bool, tok.text == "true") + elsif tok.type == :string + IR::Const.new(tok.pos, Value::String, tok.text) + elsif tok.type == :int + IR::Const.new(tok.pos, Value::Int, tok.text.to_i) + elsif tok.type == :float + IR::Const.new(tok.pos, Value::Float, tok.text.to_f) + elsif tok.type == :void + IR::Const.new(tok.pos, Value::Void, :void) + elsif tok.type == :ident + IR::Var.new(tok.pos, nil, tok.text.to_sym) + else + error("invalid constant #{tok}") + end + end + end + + def array_literal() + exprs = [] + expect("[") + loc = location() + while !matches("]") + exprs << expression() + expect(",") if !matches("]") end + expect("]") + exprs + IR::Const.new(loc, nil, exprs) + end + + def hash_literal() + exprs = {} + expect("{") +# while !matches("}") +# exprs << expression() +# expect(",") if !matches("}") +# end + expect("}") + exprs end end @@ -1076,13 +1106,22 @@ module Codegen def self.emit_const(state, v) var = mktemp(state) if v.value.is_a? Integer - putln state, "Value #{var} = MakeInt(#{v.value});" + putln state, "Value #{var} = MakeInt(#{v.value});" elsif v.value.is_a? Float - putln state, "Value #{var} = MakeReal(#{v.value});" + putln state, "Value #{var} = MakeReal(#{v.value});" elsif v.value == true || v.value == false - putln state, "Value #{var} = MakeBool(#{v.value});" + putln state, "Value #{var} = MakeBool(#{v.value});" elsif v.value.is_a? String - putln state, "Value #{var} = MakeString(#{v.value});" + putln state, "Value #{var} = MakeString(#{v.value});" + elsif v.value.is_a? Array + putln state, "Value #{var} = MakeArrayOfLength(#{v.value.length});" + v.value.each_with_index do |e, i| + val = emit(state, e) + putln state, "Array_SetIndex(#{var}, #{i}, #{val});" + + end + elsif v.value.is_a? Hash + putln state, "Value #{var} = MakeHash(#{v.value});" else raise "code emitting constants of this type not implemented" end @@ -1214,7 +1253,7 @@ end $parser = Parser.new("cerise-c.m") $checker = TypeChecker.new($parser) -state = Codegen.init($parser) +$state = Codegen.init($parser) puts "#include \n\n" @@ -1227,13 +1266,13 @@ $parser.syms.each do |name, val| args = val.value.args.map{|e| "Value #{e.name}" }.join(", ") puts "Value #{name}(#{args}) {" $parser.syms.open_scope - state.locals = val.value.locals + $state.locals = val.value.locals val.value.args.each_with_index do |name, idx| $parser.syms.add_sym( name.name, name.loc, :param, name.type, idx) end val.value.body.each do |stmnt| - Codegen.emit(state, stmnt) + Codegen.emit($state, stmnt) end puts "}\n\n" $parser.syms.close_scope