From: Mike Lowis Date: Tue, 7 Jan 2025 21:50:13 +0000 (-0500) Subject: records are now flat instead of nested. This makes the code in parser and generator... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=20c005f97b53f59a3a38bbbe80647e599716dedd;p=proto%2Fcerise-c.git records are now flat instead of nested. This makes the code in parser and generator easier to write and still achieves the end result --- diff --git a/Records.c b/Records.c index 8838061..b272c6b 100644 --- a/Records.c +++ b/Records.c @@ -7,7 +7,7 @@ struct Records_Rec1 { int foo; }; struct Records_Rec2 { - Records_Rec1 _base; + int foo; int bar; Records_Rec2* baz; }; diff --git a/Records.m b/Records.m index 614fe02..07db8d8 100644 --- a/Records.m +++ b/Records.m @@ -7,4 +7,5 @@ Rec1 is record { Rec2 is record (Rec1) { bar = int baz = Rec2 + foo = Rec2 } \ No newline at end of file diff --git a/lib/codegen.rb b/lib/codegen.rb index 8d5024e..78d7c8f 100644 --- a/lib/codegen.rb +++ b/lib/codegen.rb @@ -14,22 +14,50 @@ class Codegen @output = $stdout end + def type_lookup(type) + if type.is_a? IR::Var + if type.module.nil? + type = @syms[type.name].value || @syms[type.name].type + else + if type.module == @parser.module + type = @syms[type.name].type || @syms[type.name].value + else + type = @syms[type.module].type.exports[type.name] + type = type.type || type.value + end + end + end + type + end + def type_to_s(type) + result = "" if type == :string - "_string" + result = "_string" elsif type.is_a? Symbol - type - elsif type.is_a? IR::Var and type.module - "#{type.module || @parser.module}_#{type.name}" - elsif type.is_a? IR::Var and not type.module - "#{type.name}" + result = type + elsif type.is_a? IR::Var + if type.module.nil? + sym = @syms[type.name].value || @syms[type.name].type + result = "#{type.name}" + else + if type.module == @parser.module + sym = @syms[type.name].type || @syms[type.name].value + else + sym = @syms[type.module].type.exports[type.name] + sym = sym.type || sym.value + end + result = "#{type.module || @parser.module}_#{type.name}" + end + result += "*" if sym.is_a?(Value::Type) and sym.form == :record elsif type.form == :array - "_array" + result = "_array" elsif type.form == :hash - "_dict" + result = "_dict" else raise "unconvertable type: #{type}" end + result end def declare_sym(sym) @@ -82,12 +110,8 @@ class Codegen type = sym.value if type.form == :record puts "struct #{symname(sym)} {" - if (type.base) - puts " #{type_to_s(type.base)} _base;" - end type.fields.each do |k,v| - is_ref = reference_type?(v) - puts " #{type_to_s(v)}#{is_ref ? "*" : ""} #{k};" + puts " #{type_to_s(v)} #{k};" end puts "};" end @@ -318,6 +342,19 @@ class Codegen @syms.add_sym(v.name.name, v.loc, :local, v.type, v.value) temp = emit(v.value) error v, "invalid local definition: #{v.name.name}" if not @locals.index(v.name.name) + +# if v.type.module.nil? +# sym = @syms[v.type.name].value || @syms[v.type.name].type +# else +# if type.module == @parser.module +# sym = @syms[v.type.name].type || @syms[v.type.name].value +# else +# sym = @syms[v.type.module].type.exports[v.type.name] +# sym = sym.type || sym.value +# end +# end +# is_record = sym.is_a?(Value::Type) and sym.form == :record + putln "#{type_to_s(v.value.type)} #{v.name.name} = #{temp};" end diff --git a/lib/parser.rb b/lib/parser.rb index 6d4e31d..f3cea9a 100644 --- a/lib/parser.rb +++ b/lib/parser.rb @@ -217,23 +217,7 @@ class Parser def type_definition(name) if accept(:record) - base_type = nil - if accept("(") - base_type = qualified_identifier() - expect(")") - end - type = Value::Type.new(:record, {}, base_type, 0) - expect("{") - while not matches("}") - name = expect(:ident).text.to_sym - if type.fields[name] - error("field #{name} already defined in record") - end - expect("=") - type.fields[name] = type_specifier() - end - # parse fields here - expect("}") + type = record_definition(name) else type = type_specifier() type = Value::Type.new(:alias, nil, type, 0) @@ -241,10 +225,47 @@ class Parser type end + def record_definition(name) + base_type = nil + base_fields = {} + if accept("(") + base_type = qualified_identifier() + base_fields = type_lookup(base_type).fields.clone + expect(")") + end + type = Value::Type.new(:record, base_fields, base_type, 0) + expect("{") + while not matches("}") + name = expect(:ident).text.to_sym + if type.fields[name] + error("field #{name} already defined in record") + end + expect("=") + type.fields[name] = type_specifier() + end + # parse fields here + expect("}") + type + end + def constant_definition(name) error("constant definitions not yet supported") end + def type_lookup(type) + if type.module.nil? + type = @syms[type.name].value || @syms[type.name].type + else + if type.module == @parser.module + type = @syms[type.name].type || @syms[type.name].value + else + type = @syms[type.module].type.exports[type.name] + type = type.type || type.value + end + end + type + end + def function_arglist() args = [] expect("(")