From: Mike Lowis Date: Tue, 4 Jun 2024 20:18:50 +0000 (-0400) Subject: implemented basic arithmetic and boolean operators X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=009f078afe2df3d3849da7db7f57960a4b22df6e;p=proto%2Fcerise-c.git implemented basic arithmetic and boolean operators --- diff --git a/build.sh b/build.sh index d5f553e..2ffc1e9 100755 --- a/build.sh +++ b/build.sh @@ -1,6 +1,6 @@ #!/bin/sh ./cerise-c.rb > cerise-c.c \ - && cc -I. -O2 -o cerise-c cerise-c.c runtime.c \ + && gcc -I. -O2 -o cerise-c cerise-c.c runtime.c \ && ./cerise-c diff --git a/cerise-c.m b/cerise-c.m index a3e6967..422f2a9 100644 --- a/cerise-c.m +++ b/cerise-c.m @@ -22,19 +22,68 @@ TestBoolOps() TestIntOps() { + # Positive boolean cases + assert 1 == 1 + assert 1 != 2 + assert 1 < 2 + assert 2 > 1 + assert 1 <= 2 + assert 1 <= 1 + assert 2 >= 1 + assert 2 >= 2 + + # Negative boolean cases + assert (1 == 2) == false + assert (1 != 1) == false + assert (1 < 1) == false + assert (1 > 1) == false + assert (1 <= 0) == false + assert (2 >= 3) == false + + # Arithmetic operations + assert (43 - 1) == 42 + assert (41 + 1) == 42 + assert (84 / 2) == 42 + assert (21 * 2) == 42 + assert (11 % 5) == 1 + return true } TestRealOps() { - return false + # Positive boolean cases + assert 1.0 == 1.0 + assert 1.0 != 2.0 + assert 1.0 < 2.0 + assert 2.0 > 1.0 + assert 1.0 <= 2.0 + assert 1.0 <= 1.0 + assert 2.0 >= 1.0 + assert 2.0 >= 2.0 + + # Negative boolean cases + assert (1.0 == 2.0) == false + assert (1.0 != 1.0) == false + assert (1.0 < 1.0) == false + assert (1.0 > 1.0) == false + assert (1.0 <= 0.0) == false + assert (2.0 >= 3.0) == false + + # Arithmetic operations + assert (43 - 1) == 42 + assert (41 + 1) == 42 + assert (84 / 2) == 42 + assert (21 * 2) == 42 + #assert (11 % 5) == 1 # Not valid for reals + } init() { - assert TestLiterals() - assert TestBoolOps() - assert TestIntOps() - assert TestRealOps() + TestLiterals() + TestBoolOps() + TestIntOps() + TestRealOps() return true } diff --git a/cerise-c.rb b/cerise-c.rb index c70c75c..2030672 100755 --- a/cerise-c.rb +++ b/cerise-c.rb @@ -143,6 +143,10 @@ class Parser parse_file(path) end + def linenum(pos) + @lex.linenum(pos) + end + def parse_file(path) @lex = Lexer.new(path) @prev = nil @@ -339,8 +343,7 @@ class Parser def return_statement() loc = location - expect(:return); - if !matches("}") + if accept(:return) IR::Return.new(loc, nil, expression()) else IR::Return.new(loc, nil, nil) @@ -371,7 +374,6 @@ class Parser IR::Assert.new(loc, nil, expression()) end - def if_statement() loc = location expect(:if) @@ -1017,10 +1019,10 @@ end ## module Codegen - State = Struct.new(:label, :locals, :syms, :temp, :indent) + State = Struct.new(:parser, :label, :locals, :syms, :temp, :indent) - def self.init(syms) - State.new(0, [], syms, 0, 1) + def self.init(parser) + State.new(parser, 0, [], parser.syms, 0, 1) end def self.putln(state, msg) @@ -1063,8 +1065,12 @@ module Codegen end def self.emit_return(state, v) - temp = emit(state, v.value) - putln state, "return #{temp};" + if v.value + temp = emit(state, v.value) + putln state, "return #{temp};" + else + putln state, "return MakeNil();" + end end def self.emit_const(state, v) @@ -1174,7 +1180,8 @@ module Codegen def self.emit_assert(state, v) temp = emit(state, v.value) - putln state, "Assert(#{v.loc[0].inspect}, #{v.loc[1]}, #{temp});" + linenum = state.parser.linenum(v.loc[1]) + putln state, "Assert(#{v.loc[0].inspect}, #{linenum}, #{temp});" end def self.emit_if(state, v) @@ -1208,7 +1215,7 @@ end $parser = Parser.new("cerise-c.m") $checker = TypeChecker.new($parser) -state = Codegen.init($parser.syms) +state = Codegen.init($parser) puts "#include \n\n" diff --git a/runtime.h b/runtime.h index 4a3bdd0..33cf1b6 100644 --- a/runtime.h +++ b/runtime.h @@ -20,8 +20,6 @@ //# Hashmap //# String - - //#define VALUE_NIL 0x0llu //#define VALUE_UNDEFINED 0x1llu //#define VALUE_FALSE 0x2llu @@ -214,6 +212,10 @@ static Value ToString(Value val) { /* Builtin Functions *************************************************/ +static void Error(Value val) { + fprintf(stderr, "fatal error: %s\n", ValueAsString(val)->bytes); + exit(1); +} static void Assert(char* file, int lineno, Value val) { if (IsFalse(val) || IsNil(val)) { @@ -226,40 +228,113 @@ static void Assert(char* file, int lineno, Value val) { *************************************************/ static inline Value OpAdd(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeInt(ValueAsInt(left) + ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeReal(ValueAsReal(left) + ValueAsReal(right)); + } else { + fprintf(stderr, "fatal error: addition operator used on invalid type\n"); + exit(1); + } + return result; } static inline Value OpSub(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeInt(ValueAsInt(left) - ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeReal(ValueAsReal(left) - ValueAsReal(right)); + } else { + fprintf(stderr, "fatal error: addition operator used on invalid type\n"); + exit(1); + } + return result; } static inline Value OpMul(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeInt(ValueAsInt(left) * ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeReal(ValueAsReal(left) * ValueAsReal(right)); + } else { + fprintf(stderr, "fatal error: addition operator used on invalid type\n"); + exit(1); + } + return result; } static inline Value OpDiv(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeInt(ValueAsInt(left) / ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeReal(ValueAsReal(left) / ValueAsReal(right)); + } else { + fprintf(stderr, "fatal error: addition operator used on invalid type\n"); + exit(1); + } + return result; } static inline Value OpMod(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeInt(ValueAsInt(left) % ValueAsInt(right)); + } else { + fprintf(stderr, "fatal error: addition operator used on invalid type\n"); + exit(1); + } + return result; } static inline Value OpLt(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeBool(ValueAsInt(left) < ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeBool(ValueAsReal(left) < ValueAsReal(right)); + } else { + result = MakeBool(false); + } + return result; } static inline Value OpLtEq(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeBool(ValueAsInt(left) <= ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeBool(ValueAsReal(left) <= ValueAsReal(right)); + } else { + result = MakeBool(false); + } + return result; } static inline Value OpGt(Value left, Value right) { - return MakeNil(); + Value result; + if (IsInt(left)) { + result = MakeBool(ValueAsInt(left) > ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeBool(ValueAsReal(left) > ValueAsReal(right)); + } else { + result = MakeBool(false); + } + return result; } static inline Value OpGtEq(Value left, Value right) { Value result; - result = MakeBool(false); + if (IsInt(left)) { + result = MakeBool(ValueAsInt(left) >= ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeBool(ValueAsReal(left) >= ValueAsReal(right)); + } else { + result = MakeBool(false); + } return result; } @@ -267,6 +342,10 @@ static inline Value OpEq(Value left, Value right) { Value result; if (IsBool(left)) { result = MakeBool(ValueAsBool(left) == ValueAsBool(right)); + } else if (IsInt(left)) { + result = MakeBool(ValueAsInt(left) == ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeBool(ValueAsReal(left) == ValueAsReal(right)); } else { result = MakeBool(false); } @@ -277,6 +356,10 @@ static inline Value OpNeq(Value left, Value right) { Value result; if (IsBool(left)) { result = MakeBool(ValueAsBool(left) != ValueAsBool(right)); + } else if (IsInt(left)) { + result = MakeBool(ValueAsInt(left) != ValueAsInt(right)); + } else if (IsReal(left)) { + result = MakeBool(ValueAsReal(left) != ValueAsReal(right)); } else { result = MakeBool(false); }