now variables can access the global scope
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
|
||||
depth = 9;
|
||||
|
||||
fun fail(p)
|
||||
{
|
||||
if p < depth:
|
||||
fail(p+1, depth, fail);
|
||||
else
|
||||
assert(false);
|
||||
}
|
||||
|
||||
#fail(0);
|
||||
|
||||
fun a()
|
||||
{
|
||||
fun b()
|
||||
{
|
||||
print(depth, '\n');
|
||||
}
|
||||
|
||||
b();
|
||||
}
|
||||
|
||||
a();
|
||||
@@ -1,17 +1,5 @@
|
||||
|
||||
|
||||
l = [1, 2, 3, 4];
|
||||
|
||||
print('The list contains ', count(l), ' items.\n');
|
||||
print('The list is: ', l, '.\n');
|
||||
|
||||
|
||||
fun fail(p, fail)
|
||||
{
|
||||
if p == 5:
|
||||
assert(false);
|
||||
else
|
||||
fail(p+1, fail);
|
||||
}
|
||||
|
||||
fail(0, fail);
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
fun index(req)
|
||||
return {code: 200, 'body': 'Hello, world!'};
|
||||
|
||||
routes = {
|
||||
'/': index,
|
||||
'/groups': list_groups
|
||||
}
|
||||
|
||||
res = serve(8080, routes);
|
||||
+1
-1
@@ -233,7 +233,7 @@ int main(int argc, char **argv)
|
||||
|
||||
Runtime_SetBuiltins(runtime, builtins);
|
||||
|
||||
Object *result = run(runtime, (Error*) &error, exe, 0, NULL, 0);
|
||||
Object *result = run(runtime, (Error*) &error, exe, 0, NULL, 1, NULL, 0);
|
||||
|
||||
if(result == NULL)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ typedef struct {
|
||||
Runtime *runtime;
|
||||
Executable *exe;
|
||||
int index, argc;
|
||||
Object *globals;
|
||||
} FunctionObject;
|
||||
|
||||
static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error);
|
||||
@@ -73,7 +74,7 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
|
||||
// The right amount of arguments was provided.
|
||||
argv2 = argv;
|
||||
|
||||
Object *result = run(func->runtime, error, func->exe, func->index, argv2, expected_argc);
|
||||
Object *result = run(func->runtime, error, func->exe, func->index, func->globals, 0, argv2, expected_argc);
|
||||
|
||||
if(argv2 != argv)
|
||||
free(argv2);
|
||||
@@ -81,7 +82,7 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap,
|
||||
return result;
|
||||
}
|
||||
|
||||
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Heap *heap, Error *error)
|
||||
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *globals, Heap *heap, Error *error)
|
||||
{
|
||||
assert(runtime != NULL);
|
||||
assert(exe != NULL);
|
||||
@@ -107,6 +108,7 @@ Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, in
|
||||
func->exe = exe_copy;
|
||||
func->index = index;
|
||||
func->argc = argc;
|
||||
func->globals = globals;
|
||||
|
||||
return (Object*) func;
|
||||
}
|
||||
+41
-25
@@ -10,7 +10,8 @@ typedef struct Frame Frame;
|
||||
|
||||
struct Frame {
|
||||
Frame *prev;
|
||||
Object *vars;
|
||||
Object *locals;
|
||||
Object *globals;
|
||||
Executable *exe;
|
||||
int index, used;
|
||||
};
|
||||
@@ -645,7 +646,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
if(key == NULL)
|
||||
return 0;
|
||||
|
||||
if(!Object_Insert(runtime->frame->vars, key, val, runtime->heap, error))
|
||||
if(!Object_Insert(runtime->frame->locals, key, val, runtime->heap, error))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -835,28 +836,29 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
if(key == NULL)
|
||||
return 0;
|
||||
|
||||
Object *obj = Object_Select(runtime->frame->vars, key, runtime->heap, error);
|
||||
Object *locations[] = {
|
||||
runtime->frame->locals,
|
||||
runtime->frame->globals,
|
||||
Runtime_GetBuiltins(runtime),
|
||||
};
|
||||
|
||||
Object *obj = NULL;
|
||||
|
||||
if(obj == NULL && error->occurred == 0)
|
||||
for(int p = 0; obj == NULL && (unsigned int) p < sizeof(locations)/sizeof(locations[0]); p += 1)
|
||||
{
|
||||
// Variable not defined locally.
|
||||
if(locations[p] == NULL)
|
||||
continue;
|
||||
|
||||
Object *builtins = Runtime_GetBuiltins(runtime);
|
||||
|
||||
if(builtins != NULL)
|
||||
obj = Object_Select(builtins, key, runtime->heap, error);
|
||||
|
||||
if(obj == NULL)
|
||||
{
|
||||
if(error->occurred == 0)
|
||||
// There's no such variable.
|
||||
Error_Report(error, 1, "Reference to undefined variable \"%s\"", ops[0].as_string);
|
||||
return 0;
|
||||
}
|
||||
obj = Object_Select(locations[p], key, Runtime_GetHeap(runtime), error);
|
||||
}
|
||||
else
|
||||
if(obj == NULL)
|
||||
|
||||
if(obj == NULL)
|
||||
{
|
||||
if(error->occurred == 0)
|
||||
// There's no such variable.
|
||||
Error_Report(error, 1, "Reference to undefined variable \"%s\"", ops[0].as_string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!Runtime_Push(runtime, error, obj))
|
||||
return 0;
|
||||
@@ -912,7 +914,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
assert(ops[0].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->heap, error);
|
||||
Object *obj = Object_FromNojaFunction(runtime, runtime->frame->exe, ops[0].as_int, ops[1].as_int, runtime->frame->globals, runtime->heap, error);
|
||||
|
||||
if(obj == NULL)
|
||||
return 0;
|
||||
@@ -1033,7 +1035,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
return 1;
|
||||
}
|
||||
|
||||
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object **argv, int argc)
|
||||
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *globals, _Bool is_global_scope, Object **argv, int argc)
|
||||
{
|
||||
assert(runtime != NULL);
|
||||
assert(error != NULL);
|
||||
@@ -1053,14 +1055,28 @@ Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *
|
||||
Frame frame;
|
||||
{
|
||||
frame.prev = NULL;
|
||||
frame.vars = Object_NewMap(-1, runtime->heap, error);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if(frame.locals == NULL)
|
||||
return NULL;
|
||||
|
||||
frame.exe = Executable_Copy(exe);
|
||||
frame.index = index;
|
||||
frame.used = 0;
|
||||
|
||||
if(frame.vars == NULL)
|
||||
return NULL;
|
||||
|
||||
if(frame.exe == NULL)
|
||||
{
|
||||
Error_Report(error, 1, "Failed to copy executable");
|
||||
|
||||
@@ -23,9 +23,9 @@ Snapshot *Snapshot_New(Runtime *runtime);
|
||||
void Snapshot_Free(Snapshot *snapshot);
|
||||
void Snapshot_Print(Snapshot *snapshot, FILE *fp);
|
||||
|
||||
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object **argv, int argc);
|
||||
Object *run(Runtime *runtime, Error *error, Executable *exe, int index, Object *globals, _Bool is_global_scope, 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);
|
||||
Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *globals, Heap *heap, Error *error);
|
||||
#endif
|
||||
Reference in New Issue
Block a user