#!/bin/sh
-rm libruntime.a runtime/*.o
+OPTLEVEL=1
+
+rm -f cerise-c libruntime.a runtime/*.o
for f in runtime/*.c; do
printf "CC %s\n" "$f"
- gcc -c -I. -O2 -o "${f%.c}.o" "$f" &
+ gcc -c -I. -O$OPTLEVEL -o "${f%.c}.o" "$f" &
done
wait
printf "LIB %s\n" libruntime.a
printf "\n"
./cerise-c.rb > cerise-c.c \
&& gcc -I. -O2 -o cerise-c cerise-c.c libruntime.a \
+ && size cerise-c \
+ && printf "\n" \
&& ./cerise-c
+
def make_binop(loc, op, left, right)
node = IR::Op.new(loc, nil, op, left, right)
-# checker.infer(syms, node)
node
end
def make_unop(loc, op, value)
node = IR::Op.new(loc, nil, op, value, nil)
-# checker.infer(syms, node)
node
end
key = expression()
expect("]")
make_binop(loc, "[", expr, key)
-
-# def make_binop(loc, op, left, right)
-
-# call = IR::Call.new(location, nil, expr, [])
-# expect("(")
-# while !matches(")")
-# call.args << expression()
-# expect(",") if !matches(")")
-# end
-# expect(")")
-# call
end
-
def const_or_ident()
if matches("[")
array_literal()
##
-# Emit the Code
+# Parse and Analyze
##
$parser = Parser.new("cerise-c.m")
$checker = TypeChecker.new($parser)
$state = Codegen.init($parser)
-puts "#include <runtime.h>\n\n"
+##
+# Emit the Code
+##
+
+puts "#include <runtime.h>\n\n"
$parser.syms.each do |name, val|
args = val.value.args.map{|e| "Value #{e.name}" }.join(", ")
puts "Value #{name}(#{args});"
*************************************************/
void Error(Value val);
+void RuntimeError(char* s);
void Assert(char* file, int lineno, Value val);
Value Object_Get(Value object, Value key);
void Object_Set(Value object, Value key, Value value);
+
+/* Garbage Collection
+ *************************************************/
+
+void* GC_Allocate(size_t nbytes);
}
Value MakeArray(int32_t nslots) {
- Array* array = calloc(1, sizeof(Array));
+ Array* array = GC_Allocate(sizeof(Array));
array->length = nslots;
array->capacity = NextPow2(nslots);
- array->values = calloc(nslots, sizeof(Value));
+ array->values = GC_Allocate(nslots * sizeof(Value));
return (Value){ .as_uint64 = (NAN_TAG_ARRAY | (uintptr_t)array) };
}
{
Array* ary = ValueAsArray(array);
if (index >= ary->length) {
- Error(MakeString("array index out of bounds"));
+ RuntimeError("array index out of bounds");
}
ary->values[index] = value;
}
{
Array* ary = ValueAsArray(array);
if (index >= ary->length) {
- Error(MakeString("array index out of bounds"));
+ RuntimeError("array index out of bounds");
}
return ary->values[index];
}
}
Value MakeDict(int32_t nslots) {
- Dict* dict = calloc(1, sizeof(Dict));
+ Dict* dict = GC_Allocate(sizeof(Dict));
return (Value){ .as_uint64 = (NAN_TAG_DICT | (uintptr_t)dict) };
}
Dict* dict = ValueAsDict(dictionary);
DictNode** curr = FindNode(&(dict->root), &node);
if (!*curr) {
- DictNode* new_node = calloc(1, sizeof(DictNode));
+ DictNode* new_node = GC_Allocate(sizeof(DictNode));
*new_node = node;
*curr = new_node;
} else {
#include "runtime.h"
void Error(Value val) {
- fprintf(stderr, "fatal error: %s\n", ValueAsString(val)->bytes);
+ RuntimeError(ValueAsString(val)->bytes);
+}
+
+void RuntimeError(char* s) {
+ fprintf(stderr, "fatal error: %s\n", s);
exit(1);
}
--- /dev/null
+#include "runtime.h"
+
+#define FIRST_GEN_SIZE ((1024*1024) / sizeof(Value))
+
+Value First_Gen_Heap[FIRST_GEN_SIZE];
+Value* Heap_Next = First_Gen_Heap;
+Value* Heap_End = First_Gen_Heap + FIRST_GEN_SIZE;
+
+void* GC_Allocate(size_t nbytes) {
+ size_t ncells = nbytes / sizeof(Value);
+ if ((nbytes - (ncells * sizeof(Value))) > 0) {
+ ncells++;
+ }
+ Value* obj = Heap_Next;
+ Heap_Next += ncells;
+ if (Heap_Next > Heap_End) {
+ fprintf(stderr, "out of memory");
+ exit(1);
+ }
+ return obj;
+}
} else if (IsString(object)) {
result = String_Get(object, ValueAsInt(key));
} else {
- Error(MakeString("object is not indexable"));
+ RuntimeError("object is not indexable");
}
return result;
}
} else if (IsArray(object)) {
Array_Set(object, ValueAsInt(key), value);
} else {
- Error(MakeString("object is not assignable"));
+ RuntimeError("object is not assignable");
}
}
String* left_str = ValueAsString(left);
String* right_str = ValueAsString(right);
size_t sz = left_str->length + right_str->length;
- String* str = calloc(sizeof(String) + sz + 1, 1);
+ String* str = GC_Allocate(sizeof(String) + sz + 1);
str->length = sz;
memcpy(
str->bytes,
right_str->length + 1);
result = (Value){ .as_uint64 = (NAN_TAG_STRING | (uint64_t)str) };
} else {
- fprintf(stderr, "fatal error: addition operator used on invalid type\n");
- exit(1);
+ RuntimeError("addition operator used on invalid type");
}
return result;
}
Value MakeString(char* s) {
size_t sz = strlen(s);
- String* str = calloc(sizeof(String) + sz + 1, 1);
+ String* str = GC_Allocate(sizeof(String) + sz + 1);
str->length = sz;
strncpy(str->bytes, s, sz+1);
Value ret = (Value){ .as_uint64 = (NAN_TAG_STRING | (uint64_t)str) };
{
String* str = ValueAsString(hash);
if (index >= str->length) {
- Error(MakeString("string index out of bounds"));
+ RuntimeError("string index out of bounds");
}
return MakeInt( str->bytes[index] );
}