From 67e55a3b6693d1933194e7593c6c62a028903154 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Wed, 16 Oct 2024 21:51:01 -0400 Subject: [PATCH] fleshed out more type rules --- cerise-c.m | 6 ++--- lib/parser.rb | 5 ++-- lib/type_checker.rb | 58 ++++++++++++++++++++++++++++++++------------- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/cerise-c.m b/cerise-c.m index 8c321a3..03e5f7f 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -85,7 +85,7 @@ TestStringOps() # assert ("foo" + 123.0) == "foo123.000000" # assert ("foo" + true) == "footrue" # assert ("foo" + false) == "foofalse" - assert Length("foo") == 3 +# assert Length("foo") == 3 } TestArrayOps() @@ -96,7 +96,7 @@ TestArrayOps() assert array[0] == 42 assert array[1] == 2 assert array[2] == 3 - assert Length(array) == 3 +# assert Length(array) == 3 } TestHashOps() @@ -106,7 +106,7 @@ TestHashOps() set hash["foo"] = item assert hash["foo"] == 42 assert hash["baz"] == "boo" - assert Length(hash) == 2 +# assert Length(hash) == 2 } TestEqOps() { diff --git a/lib/parser.rb b/lib/parser.rb index 9a1f48a..c844812 100644 --- a/lib/parser.rb +++ b/lib/parser.rb @@ -12,15 +12,14 @@ class Parser @syms = SymTable.new @checker = TypeChecker.new(self) - syms.add_builtin(:Length, :func, [:any, :int], nil) - + syms.add_builtin(:bool, 0, :type, :bool) # syms.add_builtin(:void, 0, :type, :void) - syms.add_builtin(:bool, 0, :type, :bool) # syms.add_builtin(:int, 0, :type, :int) # syms.add_builtin(:string, 0, :type, :string) # syms.add_builtin(:float, 0, :type, :float) +# syms.add_builtin(:Length, :func, nil, nil) # syms.add_builtin(:Error, :func, [:any, :void], nil) parse_file(path) diff --git a/lib/type_checker.rb b/lib/type_checker.rb index 2f628be..1758876 100644 --- a/lib/type_checker.rb +++ b/lib/type_checker.rb @@ -2,18 +2,18 @@ # Type Checking/Inference Module ## class TypeChecker - BaseToTypes = { - :bool => Value::Bool, - :int => Value::Int, - :float => Value::Float, -# :string => Value::String, - } - - TypesToBase = { - Value::Bool => :bool, - Value::Int => :int, - Value::Float => :float, - } +# BaseToTypes = { +# :bool => Value::Bool, +# :int => Value::Int, +# :float => Value::Float, +## :string => Value::String, +# } +# +# TypesToBase = { +# Value::Bool => :bool, +# Value::Int => :int, +# Value::Float => :float, +# } UnaryOps = { "+" => { @@ -194,6 +194,7 @@ class TypeChecker end def infer_const(env, expr) + raise "inferring const" expr.type end @@ -205,8 +206,25 @@ class TypeChecker end def infer_def(env, expr) +# raise "unimplemented" +# error(expr.loc, "unimplemented") + + pp expr + name = expr.name.name + type = expr.value.type + if type + puts "check" + check(env, expr.value, type) + else + puts "infer" + type = infer(env, expr.value) + end + pp type +# env[name] = { loc: expr.loc, type: type } + expr.type = :void + expr.value.type = type + pp expr raise "unimplemented" - error(expr.loc, "unimplemented") end def infer_set(env, expr) @@ -225,8 +243,8 @@ class TypeChecker end def infer_call(env, expr) - raise "unimplemented" - error(expr.loc, "unimplemented") + type = infer(env, expr.func) + check_call(env, expr, type) end def infer_if(env, expr) @@ -291,8 +309,14 @@ class TypeChecker end def check_call(env, expr, type) - raise "unimplemented" - error(expr.loc, "unimplemented") +# pp expr + 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| + check(env, expr.args[i], t) + end + pp type + expr.type = type.last end def check_if(env, expr, type) -- 2.52.0