From 329c1bf0eff24eb8c084d6147acea94ab8f41df5 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Sun, 20 Oct 2024 23:36:44 -0400 Subject: [PATCH] started adding module imports and exports --- Int.c | 9 +++++++++ Int.m | 6 ++++++ cerise-c.m | 3 ++- cerise-c.rb | 2 +- lib/compiler.rb | 20 +++++++++++++++++++- lib/parser.rb | 18 ++++++++++++++++-- lib/type_checker.rb | 13 ++++++++++++- lib/value.rb | 2 ++ 8 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 Int.c create mode 100644 Int.m diff --git a/Int.c b/Int.c new file mode 100644 index 0000000..e480373 --- /dev/null +++ b/Int.c @@ -0,0 +1,9 @@ +#include + +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 index 0000000..c1f959c --- /dev/null +++ b/Int.m @@ -0,0 +1,6 @@ +module Int + +SumInts(a : int, b : int) : int +{ + return a + b +} diff --git a/cerise-c.m b/cerise-c.m index 0337271..6ca8377 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -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) } diff --git a/cerise-c.rb b/cerise-c.rb index 35ef595..a25e974 100755 --- a/cerise-c.rb +++ b/cerise-c.rb @@ -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 diff --git a/lib/compiler.rb b/lib/compiler.rb index d7d1120..127d7f6 100644 --- a/lib/compiler.rb +++ b/lib/compiler.rb @@ -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 diff --git a/lib/parser.rb b/lib/parser.rb index 3935db9..0eabe9e 100644 --- a/lib/parser.rb +++ b/lib/parser.rb @@ -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 diff --git a/lib/type_checker.rb b/lib/type_checker.rb index d7af957..d000f3f 100644 --- a/lib/type_checker.rb +++ b/lib/type_checker.rb @@ -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) diff --git a/lib/value.rb b/lib/value.rb index 15e6560..05065f6 100644 --- a/lib/value.rb +++ b/lib/value.rb @@ -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) -- 2.54.0