From d70fa148567b1bcb8c743433a015c1732ea21915 Mon Sep 17 00:00:00 2001 From: Francesco Cozzuto Date: Tue, 30 Nov 2021 19:43:38 +0100 Subject: [PATCH] added stack trace log on error --- 3p/include/llhs.h | 80 ++++++++++++++++++++++++++++++++++++++++ 3p/libs/libllhs.a | Bin 0 -> 95366 bytes samples/list.noja | 9 ++++- samples/webservice.noja | 10 +++++ src/main.c | 17 ++++++++- src/runtime/runtime.c | 73 +++++++++++++++++++++++++++++------- src/runtime/runtime.h | 3 +- 7 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 3p/include/llhs.h create mode 100644 3p/libs/libllhs.a create mode 100644 samples/webservice.noja diff --git a/3p/include/llhs.h b/3p/include/llhs.h new file mode 100644 index 0000000..27d7019 --- /dev/null +++ b/3p/include/llhs.h @@ -0,0 +1,80 @@ + +#define MAX_HEADERS 16 +#define MAX_URI 4096 +#define MAX_BODY (1024 * 1024) +#define MAX_HNAME 128 +#define MAX_HBODY 1024 + +#define BUFFER_INIT_SIZE 256 +#define BUFFER_GROW_FACTOR 2 +#define BUFFER_GROW_ADDEND 0 + +#define BACKLOG 128 +#define POLL_TIMEOUT 5000 +#define MAX_POLL_EVENTS 64 +#define IMPLICIT_LENGTH 1 + +#define MAX_CLIENTS 256 +#define MAX_ALIVE 64 + +typedef void llhs_response; + +typedef enum { + llhs_HTTP_0_9, + llhs_HTTP_1_0, + llhs_HTTP_1_1, +} llhs_version; + +typedef enum { + llhs_GET, + llhs_PUT, + llhs_POST, + llhs_HEAD, + llhs_TRACE, + llhs_PATCH, + llhs_DELETE, + llhs_OPTIONS, + llhs_CONNECT, +} llhs_method; + +typedef struct { + const char *name; + const char *body; + int namel; + int bodyl; +} llhs_header; + +typedef struct { + llhs_version version; + llhs_method method; + const char *URI; + int URIl; + llhs_header headers[MAX_HEADERS]; + int headerc; + const void *body; + int bodyl; +} llhs_request; + +typedef struct { + _Bool occurred; + char message[256]; + int length; + const char *file, + *func; + int line; +} llhs_error; + +typedef void (*llhs_callback)(void *userp, const llhs_request *req, llhs_response *res); +typedef void (*llhs_logger )(void *userp, const char *level, const char *msg); + +_Bool llhs_serve(unsigned short port, void *userp, llhs_callback callback, llhs_logger logger, llhs_error *error); + +_Bool llhs_match (const char *x, const char *y); +_Bool llhs_match2(const char *x, const char *y, int xl, int yl); +const char *llhs_getheader(llhs_request *res, const char *name); + +void llhs_setcode (llhs_response *res, int code); +_Bool llhs_setbody (llhs_response *res, const void *body, int size); +void llhs_setbody2 (llhs_response *res, void *body, int bodyl, void (*free)(void *addr)); +_Bool llhs_setheader (llhs_response *res, const char *name, const char *body); +_Bool llhs_setheader2(llhs_response *res, const char *name, int body); diff --git a/3p/libs/libllhs.a b/3p/libs/libllhs.a new file mode 100644 index 0000000000000000000000000000000000000000..167b5c2ef0a11581f50a5dad4be6f21f22a5625e GIT binary patch literal 95366 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 CYFFX_ literal 0 HcmV?d00001 diff --git a/samples/list.noja b/samples/list.noja index f23b286..ddb3efd 100644 --- a/samples/list.noja +++ b/samples/list.noja @@ -3,4 +3,11 @@ l = [1, 2, 3, 4]; print('The list contains ', count(l), ' items.\n'); -print('The list is: ', l, '.\n'); \ No newline at end of file +print('The list is: ', l, '.\n'); + + +fun fail() + assert(false); + + +fail(); \ No newline at end of file diff --git a/samples/webservice.noja b/samples/webservice.noja new file mode 100644 index 0000000..0940026 --- /dev/null +++ b/samples/webservice.noja @@ -0,0 +1,10 @@ + +fun index(req) + return {code: 200, 'body': 'Hello, world!'}; + +routes = { + '/': index, + '/groups': list_groups +} + +res = serve(8080, routes); \ No newline at end of file diff --git a/src/main.c b/src/main.c index 5104b8c..9ed9750 100644 --- a/src/main.c +++ b/src/main.c @@ -217,7 +217,22 @@ int main(int argc, char **argv) RuntimeError error; RuntimeError_Init(&error, runtime); - + + Object *builtins = Object_NewBuiltinsMap(runtime, Runtime_GetHeap(runtime), (Error*) &error); + + if(builtins == NULL) + { + fprintf(stderr, "Couldn't initialize runtime.\n"); + Debug_Free(dbg); + Source_Free(src); + Executable_Free(exe); + RuntimeError_Free(&error); + Runtime_Free(runtime); + return 1; + } + + Runtime_SetBuiltins(runtime, builtins); + Object *result = run(runtime, (Error*) &error, exe, 0, NULL, 0); if(result == NULL) diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index 08ca799..c262c12 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -101,17 +101,16 @@ void Runtime_Free(Runtime *runtime) free(runtime); } -Object *Runtime_GetBuiltins(Runtime *runtime, Error *error) +Object *Runtime_GetBuiltins(Runtime *runtime) { - if(runtime->builtins == NULL) - { - runtime->builtins = Object_NewBuiltinsMap(runtime, Runtime_GetHeap(runtime), error); - if(runtime->builtins == NULL) - return NULL; - } return runtime->builtins; } +void Runtime_SetBuiltins(Runtime *runtime, Object *builtins) +{ + runtime->builtins = builtins; +} + _Bool Runtime_Push(Runtime *runtime, Error *error, Object *obj) { assert(runtime != NULL); @@ -239,7 +238,56 @@ void Snapshot_Print(Snapshot *snapshot, FILE *fp) assert(snapshot != NULL); assert(fp != NULL); - fprintf(fp, " (Snapshot can't be printed yet)\n"); + fprintf(fp, "Stack trace:\n"); + + for(int i = 0; i < snapshot->depth; i += 1) + { + SnapshotNode node = snapshot->nodes[i]; + + Executable *exe = node.exe; + Source *src = Executable_GetSource(exe); + + const char *name; + { + name = NULL; + + if(src != NULL) + name = Source_GetName(src); + + if(name == NULL) + name = "(unnamed)"; + } + + int line; + { + if(src == NULL) + line = 0; + else + { + line = 1; + + const char *body = Source_GetBody(src); + int offset = Executable_GetInstrOffset(exe, node.index); + + int i = 0; + + while(i < offset) + { + if(body[i] == '\n') + line += 1; + + i += 1; + } + } + } + + if(line == 0) + fprintf(fp, "\t#%d %s\n", i, name); + else + fprintf(fp, "\t#%d %s:%d\n", i, name, line); + } + + //fprintf(fp, " (Snapshot can't be printed yet)\n"); } static Object *do_math_op(Object *lop, Object *rop, Opcode opcode, Heap *heap, Error *error) @@ -793,13 +841,10 @@ static _Bool step(Runtime *runtime, Error *error) { // Variable not defined locally. - Object *builtins = Runtime_GetBuiltins(runtime, error); + Object *builtins = Runtime_GetBuiltins(runtime); - if(builtins == NULL) - // Failed to create builtins map. - return 0; - - obj = Object_Select(runtime->builtins, key, runtime->heap, error); + if(builtins != NULL) + obj = Object_Select(builtins, key, runtime->heap, error); if(obj == NULL) { diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 1a2949a..406e289 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -13,7 +13,8 @@ _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); +Object* Runtime_GetBuiltins(Runtime *runtime); +void Runtime_SetBuiltins(Runtime *runtime, Object *builtins); int Runtime_GetCurrentIndex(Runtime *runtime); Executable *Runtime_GetCurrentExecutable(Runtime *runtime);