added closures
This commit is contained in:
@@ -36,6 +36,7 @@ mkdir temp/runtime
|
|||||||
gcc -c src/runtime/runtime_error.c -o temp/runtime/runtime_error.o $FLAGS
|
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/runtime.c -o temp/runtime/runtime.o $FLAGS
|
||||||
gcc -c src/runtime/o_builtins.c -o temp/runtime/o_builtins.o $FLAGS
|
gcc -c src/runtime/o_builtins.c -o temp/runtime/o_builtins.o $FLAGS
|
||||||
|
gcc -c src/runtime/o_closure.c -o temp/runtime/o_closure.o $FLAGS
|
||||||
gcc -c src/runtime/o_nfunc.c -o temp/runtime/o_nfunc.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
|
gcc -c src/runtime/o_func.c -o temp/runtime/o_func.o $FLAGS
|
||||||
|
|
||||||
@@ -81,6 +82,7 @@ gcc src/main.c src/debug.c \
|
|||||||
temp/runtime/runtime.o \
|
temp/runtime/runtime.o \
|
||||||
temp/runtime/runtime_error.o \
|
temp/runtime/runtime_error.o \
|
||||||
temp/runtime/o_builtins.o \
|
temp/runtime/o_builtins.o \
|
||||||
|
temp/runtime/o_closure.o \
|
||||||
temp/runtime/o_nfunc.o \
|
temp/runtime/o_nfunc.o \
|
||||||
temp/runtime/o_func.o \
|
temp/runtime/o_func.o \
|
||||||
temp/common/executable.o \
|
temp/common/executable.o \
|
||||||
|
|||||||
@@ -11,14 +11,27 @@ fun fail(p)
|
|||||||
|
|
||||||
#fail(0);
|
#fail(0);
|
||||||
|
|
||||||
fun a()
|
defined_globally = 111;
|
||||||
|
|
||||||
|
fun A()
|
||||||
{
|
{
|
||||||
fun b()
|
print('Hello from A!\n');
|
||||||
|
|
||||||
|
defined_in_A = 10;
|
||||||
|
|
||||||
|
fun B()
|
||||||
{
|
{
|
||||||
print(depth, '\n');
|
defined_in_B = 33;
|
||||||
|
|
||||||
|
print('Hello from B!\n');
|
||||||
|
print('defined_globally = ', defined_globally, '\n');
|
||||||
|
print('defined_in_A = ', defined_in_A, '\n');
|
||||||
|
print('defined_in_B = ', defined_in_B, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
b();
|
B();
|
||||||
|
|
||||||
|
print('defined_in_B = ', defined_in_B, '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
a();
|
A();
|
||||||
+1
-1
@@ -233,7 +233,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
Runtime_SetBuiltins(runtime, builtins);
|
Runtime_SetBuiltins(runtime, builtins);
|
||||||
|
|
||||||
Object *result = run(runtime, (Error*) &error, exe, 0, NULL, 1, NULL, 0);
|
Object *result = run(runtime, (Error*) &error, exe, 0, NULL, NULL, 0);
|
||||||
|
|
||||||
if(result == NULL)
|
if(result == NULL)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#include "../utils/defs.h"
|
||||||
|
#include "../objects/objects.h"
|
||||||
|
|
||||||
|
typedef struct ClosureObject ClosureObject;
|
||||||
|
|
||||||
|
struct ClosureObject {
|
||||||
|
Object base;
|
||||||
|
ClosureObject *prev;
|
||||||
|
Object *vars;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
|
||||||
|
|
||||||
|
static const Type t_closure = {
|
||||||
|
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
|
||||||
|
.name = "closure",
|
||||||
|
.size = sizeof(ClosureObject),
|
||||||
|
.select = select,
|
||||||
|
};
|
||||||
|
|
||||||
|
Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *error)
|
||||||
|
{
|
||||||
|
ClosureObject *obj = (ClosureObject*) Heap_Malloc(heap, &t_closure, error);
|
||||||
|
|
||||||
|
if(obj == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if(parent != NULL && parent->type != &t_closure)
|
||||||
|
{
|
||||||
|
Error_Report(error, 0, "Object is not a closure");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj->prev = (ClosureObject*) parent;
|
||||||
|
obj->vars = new_map;
|
||||||
|
|
||||||
|
return (Object*) obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Object *select(Object *self, Object *key, Heap *heap, Error *err)
|
||||||
|
{
|
||||||
|
ClosureObject *closure = (ClosureObject*) self;
|
||||||
|
|
||||||
|
Object *selected = NULL;
|
||||||
|
|
||||||
|
while(closure != NULL && selected == NULL)
|
||||||
|
{
|
||||||
|
selected = Object_Select(closure->vars, key, heap, err);
|
||||||
|
|
||||||
|
if(err->occurred)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
closure = closure->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ typedef struct {
|
|||||||
Runtime *runtime;
|
Runtime *runtime;
|
||||||
Executable *exe;
|
Executable *exe;
|
||||||
int index, argc;
|
int index, argc;
|
||||||
Object *globals;
|
Object *closure;
|
||||||
} FunctionObject;
|
} FunctionObject;
|
||||||
|
|
||||||
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error);
|
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error);
|
||||||
@@ -74,7 +74,7 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
|
|||||||
// The right amount of arguments was provided.
|
// The right amount of arguments was provided.
|
||||||
argv2 = argv;
|
argv2 = argv;
|
||||||
|
|
||||||
Object *result = run(func->runtime, error, func->exe, func->index, func->globals, 0, argv2, expected_argc);
|
Object *result = run(func->runtime, error, func->exe, func->index, func->closure, argv2, expected_argc);
|
||||||
|
|
||||||
if(argv2 != argv)
|
if(argv2 != argv)
|
||||||
free(argv2);
|
free(argv2);
|
||||||
@@ -82,7 +82,7 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *globals, Heap *heap, Error *error)
|
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *closure, Heap *heap, Error *error)
|
||||||
{
|
{
|
||||||
assert(runtime != NULL);
|
assert(runtime != NULL);
|
||||||
assert(exe != NULL);
|
assert(exe != NULL);
|
||||||
@@ -108,7 +108,7 @@ Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, in
|
|||||||
func->exe = exe_copy;
|
func->exe = exe_copy;
|
||||||
func->index = index;
|
func->index = index;
|
||||||
func->argc = argc;
|
func->argc = argc;
|
||||||
func->globals = globals;
|
func->closure = closure;
|
||||||
|
|
||||||
return (Object*) func;
|
return (Object*) func;
|
||||||
}
|
}
|
||||||
+13
-22
@@ -7,11 +7,10 @@
|
|||||||
#define MAX_FRAMES 16
|
#define MAX_FRAMES 16
|
||||||
|
|
||||||
typedef struct Frame Frame;
|
typedef struct Frame Frame;
|
||||||
|
|
||||||
struct Frame {
|
struct Frame {
|
||||||
Frame *prev;
|
Frame *prev;
|
||||||
Object *locals;
|
Object *locals;
|
||||||
Object *globals;
|
Object *closure;
|
||||||
Executable *exe;
|
Executable *exe;
|
||||||
int index, used;
|
int index, used;
|
||||||
};
|
};
|
||||||
@@ -838,7 +837,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
|
|
||||||
Object *locations[] = {
|
Object *locations[] = {
|
||||||
runtime->frame->locals,
|
runtime->frame->locals,
|
||||||
runtime->frame->globals,
|
runtime->frame->closure,
|
||||||
Runtime_GetBuiltins(runtime),
|
Runtime_GetBuiltins(runtime),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -914,7 +913,12 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
assert(ops[0].type == OPTP_INT);
|
assert(ops[0].type == OPTP_INT);
|
||||||
assert(ops[1].type == OPTP_INT);
|
assert(ops[1].type == OPTP_INT);
|
||||||
|
|
||||||
Object *obj = Object_FromNojaFunction(runtime, runtime->frame->exe, ops[0].as_int, ops[1].as_int, runtime->frame->globals, runtime->heap, error);
|
Object *closure = Object_NewClosure(runtime->frame->closure, runtime->frame->locals, Runtime_GetHeap(runtime), error);
|
||||||
|
|
||||||
|
if(closure == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Object *obj = Object_FromNojaFunction(runtime, runtime->frame->exe, ops[0].as_int, ops[1].as_int, closure, runtime->heap, error);
|
||||||
|
|
||||||
if(obj == NULL)
|
if(obj == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1035,7 +1039,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *globals, _Bool is_global_scope, Object **argv, int argc)
|
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc)
|
||||||
{
|
{
|
||||||
assert(runtime != NULL);
|
assert(runtime != NULL);
|
||||||
assert(error != NULL);
|
assert(error != NULL);
|
||||||
@@ -1055,28 +1059,15 @@ Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *
|
|||||||
Frame frame;
|
Frame frame;
|
||||||
{
|
{
|
||||||
frame.prev = NULL;
|
frame.prev = NULL;
|
||||||
|
frame.closure = closure;
|
||||||
if(is_global_scope)
|
|
||||||
{
|
|
||||||
if(globals == NULL)
|
|
||||||
globals = Object_NewMap(-1, runtime->heap, error);
|
|
||||||
|
|
||||||
frame.globals = globals;
|
|
||||||
frame.locals = frame.globals;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frame.globals = globals;
|
|
||||||
frame.locals = Object_NewMap(-1, runtime->heap, error);
|
frame.locals = Object_NewMap(-1, runtime->heap, error);
|
||||||
}
|
|
||||||
|
|
||||||
if(frame.locals == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
frame.exe = Executable_Copy(exe);
|
frame.exe = Executable_Copy(exe);
|
||||||
frame.index = index;
|
frame.index = index;
|
||||||
frame.used = 0;
|
frame.used = 0;
|
||||||
|
|
||||||
|
if(frame.locals == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if(frame.exe == NULL)
|
if(frame.exe == NULL)
|
||||||
{
|
{
|
||||||
Error_Report(error, 1, "Failed to copy executable");
|
Error_Report(error, 1, "Failed to copy executable");
|
||||||
|
|||||||
@@ -23,9 +23,10 @@ Snapshot *Snapshot_New(Runtime *runtime);
|
|||||||
void Snapshot_Free(Snapshot *snapshot);
|
void Snapshot_Free(Snapshot *snapshot);
|
||||||
void Snapshot_Print(Snapshot *snapshot, FILE *fp);
|
void Snapshot_Print(Snapshot *snapshot, FILE *fp);
|
||||||
|
|
||||||
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *globals, _Bool is_global_scope, Object **argv, int argc);
|
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc);
|
||||||
|
|
||||||
|
Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *error);
|
||||||
Object *Object_NewBuiltinsMap(Runtime *runtime, Heap *heap, Error *err);
|
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_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, Object *globals, Heap *heap, Error *error);
|
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *closure, Heap *heap, Error *error);
|
||||||
#endif
|
#endif
|
||||||
Reference in New Issue
Block a user