]> git.mdlowis.com Git - proto/cerise-c.git/commitdiff
change where module resolution happens. Now it is happening in the parser and is...
authorMike Lowis <mike.lowis@gentex.com>
Mon, 21 Oct 2024 20:29:20 +0000 (16:29 -0400)
committerMike Lowis <mike.lowis@gentex.com>
Mon, 21 Oct 2024 20:29:20 +0000 (16:29 -0400)
lib/ir.rb
lib/parser.rb
lib/type_checker.rb

index 23b5044c85075df024ed018ceea86a5a941d0408..e8cb6763eb92a246c3857a784c4eada2c4ae76dc 100644 (file)
--- a/lib/ir.rb
+++ b/lib/ir.rb
@@ -6,7 +6,7 @@ module IR
   Return = Struct.new(:loc, :type, :value)
   Assert = Struct.new(:loc, :type, :value)
   Const  = Struct.new(:loc, :type, :value)
-  Var    = Struct.new(:loc, :type, :name)
+  Var    = Struct.new(:loc, :type, :name, :module)
   Def    = Struct.new(:loc, :type, :name, :value)
   Set    = Struct.new(:loc, :type, :name, :value)
   Op     = Struct.new(:loc, :type, :op, :left, :right)
index 0eabe9e5dc1e8d96249060ad6ab1bbcd502bf8f1..6ffacfe728afe044106d814be4352eb13a56f3b5 100644 (file)
@@ -452,9 +452,17 @@ class Parser
       elsif tok.type == :ident
         varname = IR::Var.new(tok.pos, nil, tok.text.to_sym)
         if accept(".")
+          mod = syms[varname.name]
+          pp mod
+          if mod.kind != :module
+            error("accessing field in object that is neither a record nor a module")
+          end
           tok = consume()
-          field = IR::Var.new(tok.pos, nil, tok.text.to_sym)
-          varname = make_binop(varname.loc, ".", varname, field)
+          sym = mod.type.exports[tok.text.to_sym]
+          if not sym
+            error("module or record has no such field '#{tok.text}'")
+          end
+          varname = IR::Var.new(tok.pos, sym[:type], tok.text.to_sym, varname.name)
         end
         varname
       else
index d000f3fef13d8d44c04e4110fe8010d53fb577e3..78542aea968064683e9e5916a150f38aac18af8b 100644 (file)
@@ -224,10 +224,17 @@ class TypeChecker
   end
 
   def infer_var(env, expr)
-    if env[expr.name].nil?
-      error(expr.loc, "symbol '#{expr.name}' not defined")
+    mod = expr.module
+    name = expr.name
+    if mod
+      expr.type = env[mod].type.exports[name][:type]
+    else
+      if env[expr.name].nil?
+        error(expr.loc, "symbol '#{expr.name}' not defined")
+      end
+      expr.type = env[expr.name][:type]
     end
-    expr.type = env[expr.name][:type]
+    expr.type
   end
 
   def infer_def(env, expr)
@@ -333,12 +340,6 @@ class TypeChecker
       type = infer(env, expr.func)
     end
 
-    # Handle module references here
-    if expr.func.type.is_a? Value::Module
-      pp "MODULE!!!"
-      pp expr
-    end
-
     error(expr.loc, "object being applied is not a function (has type: #{type.to_s})") if not type.is_a? Array
     error(expr.loc, "wrong number of arguments to function call") if (type.length - 1) != expr.args.length
     type[0..-2].each_with_index do |t,i|
@@ -379,12 +380,7 @@ class TypeChecker
   end
 
   def check_binary(env, expr, vtype)
-    if expr.op == "."
-      left_type = infer(env, expr.left)
-      if not left_type.is_a? Value::Module
-        error(expr.loc, "left side of '.' is not a module or record")
-      end
-    elsif expr.op == "["
+    if expr.op == "["
       left_type = infer(env, expr.left)
       if (left_type.is_a? Value::Type) and left_type.form == :array
         check(env, expr.right, :int)