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
}
parse_file(path)
end
+ def linenum(pos)
+ @lex.linenum(pos)
+ end
+
def parse_file(path)
@lex = Lexer.new(path)
@prev = nil
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)
IR::Assert.new(loc, nil, expression())
end
-
def if_statement()
loc = location
expect(:if)
##
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)
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)
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)
$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"
//# Hashmap
//# String
-
-
//#define VALUE_NIL 0x0llu
//#define VALUE_UNDEFINED 0x1llu
//#define VALUE_FALSE 0x2llu
/* 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)) {
*************************************************/
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;
}
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);
}
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);
}