]> git.mdlowis.com Git - proto/cerise-c.git/commitdiff
started adding module imports and exports
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 21 Oct 2024 03:36:44 +0000 (23:36 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 21 Oct 2024 03:36:44 +0000 (23:36 -0400)
Int.c [new file with mode: 0644]
Int.m [new file with mode: 0644]
cerise-c.m
cerise-c.rb
lib/compiler.rb
lib/parser.rb
lib/type_checker.rb
lib/value.rb

diff --git a/Int.c b/Int.c
new file mode 100644 (file)
index 0000000..e480373
--- /dev/null
+++ b/Int.c
@@ -0,0 +1,9 @@
+#include <runtime.h>
+
+Value Int_SumInts(Value a, Value b);
+
+Value Int_SumInts(Value a, Value b) {
+    Value _t0 = OpAdd(a, b);
+    return _t0;
+}
+
diff --git a/Int.m b/Int.m
new file mode 100644 (file)
index 0000000..c1f959c
--- /dev/null
+++ b/Int.m
@@ -0,0 +1,6 @@
+module Int
+
+SumInts(a : int, b : int) : int
+{
+    return a + b
+}
index 0337271065d6c04c6c2eff5055f431bed4fd62c4..6ca837715454d7fd41e6f57e11a4d84fb7f64388 100644 (file)
@@ -1,7 +1,7 @@
 module TestSuite
 
 imports (
-    "foo/bar/baz"
+    "Int.m"
 )
 
 exports (Main)
@@ -210,4 +210,5 @@ Main()
     TestGtEqOps()
     TestNeqOps()
     TestIfBlocks()
+    Int.SumInts(1,2)
 }
index 35ef595ab5459fd59d96f21db81c06a3fb000996..a25e97457800bc11f0b3b2d212901816db7e4b70 100755 (executable)
@@ -31,4 +31,4 @@ require_relative 'lib/type_checker'
 require_relative 'lib/codegen'
 require_relative 'lib/compiler'
 
-pp Compiler.compile("cerise-c.m")
\ No newline at end of file
+ARGV.each {|p| Compiler.compile(p) }
\ No newline at end of file
index d7d112061e48b4960262c7b560ac38fba506ea35..127d7f678497e38ef1d35951a8804d281aa3b2d1 100644 (file)
@@ -1,4 +1,11 @@
 module Compiler
+  PATH = [
+    ".",
+    "#{ENV["HOME"]}/lib/cerise",
+    "/usr/share/cerise",
+    "/usr/local/share/cerise"
+  ]
+
   def self.compile(path)
     out_path = path.sub(/\.[^.]+$/,'.c')
     parser   = Parser.new(path)
@@ -6,6 +13,17 @@ module Compiler
     codegen  = Codegen.new(parser)
     codegen.output(out_path)
     `gcc -c -I. -O1 -o cerise-c.o #{out_path}`
-    parser.symbols
+    Value::Module.new(parser.module, parser.symbols)
+  end
+
+  def self.import(path)
+    PATH.each do |root|
+      p = "#{root}/#{path}"
+      puts p
+      if File.exist?(p)
+        return Compiler.compile(p)
+      end
+    end
+    raise "could not find #{path} in search paths"
   end
 end
\ No newline at end of file
index 3935db99382c7c7fc9d5acc7c1a1a3b58f829027..0eabe9e5dc1e8d96249060ad6ab1bbcd502bf8f1 100644 (file)
@@ -148,7 +148,15 @@ class Parser
       @imports = []
       expect("(")
       while !matches(")")
-        @imports << module_path()
+        modpath = module_path()
+        mod = Compiler.import(modpath)
+        syms.add_builtin(
+            mod.name,
+            :module,
+            mod,
+            nil
+        )
+        @imports << modpath
         expect(",") if not matches(")")
       end
       expect(")")
@@ -442,7 +450,13 @@ class Parser
       elsif tok.type == :void
         IR::Const.new(tok.pos, :void, :void)
       elsif tok.type == :ident
-        IR::Var.new(tok.pos, nil, tok.text.to_sym)
+        varname = IR::Var.new(tok.pos, nil, tok.text.to_sym)
+        if accept(".")
+          tok = consume()
+          field = IR::Var.new(tok.pos, nil, tok.text.to_sym)
+          varname = make_binop(varname.loc, ".", varname, field)
+        end
+        varname
       else
         error("invalid constant #{tok}")
       end
index d7af957170834663c03de1175bb999a6e6e39334..d000f3fef13d8d44c04e4110fe8010d53fb577e3 100644 (file)
@@ -333,6 +333,12 @@ 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|
@@ -373,7 +379,12 @@ class TypeChecker
   end
 
   def check_binary(env, expr, vtype)
-    if expr.op == "["
+    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 == "["
       left_type = infer(env, expr.left)
       if (left_type.is_a? Value::Type) and left_type.form == :array
         check(env, expr.right, :int)
index 15e6560b39a68165efe6055e1e6c185f3534b8b8..05065f6f3e569d1b7d1b9595031953125f73a2be 100644 (file)
@@ -6,6 +6,8 @@ module Value
   Type  = Struct.new(:form, :fields, :base, :size)
   Field = Struct.new(:type, :offset)
 
+  Module = Struct.new(:name, :exports)
+
   # Base type definitions
   Void   = Type.new(:void,  nil, nil, 0)
   Bool   = Type.new(:bool,  nil, nil, 1)