diff --git a/samples/func.noja b/samples/func.noja index 13fad58..f0d6e0f 100644 --- a/samples/func.noja +++ b/samples/func.noja @@ -1,6 +1,6 @@ fun k(k) - return k(); + return k(k); k(k); diff --git a/src/debug.c b/src/debug.c index 9ef64ad..0dee9cf 100644 --- a/src/debug.c +++ b/src/debug.c @@ -267,7 +267,8 @@ _Bool Debug_Callback(Runtime *runtime, void *userp) "step .............. Run an instruction\n" "quit .............. Stop execution\n" "continue .......... Run until a breakpoint or the end of the code is reached\n" - "breakpoint ........ Add a breakpoint\n"); + "breakpoint ........ Add a breakpoint\n" + "stack ............. Show the contents of the stack\n"); } else if(!strcmp(argv[1], "help")) { @@ -339,6 +340,17 @@ _Bool Debug_Callback(Runtime *runtime, void *userp) " | a line number, a character offset or an instruction index.\n" "\n"); } + else if(!strcmp(argv[1], "stack")) + { + fprintf(stderr, + "\n" + " Command | stack\n" + " | \n" + " Usage | > stack\n" + " | \n" + " Description | Show the contents of the stack.\n" + "\n"); + } else { fprintf(stdout, "Unknown command \"%s\".\n", argv[1]); @@ -436,6 +448,35 @@ _Bool Debug_Callback(Runtime *runtime, void *userp) { return 1; } + else if(!strcmp(argv[0], "stack")) + { + Stack *stack = Runtime_GetStack(runtime); + assert(stack != NULL); + + Error error; + Error_Init(&error); + + if(Stack_Size(stack) == 0) + fprintf(stderr, "The stack is empty.\n"); + + for(int i = 0; i < (int) Stack_Size(stack); i += 1) + { + Object *obj = Stack_Top(stack, -i); + assert(obj != NULL); + + fprintf(stderr, " %d | ", i); + Object_Print(obj, stderr, &error); + + if(error.occurred) + { + Error_Free(&error); + Error_Init(&error); + fprintf(stderr, "(unprintable)"); + } + + fprintf(stderr, "\n"); + } + } else if(!strcmp(argv[0], "quit")) { return 0; diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 9153d03..9d1973b 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -4,7 +4,7 @@ #include "runtime.h" #define MAX_FRAME_STACK 16 -#define MAX_FRAMES 1024 +#define MAX_FRAMES 16 typedef struct Frame Frame; @@ -25,6 +25,11 @@ struct xRuntime { Heap *heap; }; +Stack *Runtime_GetStack(Runtime *runtime) +{ + return Stack_Copy(runtime->stack, 1); +} + Heap *Runtime_GetHeap(Runtime *runtime) { return runtime->heap; diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index e70d4c4..ca877f9 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -2,6 +2,7 @@ #define RUNTIME_H #include // meh.. just for the definition of FILE. #include "../utils/error.h" +#include "../utils/stack.h" #include "../objects/objects.h" #include "../common/executable.h" @@ -11,6 +12,7 @@ void Runtime_Free(Runtime *runtime); _Bool Runtime_Pop(Runtime *runtime, Error *error, unsigned int n); _Bool Runtime_Push(Runtime *runtime, Error *error, Object *obj); Heap* Runtime_GetHeap(Runtime *runtime); +Stack* Runtime_GetStack(Runtime *runtime); Object* Runtime_GetBuiltins(Runtime *runtime, Error *error); int Runtime_GetCurrentIndex(Runtime *runtime); Executable *Runtime_GetCurrentExecutable(Runtime *runtime); diff --git a/src/utils/stack.c b/src/utils/stack.c index 1fc2e97..b695c50 100644 --- a/src/utils/stack.c +++ b/src/utils/stack.c @@ -1,12 +1,20 @@ +#include #include #include "stack.h" #include "defs.h" struct xStack { - unsigned int size, used; - void *body[]; + unsigned int size, + used; + int refs; + void *body[]; }; +_Bool Stack_IsReadOnlyCopy(Stack *s) +{ + return (uintptr_t) s & (uintptr_t) 1; +} + void *Stack_New(int size) { if(size < 0) @@ -17,15 +25,26 @@ void *Stack_New(int size) if(s == NULL) return NULL; + assert((intptr_t) s % 8 == 0); + s->size = size; s->used = 0; + s->refs = 1; return s; } +static Stack *unmark(Stack *s) +{ + return (Stack*) ((intptr_t) s & ~ (intptr_t) 1); +} + void *Stack_Top(Stack *s, int n) { assert(n <= 0); + // Remove readonly bit. + s = unmark(s); + if(s->used == 0) return NULL; @@ -37,6 +56,9 @@ void *Stack_Top(Stack *s, int n) _Bool Stack_Pop(Stack *s, unsigned int n) { + if(Stack_IsReadOnlyCopy(s)) + return 0; + if(s->used < n) return 0; @@ -49,6 +71,9 @@ _Bool Stack_Push(Stack *s, void *item) assert(s != NULL); assert(item != NULL); + if(Stack_IsReadOnlyCopy(s)) + return 0; + if(s->used == s->size) return 0; @@ -57,17 +82,51 @@ _Bool Stack_Push(Stack *s, void *item) return 1; } +Stack *Stack_Copy(Stack *s, _Bool readonly) +{ + if(Stack_IsReadOnlyCopy(s)) + { + // Reference is readonly, + // so the copy must be + // readonly. + readonly = 1; + + // Remove readonly bit. + s = unmark(s); + } + + s->refs += 1; + + if(readonly) + return (Stack*) ((uintptr_t) s | (intptr_t) 1); + else + return s; +} + void Stack_Free(Stack *s) { - free(s); + // Remove readonly bit. + s = unmark(s); + + s->refs -= 1; + assert(s->refs >= 0); + + if(s->refs == 0) + free(s); } unsigned int Stack_Size(Stack *s) { + // Remove readonly bit. + s = unmark(s); + return s->used; } unsigned int Stack_Capacity(Stack *s) { + // Remove readonly bit. + s = unmark(s); + return s->size; } \ No newline at end of file diff --git a/src/utils/stack.h b/src/utils/stack.h index e440f77..7da5e94 100644 --- a/src/utils/stack.h +++ b/src/utils/stack.h @@ -7,5 +7,7 @@ _Bool Stack_Pop(Stack *s, unsigned int n); _Bool Stack_Push(Stack *s, void *item); void Stack_Free(Stack *s); unsigned int Stack_Size(Stack *s); +Stack *Stack_Copy(Stack *s, _Bool readonly); unsigned int Stack_Capacity(Stack *s); +_Bool Stack_IsReadOnlyCopy(Stack *s); #endif \ No newline at end of file