diff --git a/build.sh b/build.sh index 1df1dd2..68d2457 100755 --- a/build.sh +++ b/build.sh @@ -35,7 +35,7 @@ gcc -c src/common/executable.c -o temp/common/executable.o $FLAGS mkdir temp/runtime gcc -c src/runtime/runtime_error.c -o temp/runtime/runtime_error.o $FLAGS gcc -c src/runtime/runtime.c -o temp/runtime/runtime.o $FLAGS -gcc -c src/runtime/builtins.c -o temp/runtime/builtins.o $FLAGS +gcc -c src/runtime/o_builtins.c -o temp/runtime/o_builtins.o $FLAGS gcc -c src/runtime/o_nfunc.c -o temp/runtime/o_nfunc.o $FLAGS gcc -c src/runtime/o_func.c -o temp/runtime/o_func.o $FLAGS @@ -80,7 +80,7 @@ gcc src/main.c src/debug.c \ temp/objects/o_string.o \ temp/runtime/runtime.o \ temp/runtime/runtime_error.o \ - temp/runtime/builtins.o \ + temp/runtime/o_builtins.o \ temp/runtime/o_nfunc.o \ temp/runtime/o_func.o \ temp/common/executable.o \ diff --git a/src/main.c b/src/main.c index c6f5056..5104b8c 100644 --- a/src/main.c +++ b/src/main.c @@ -217,16 +217,6 @@ int main(int argc, char **argv) RuntimeError error; RuntimeError_Init(&error, runtime); - - if(!add_builtins(runtime, (Error*) &error)) - { - fprintf(stderr, "Couldn't load builtins: %s\n", error.base.message); - Debug_Free(dbg); - Source_Free(src); - Executable_Free(exe); - RuntimeError_Free(&error); - return 1; - } Object *result = run(runtime, (Error*) &error, exe, 0, NULL, 0); diff --git a/src/objects/o_string.c b/src/objects/o_string.c index cce9084..2758620 100644 --- a/src/objects/o_string.c +++ b/src/objects/o_string.c @@ -14,19 +14,38 @@ static int hash(Object *self); static int count(Object *self); static Object *copy(Object *self, Heap *heap, Error *err); static void print(Object *obj, FILE *fp); +static char *to_string(Object *self, int *size, Heap *heap, Error *err); static _Bool op_eql(Object *self, Object *other); static const Type t_string = { .base = (Object) { .type = &t_type, .flags = Object_STATIC }, .name = "string", - .size = sizeof (StringObject), + .atomic = ATMTP_STRING, + .size = sizeof(StringObject), .hash = hash, .count = count, .copy = copy, .print = print, + .to_string = to_string, .op_eql = op_eql, }; +static char *to_string(Object *self, int *size, Heap *heap, Error *err) +{ + assert(self != NULL); + assert(self->type == &t_string); + + (void) heap; + (void) err; + + StringObject *s = (StringObject*) self; + + if(size) + *size = s->size; + + return s->body; +} + Object *Object_FromString(const char *str, int len, Heap *heap, Error *error) { assert(str != NULL); diff --git a/src/objects/objects.c b/src/objects/objects.c index a65082b..efa36f3 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -10,7 +10,7 @@ const Type t_type = { const char *Object_GetName(const Object *obj) { - assert(obj); + assert(obj != NULL); const Type *type = Object_GetType(obj); assert(type); @@ -23,15 +23,15 @@ const char *Object_GetName(const Object *obj) const Type *Object_GetType(const Object *obj) { - assert(obj); - assert(obj->type); + assert(obj != NULL); + assert(obj->type != NULL); return obj->type; } unsigned int Object_GetSize(const Object *obj, Error *err) { - assert(err); - assert(obj); + assert(err != NULL); + assert(obj != NULL); const Type *type = Object_GetType(obj); assert(type); @@ -41,8 +41,8 @@ unsigned int Object_GetSize(const Object *obj, Error *err) unsigned int Object_GetDeepSize(const Object *obj, Error *err) { - assert(err); - assert(obj); + assert(err != NULL); + assert(obj != NULL); const Type *type = Object_GetType(obj); assert(type); @@ -58,10 +58,10 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err) int Object_Hash(Object *obj, Error *err) { - assert(obj); + assert(obj != NULL); const Type *type = Object_GetType(obj); - assert(type); + assert(type != NULL); if(type->hash == NULL) { @@ -74,11 +74,11 @@ int Object_Hash(Object *obj, Error *err) Object *Object_Copy(Object *obj, Heap *heap, Error *err) { - assert(err); - assert(obj); + assert(err != NULL); + assert(obj != NULL); const Type *type = Object_GetType(obj); - assert(type); + assert(type != NULL); if(type->copy == NULL) { @@ -245,6 +245,13 @@ _Bool Object_IsFloat(Object *obj) return obj->type->atomic == ATMTP_FLOAT; } +_Bool Object_IsString(Object *obj) +{ + assert(obj != NULL); + assert(obj->type != NULL); + return obj->type->atomic == ATMTP_STRING; +} + long long int Object_ToInt(Object *obj, Error *err) { assert(err); @@ -314,6 +321,29 @@ double Object_ToFloat(Object *obj, Error *err) return type->to_float(obj, err); } +const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err) +{ + assert(err != NULL); + assert(obj != NULL); + + if(!Object_IsString(obj)) + { + Error_Report(err, 0, "Object is not a string"); + return NULL; + } + + const Type *type = Object_GetType(obj); + assert(type); + + if(type->to_string == NULL) + { + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + return NULL; + } + + return type->to_string(obj, size, heap, err); +} + _Bool Object_Compare(Object *obj1, Object *obj2, Error *error) { assert(obj1 != NULL); diff --git a/src/objects/objects.h b/src/objects/objects.h index e946905..4198aef 100644 --- a/src/objects/objects.h +++ b/src/objects/objects.h @@ -18,6 +18,7 @@ typedef enum { ATMTP_INT, ATMTP_BOOL, ATMTP_FLOAT, + ATMTP_STRING, } AtomicType; struct Type { @@ -94,10 +95,12 @@ Object* Object_FromString(const char *str, int len, Heap *heap, Error *error); _Bool Object_IsInt (Object *obj); _Bool Object_IsBool (Object *obj); _Bool Object_IsFloat(Object *obj); +_Bool Object_IsString(Object *obj); long long int Object_ToInt (Object *obj, Error *err); _Bool Object_ToBool (Object *obj, Error *err); double Object_ToFloat(Object *obj, Error *err); +const char *Object_ToString(Object *obj, int *size, Heap *heap, Error *err); _Bool Object_Compare(Object *obj1, Object *obj2, Error *error); diff --git a/src/runtime/builtins.c b/src/runtime/builtins.c deleted file mode 100644 index 98cd7c8..0000000 --- a/src/runtime/builtins.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include "runtime.h" - -static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - for(int i = 0; i < (int) argc; i += 1) - Object_Print(argv[i], stdout); - - return Object_NewNone(Runtime_GetHeap(runtime), error); -} - -static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - int n = Object_Count(argv[0], error); - - if(error->occurred) - return NULL; - - return Object_FromInt(n, Runtime_GetHeap(runtime), error); -} - -static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error) -{ - assert(argc == 1); - - if(Object_ToBool(argv[0], error)) - { - return Object_NewNone(Runtime_GetHeap(runtime), error); - } - else - { - if(!error->occurred) - Error_Report(error, 0, "Assertion failed"); - return NULL; - } -} - -typedef struct { - const char *name; - int argc; - Object *(*callback)(Runtime*, Object**, unsigned int, Error*); -} BuiltinNativeFunctions; - -BuiltinNativeFunctions builtins[] = { - {"print", -1, bin_print}, - {"count", 1, bin_count}, - {"assert", 1, bin_assert}, -}; - -_Bool add_builtins(Runtime *runtime, Error *error) -{ - Heap *heap = Runtime_GetHeap(runtime); - assert(heap != NULL); - - Object *dest = Runtime_GetBuiltins(runtime, error); - - if(dest == NULL) - return 0; - - for(int i = 0; (unsigned int) i < sizeof(builtins) / sizeof(builtins[0]); i += 1) - { - Object *name = Object_FromString(builtins[i].name, -1, heap, error); - - if(name == NULL) - return 0; - - Object *func = Object_FromNativeFunction(runtime, builtins[i].callback, builtins[i].argc, heap, error); - - if(func == NULL) - return NULL; - - if(!Object_Insert(dest, name, func, heap, error)) - return 0; - } - - return 1; -} \ No newline at end of file diff --git a/src/runtime/o_builtins.c b/src/runtime/o_builtins.c new file mode 100644 index 0000000..b064db5 --- /dev/null +++ b/src/runtime/o_builtins.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include "runtime.h" +#include "../utils/defs.h" + +static Object *select(Object *self, Object *key, Heap *heap, Error *err); +static int count(Object *self); + +static Object *bin_print (Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_count (Runtime *runtime, Object **argv, unsigned int argc, Error *error); +static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error); + +typedef struct { + Object base; + Runtime *runtime; +} BuiltinsMapOjbect; + +static const Type t_builtins_map = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "builtins map", + .size = sizeof(BuiltinsMapOjbect), + .select = select, + .count = count, + .print = NULL, +}; + +static Object *select(Object *self, Object *key, Heap *heap, Error *err) +{ + BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) self; + + if(!Object_IsString(key)) + { + Error_Report(err, 0, "Non string key"); + return NULL; + } + + int n; + const char *s; + + s = Object_ToString(key, &n, heap, err); + + if(s == NULL) + return NULL; + + #define PAIR(p, q) \ + (((uint64_t) (p) << 32) | (uint32_t) (q)) + + switch(PAIR(n, s[0])) + { + case PAIR(sizeof("count")-1, 'c'): + { + if(!strcmp(s, "count")) + return Object_FromNativeFunction(bm->runtime, bin_count, 1, heap, err); + return NULL; + } + + case PAIR(sizeof("print")-1, 'p'): + { + if(!strcmp(s, "print")) + return Object_FromNativeFunction(bm->runtime, bin_print, -1, heap, err); + return NULL; + } + + case PAIR(sizeof("assert")-1, 'a'): + { + if(!strcmp(s, "assert")) + return Object_FromNativeFunction(bm->runtime, bin_assert, -1, heap, err); + return NULL; + } + + default: NULL; + } + + UNREACHABLE; + return NULL; +} + +static int count(Object *self) +{ + (void) self; + return 3; +} + +Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err) +{ + BuiltinsMapOjbect *bm = (BuiltinsMapOjbect*) Heap_Malloc(heap, &t_builtins_map, err); + + if(bm == NULL) + return NULL; + + bm->runtime = runtime; + + return (Object*) bm; +} + +static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + for(int i = 0; i < (int) argc; i += 1) + Object_Print(argv[i], stdout); + + return Object_NewNone(Runtime_GetHeap(runtime), error); +} + +static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + int n = Object_Count(argv[0], error); + + if(error->occurred) + return NULL; + + return Object_FromInt(n, Runtime_GetHeap(runtime), error); +} + +static Object *bin_assert(Runtime *runtime, Object **argv, unsigned int argc, Error *error) +{ + assert(argc == 1); + + if(Object_ToBool(argv[0], error)) + { + return Object_NewNone(Runtime_GetHeap(runtime), error); + } + else + { + if(!error->occurred) + Error_Report(error, 0, "Assertion failed"); + return NULL; + } +} \ No newline at end of file diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index fa6ffb6..08ca799 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -104,8 +104,11 @@ void Runtime_Free(Runtime *runtime) Object *Runtime_GetBuiltins(Runtime *runtime, Error *error) { if(runtime->builtins == NULL) - runtime->builtins = Object_NewMap(-1, runtime->heap, error); - + { + runtime->builtins = Object_NewBuiltinsMap(runtime, Runtime_GetHeap(runtime), error); + if(runtime->builtins == NULL) + return NULL; + } return runtime->builtins; } @@ -790,8 +793,13 @@ static _Bool step(Runtime *runtime, Error *error) { // Variable not defined locally. - if(runtime->builtins != NULL) - obj = Object_Select(runtime->builtins, key, runtime->heap, error); + Object *builtins = Runtime_GetBuiltins(runtime, error); + + if(builtins == NULL) + // Failed to create builtins map. + return 0; + + obj = Object_Select(runtime->builtins, key, runtime->heap, error); if(obj == NULL) { diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index ca877f9..1a2949a 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -22,9 +22,9 @@ Snapshot *Snapshot_New(Runtime *runtime); void Snapshot_Free(Snapshot *snapshot); void Snapshot_Print(Snapshot *snapshot, FILE *fp); -_Bool add_builtins(Runtime *runtime, Error *error); Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object **argv, int argc); +Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err); Object* Object_FromNativeFunction(Runtime *runtime, Object *(*callback)(Runtime*, Object**, unsigned int, Error*), int argc, Heap *heap, Error *error); Object* Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Heap *heap, Error *error); #endif \ No newline at end of file