]> git.mdlowis.com Git - proto/cerise-c.git/commitdiff
implemented basic arithmetic and boolean operators
authorMike Lowis <mike.lowis@gentex.com>
Tue, 4 Jun 2024 20:18:50 +0000 (16:18 -0400)
committerMike Lowis <mike.lowis@gentex.com>
Tue, 4 Jun 2024 20:18:50 +0000 (16:18 -0400)
build.sh
cerise-c.m
cerise-c.rb
runtime.h

index d5f553ee86b2f7ad09d11bf7b9065d8ea79eab46..2ffc1e9b3b4c099e72ae3fb6f6f92d02aedd90d8 100755 (executable)
--- 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
 
index a3e6967f3961592173e6cb2bb776c415e38bdaa5..422f2a9458aed84822b8cb926573266a3b73bd55 100644 (file)
@@ -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
 }
index c70c75cd0e2696b13b2e373ee36023989b276dde..2030672d0c74efa276a255c2d1656ecc48fb4f03 100755 (executable)
@@ -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 <runtime.h>\n\n"
 
index 4a3bdd0ea1169d740cfdf6d40a8f780a76037ce8..33cf1b6a314befbab28e4ae77e133b7f5e129f42 100644 (file)
--- 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);
     }