From 1671d178e4f87bf3538b4dca30f8530da9bf8ba5 Mon Sep 17 00:00:00 2001 From: cozis Date: Fri, 9 Dec 2022 14:26:31 +0100 Subject: [PATCH] example scripts update; new BUILD_MODE=CHECKMEM; patched some memory leaks --- examples/http.noja | 58 +++++++++---------------- examples/json.noja | 92 +++++++++++++++++++--------------------- examples/scan.noja | 10 +++-- makefile | 5 ++- src/lib/builtins/basic.c | 26 +++++++++--- 5 files changed, 94 insertions(+), 97 deletions(-) diff --git a/examples/http.noja b/examples/http.noja index 4628aa4..339ea2d 100644 --- a/examples/http.noja +++ b/examples/http.noja @@ -46,8 +46,7 @@ fun parseMethod(scan: Scanner) { method = ""; do { method = cat(method, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } while char != none and isUpper(char); return method, none; @@ -59,16 +58,13 @@ fun parsePort(scan: Scanner) { char = scan->current(); if char == ":" and isDigit(scan->hint(1)): { - scan->consume(); # Skip the ":" - char = scan->current(); + char = scan->consume(); # Skip the ":" port = 0; do { - digit = ord(char) - - ord("0"); + digit = ord(char) - ord("0"); port = port * 10 + digit; - scan->consume(); - char = scan->current(); + char = scan->consume(); } while char != none and isDigit(char); } return port; @@ -90,8 +86,7 @@ fun parseHost(scan: Scanner) { name = ""; do { name = cat(name, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } while char != none and isHostname(char); port = parsePort(scan); @@ -104,8 +99,7 @@ fun parsePath(scan: Scanner) { char = scan->current(); if char != none and char == "/": { path = cat(path, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } else { if char == none or not isPChar(char): return none, "Invalid character in place of path"; @@ -114,14 +108,12 @@ fun parsePath(scan: Scanner) { while char != none and isPChar(char): { do { path = cat(path, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } while char != none and isPChar(char); if char == none or char != "/": break; path = cat(path, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } return path; @@ -139,12 +131,9 @@ fun parseQuery(scan: Scanner) { char = scan->current(); if char != none and char == "?": { - scan->consume(); # Consume the "?" query = ""; - while isQuery(char = scan->current()): { + while isQuery(char = scan->consume()): query = cat(query, char); - scan->consume(); - } } else query = none; @@ -161,12 +150,9 @@ fun parseFragment(scan: Scanner) { char = scan->current(); if char != none and char == "#": { - scan->consume(); # Consume the "#" fragment = ""; - while isFragment(char = scan->current()): { + while isFragment(char = scan->consume()): fragment = cat(fragment, char); - scan->consume(); - } } else fragment = none; @@ -207,8 +193,7 @@ fun parseSchema(scan: Scanner) { schema = ""; do { schema = cat(schema, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } while isSchema(char); if char == ":": @@ -230,7 +215,7 @@ fun parseURL(scan: Scanner) { schema = parseSchema(scan); if followsAuthority(scan): { - consume(scan, 2); + scan->consume(2); host, error = parseHost(scan); if error != none: @@ -272,14 +257,12 @@ fun parseVersion(scan: Scanner) { or scan->hint(4) != "/" or not isDigit(scan->hint(5)): return none, "Invalid version token"; - scan->consume(5); - major = ord(scan->current()) - - ord("0"); + char = scan->consume(5); + major = ord(char) - ord("0"); if scan->hint(1) != "." and isDigit(scan->hint(2)): { - scan->consume(2); - minor = ord(scan->current()) - - ord("0"); + char = scan->consume(2); + minor = ord(char) - ord("0"); } else minor = 0; scan->consume(); @@ -345,22 +328,19 @@ fun parse(src: String) { name = ""; do { name = cat(name, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } while char != ":" and char != none; if char == none: return none, "Invalid header (missing \":\" after name)"; scan->consume(); - scan->consumeSpaces(); - char = scan->current(); + char = scan->consumeSpaces(); # Header body until \r body = ""; do { body = cat(body, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } while char != "\r" and char != none; headers[name] = body; diff --git a/examples/json.noja b/examples/json.noja index 4427259..00a44d4 100644 --- a/examples/json.noja +++ b/examples/json.noja @@ -3,18 +3,17 @@ scan = import("scan.noja"); newScanner = scan.newScanner; Scanner = scan.Scanner; isDigit = scan.isDigit; +ord = string.ord; fun parseString(scan: Scanner) { assert(scan->current() == '"'); - scan->consume(); # Consume the opening " + char = scan->consume(); # Consume the opening " temp = ""; - char = scan->current(); while char != '"' and char != none: { temp = string.cat(temp, char); - scan->consume(); - char = scan->current(); + char = scan->consume(); } if char == none: { @@ -36,16 +35,17 @@ fun parseObject(scan: Scanner) { scan->consume(); obj = {}; - scan->consumeSpaces(); - if scan->current() != '}': do { + char = scan->consumeSpaces(); + if char != '}': do { + key, err = parseValue(scan); if err != none: return none, err; if type(key) != String: return none, "Object key isn't a string"; - scan->consumeSpaces(); - if scan->current() != ':': + char = scan->consumeSpaces(); + if char != ':': return none, "Missing ':' separator after key"; scan->consume(); @@ -57,11 +57,11 @@ fun parseObject(scan: Scanner) { return none, "Duplicate key in object"; obj[key] = val; - scan->consumeSpaces(); - if scan->current() == '}': + char = scan->consumeSpaces(); + if char == '}': done = true; else { - if scan->current() != ',': + if char != ',': return none, "Invalid character where either ',' or '}' were expected"; scan->consume(); # Consume the "," done = false; @@ -79,16 +79,16 @@ fun parseArray(scan: Scanner) { array = []; - scan->consumeSpaces(); - if scan->current() != ']': do { + char = scan->consumeSpaces(); + if char != ']': do { val, err = parseValue(scan); if err != none: return none, err; array[count(array)] = val; - scan->consumeSpaces(); - if scan->current() == ']': + char = scan->consumeSpaces(); + if char == ']': done = true; else { if scan->current() != ',': @@ -105,21 +105,21 @@ fun parseArray(scan: Scanner) { fun parseFalse(scan: Scanner) { assert(scan->current() == 'f'); - scan->consume(); + char = scan->consume(); - if scan->current() != 'a': + if char != 'a': return none, "Invalid character after 'f'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 'l': + if char != 'l': return none, "Invalid character after 'fa'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 's': + if char != 's': return none, "Invalid character after 'fal'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 'e': + if char != 'e': return none, "Invalid character after 'fals'"; scan->consume(); @@ -129,17 +129,17 @@ fun parseFalse(scan: Scanner) { fun parseTrue(scan: Scanner) { assert(scan->current() == 't'); - scan->consume(); + char = scan->consume(); - if scan->current() != 'r': + if char != 'r': return none, "Invalid character after 't'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 'u': + if char != 'u': return none, "Invalid character after 'tr'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 'e': + if char != 'e': return none, "Invalid character after 'tru'"; scan->consume(); @@ -149,17 +149,17 @@ fun parseTrue(scan: Scanner) { fun parseNull(scan: Scanner) { assert(scan->current() == 'n'); - scan->consume(); + char = scan->consume(); - if scan->current() != 'u': + if char != 'u': return none, "Invalid character after 'n'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 'l': + if char != 'l': return none, "Invalid character after 'nu'"; - scan->consume(); + char = scan->consume(); - if scan->current() != 'l': + if char != 'l': return none, "Invalid character after 'nul'"; scan->consume(); @@ -167,9 +167,8 @@ fun parseNull(scan: Scanner) { } fun integerFromDigit(char: String) { - assert(count(char) == 1); - return string.ord(char) - - string.ord('0'); + assert(isDigit(char)); + return ord(char) - ord('0'); } fun parseNumber(scan: Scanner) { @@ -180,9 +179,8 @@ fun parseNumber(scan: Scanner) { if char == '+' or char == '-': { sign = {'+': 1, '-': -1}[char]; - scan->consume(); - char = scan->current(); + char = scan->consume(); if not isDigit(char): return none, "Invalid character after +/-"; } @@ -194,23 +192,20 @@ fun parseNumber(scan: Scanner) { n = integerFromDigit(char); temp = temp * 10 + n; - scan->consume(); - char = scan->current(); + char = scan->consume(); } while isDigit(char); if char == '.' and isDigit(scan->hint(1)): { - scan->consume(); # Consume the dot - char = scan->current(); - + char = scan->consume(); # Consume the dot + q = 1.0; do { q = q / 10; n = integerFromDigit(char); temp = temp + q * n; - scan->consume(); - char = scan->current(); + char = scan->consume(); } while isDigit(char); } @@ -240,8 +235,7 @@ fun parseValue(scan: Scanner) { '9': parseNumber }; - scan->consumeSpaces(); - char = scan->current(); + char = scan->consumeSpaces(); if char == none: { val = none; err = "Source ended where a value was expected"; diff --git a/examples/scan.noja b/examples/scan.noja index 2b6b417..24a0779 100644 --- a/examples/scan.noja +++ b/examples/scan.noja @@ -26,11 +26,15 @@ fun consume(scan: Scanner, n: int = 1) { assert(n > 0); limit = count(scan.src); scan.i = min(scan.i + n, limit); + return current(scan); } -fun consumeSpaces(scan: Scanner) - while isSpace(current(scan)): - consume(scan); +fun consumeSpaces(scan: Scanner) { + char = current(scan); + while isSpace(char): + char = consume(scan); + return char; +} fun newScanner(src: String) { scan = { diff --git a/makefile b/makefile index c430a75..d0960a0 100644 --- a/makefile +++ b/makefile @@ -52,7 +52,7 @@ LFLAGS = -lm # Can be one of: YES, NO USING_VALGRIND = NO -# May be one of: COVERAGE, RELEASE, DEBUG +# May be one of: COVERAGE, RELEASE, DEBUG, CHECKMEM BUILD_MODE = RELEASE # Changing the BUILD_MODE will add one of the @@ -62,6 +62,9 @@ BUILD_MODE = RELEASE CFLAGS_DEBUG = -DDEBUG -g LFLAGS_DEBUG = +CFLAGS_CHECKMEM = -fsanitize=address -g +LFLAGS_CHECKMEM = -fsanitize=address + CFLAGS_RELEASE = -DNDEBUG -O3 LFLAGS_RELEASE = diff --git a/src/lib/builtins/basic.c b/src/lib/builtins/basic.c index 708676d..a6e9129 100644 --- a/src/lib/builtins/basic.c +++ b/src/lib/builtins/basic.c @@ -134,13 +134,18 @@ static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object UNUSED(errname); Object *o_none = Object_NewNone(heap, error); - if(o_none == NULL) + if(o_none == NULL) { + Source_Free(src); return -1; + } Object *o_err = Object_FromString(sub_error.message, -1, heap, error); - if(o_err == NULL) + if(o_err == NULL) { + Source_Free(src); return -1; + } + Source_Free(src); Error_Free(&sub_error); rets[0] = o_none; rets[1] = o_err; @@ -156,19 +161,30 @@ static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object UNUSED(errname); Object *o_none = Object_NewNone(heap, error); - if(o_none == NULL) return -1; + if(o_none == NULL) { + Source_Free(src); + Executable_Free(exe); + return -1; + } Object *o_err = Object_FromString(sub_error.message, -1, heap, error); - if(o_err == NULL) return -1; - + if(o_err == NULL) { + Source_Free(src); + Executable_Free(exe); + return -1; + } Error_Free(&sub_error); rets[0] = o_none; rets[1] = o_err; + Source_Free(src); + Executable_Free(exe); return 2; } ASSERT(retc == 1); Error_Free(&sub_error); + Source_Free(src); + Executable_Free(exe); rets[0] = sub_rets[0]; return 1; }