]> git.mdlowis.com Git - proto/cerise-c.git/commitdiff
records are now flat instead of nested. This makes the code in parser and generator...
authorMike Lowis <mike.lowis@gentex.com>
Tue, 7 Jan 2025 21:50:13 +0000 (16:50 -0500)
committerMike Lowis <mike.lowis@gentex.com>
Tue, 7 Jan 2025 21:50:13 +0000 (16:50 -0500)
Records.c
Records.m
lib/codegen.rb
lib/parser.rb

index 8838061837620db8cafbcd78efb7c83636ab2ca9..b272c6bce6ae1281e5eda52d1fd7bbbcff69a9b1 100644 (file)
--- 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;
 };
index 614fe0222034cdae8962e08489d9634e27a2dc57..07db8d88d24e630be51ba0806e31afbac1ee0111 100644 (file)
--- 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
index 8d5024ec002eb619a2af76724c8da694b487cbd8..78d7c8f0df91f717c3d4a955b1f2f800ad182bf0 100644 (file)
@@ -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
 
index 6d4e31ddcd2b07dbdba4b7b9b7009cffa9445081..f3cea9aad58113249baf503f30d4e92e00b67c74 100644 (file)
@@ -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("(")