diff --git a/examples/algorithms/bubble_sort.noja b/examples/algorithms/bubble_sort.noja index 8dd635c..79f4667 100644 --- a/examples/algorithms/bubble_sort.noja +++ b/examples/algorithms/bubble_sort.noja @@ -1,9 +1,4 @@ -fun dummy() {} -Func = type(dummy); -NFunc = type(print); # The function type is not a built-in at the moment, - # but we can define it manually. - fun copyList(list: List) { list2 = []; @@ -17,10 +12,10 @@ fun copyList(list: List) { return list2; } -fun numericLess(a: int | float, b: int | float) +fun numericLess(a: Numeric, b: Numeric) return a < b; -fun bubbleSort(list: List, less: NFunc | Func = numericLess) { +fun bubbleSort(list: List, less: Callable = numericLess) { list2 = copyList(list); diff --git a/examples/data_structures/queue.noja b/examples/data_structures/queue.noja deleted file mode 100644 index 4206400..0000000 --- a/examples/data_structures/queue.noja +++ /dev/null @@ -1,142 +0,0 @@ -# This script implements a circular queue and -# its relative tests! - -fun newCircularQueue(T: Type = int, max: int = 3) { - - if T == None: - error("Invalid type"); - - if max <= 0: - error("Maximum queue size must be positive"); - - list = []; - i = 0; - while i < max: { - list[i] = none; - i = i+1; - } - - return { - max: max, - head: 0, - tail: 0, - list: list, - type: T - }; -} - -fun getSize(queue: Map) { - - size = none; - if queue.tail == queue.head: { - if queue.list[queue.tail] == none: { - size = 0; - } else { - size = queue.max; - } - } else if queue.tail < queue.head: { - size = queue.head - - queue.tail; - } else { - size = queue.head - + queue.max - - queue.tail; - } - return size; -} - -fun append(queue: Map, value) { - - if type(value) != queue.type: - error("Invalid type"); - - size = getSize(queue); - - queue.list[queue.head] = value; - - if size == queue.max: { - queue.tail = queue.tail+1; - if queue.tail == queue.max: - queue.tail = 0; - } - - queue.head = queue.head+1; - if queue.head == queue.max: - queue.head = 0; -} - -fun pop(queue: Map) { - - if getSize(queue) == 0: - return none; - - value = queue.list[queue.tail]; - queue.list[queue.tail] = none; - - queue.tail = queue.tail+1; - if queue.tail == queue.max: - queue.tail = 0; - - return value; -} - -{ - utils = import("../utils.noja"); - - queue = newCircularQueue(int, 3); - assert(getSize(queue) == 0); - assert(queue.head == 0); - assert(queue.tail == 0); - - append(queue, 1); - assert(queue.head == 1); - assert(queue.tail == 0); - assert(getSize(queue) == 1); - assert(utils.compareAny(queue.list, [1, none, none])); - - append(queue, 2); - assert(queue.head == 2); - assert(queue.tail == 0); - assert(getSize(queue) == 2); - assert(utils.compareAny(queue.list, [1, 2, none])); - - append(queue, 3); - assert(queue.head == 0); - assert(queue.tail == 0); - assert(getSize(queue) == 3); - assert(utils.compareAny(queue.list, [1, 2, 3])); - - append(queue, 4); - assert(queue.head == 1); - assert(queue.tail == 1); - assert(getSize(queue) == 3); - assert(utils.compareAny(queue.list, [4, 2, 3])); - - v = pop(queue); - assert(v == 2); - assert(queue.head == 1); - assert(queue.tail == 2); - assert(getSize(queue) == 2); - assert(utils.compareAny(queue.list, [4, none, 3])); - - v = pop(queue); - assert(v == 3); - assert(queue.head == 1); - assert(queue.tail == 0); - assert(getSize(queue) == 1); - assert(utils.compareAny(queue.list, [4, none, none])); - - v = pop(queue); - assert(v == 4); - assert(queue.head == 1); - assert(queue.tail == 1); - assert(getSize(queue) == 0); - assert(utils.compareAny(queue.list, [none, none, none])); - - v = pop(queue); - assert(v == none); - assert(queue.head == 1); - assert(queue.tail == 1); - assert(getSize(queue) == 0); - assert(utils.compareAny(queue.list, [none, none, none])); -} \ No newline at end of file diff --git a/examples/data_structures/stack.noja b/examples/data_structures/stack.noja deleted file mode 100644 index d20b8f1..0000000 --- a/examples/data_structures/stack.noja +++ /dev/null @@ -1,67 +0,0 @@ -# Implementation of a stack using a linked list. - -fun Stack_New(T) { - if T == None: - return none, "The type can't be None"; - return { count: 0, head: none, type: T }; -} - -fun Stack_Push(stack: Map, value) { - - assert(stack.type != None); - - if type(value) != stack.type: - error("Invalid type"); - - node = {prev: none, item: value}; - - node.prev = stack.head; - stack.head = node; - stack.count = stack.count + 1; -} - -fun Stack_Pop(stack: Map) { - - if stack.head == none: - return none; - - value = stack.head.item; - stack.head = stack.head.prev; - stack.count = stack.count - 1; - - return value; -} - -fun Stack_Print(stack: Map) { - print("["); - curr = stack.head; - while curr != none: { - print(curr.item); - curr = curr.prev; - if curr != none: - print(", "); - } - print("]"); -} - -stack = Stack_New(int); - -Stack_Push(stack, 1); -Stack_Push(stack, 2); -Stack_Push(stack, 3); - -Stack_Print(stack); -print("\n"); - -x = Stack_Pop(stack); -y = Stack_Pop(stack); -z = Stack_Pop(stack); -w = Stack_Pop(stack); - -assert(x == 3); -assert(y == 2); -assert(z == 1); -assert(w == none); - -Stack_Print(stack); -print("\n"); diff --git a/examples/int_to_str.noja b/examples/int_to_str.noja deleted file mode 100644 index 7fba110..0000000 --- a/examples/int_to_str.noja +++ /dev/null @@ -1,65 +0,0 @@ - -# Shortcuts for some commonly used functions -chr = string.chr; -ord = string.ord; -cat = string.cat; - -# Some useful stuff -Numeric = int | float; - -# This function returns the magnitude of the -# argument and the power of 10 with the same -# magnitude. -fun getIntegerMagnitude(n: int) { - assert(n >= 0); - magn = 0; - powr = 1; - # Basically grow the power until it's - # bigger than the input. - while n >= powr * 10: { - powr = 10 * powr; - magn = 1 + magn; - } - return magn, powr; -} - -# Stringify a number between 0 and 9. -fun stringFromDigit(digit: int) { - assert(digit >= 0 and digit <= 9); - return chr(ord("0") + digit); -} - -fun abs(n: Numeric) { - if n < 0: - return -n; - return n; -} - -# Stringify an unsigned integer -fun stringFromInteger(n: int) { - - negative = (n < 0); - - # Get the power of 10 with the - # magnitude of the input. - _, power = getIntegerMagnitude(n); - - temp = abs(n); # Temporary copy of the input - text = ""; # The output we're about to compute - - while power >= 1: { - # Pop the leftmost digit from [temp]. - digit = temp / power; # Get the leftmost digit - temp = temp % power; # Remove it - - # Add the digit to the output. - text = cat(text, stringFromDigit(digit)); - - # Prep for the next iteration. - power = power / 10; - } - - if negative: - text = cat("-", text); - return text; -} \ No newline at end of file diff --git a/examples/json.noja b/examples/json.noja index 00a44d4..23f8277 100644 --- a/examples/json.noja +++ b/examples/json.noja @@ -85,7 +85,7 @@ fun parseArray(scan: Scanner) { val, err = parseValue(scan); if err != none: return none, err; - array[count(array)] = val; + append(array, val); char = scan->consumeSpaces(); if char == ']': @@ -166,11 +166,6 @@ fun parseNull(scan: Scanner) { return none; } -fun integerFromDigit(char: String) { - assert(isDigit(char)); - return ord(char) - ord('0'); -} - fun parseNumber(scan: Scanner) { char = scan->current(); diff --git a/examples/rosetta_code/99_bottles_of_beer.noja b/examples/rosetta_code/99_bottles_of_beer.noja index aa1a33b..c0f13b7 100644 --- a/examples/rosetta_code/99_bottles_of_beer.noja +++ b/examples/rosetta_code/99_bottles_of_beer.noja @@ -18,7 +18,6 @@ # # ================================== -stringFromInteger = import("../int_to_str.noja").stringFromInteger; cat = string.cat; fun verse(n: int) diff --git a/examples/rosetta_code/arithmetic_and_geometric_mean.noja b/examples/rosetta_code/arithmetic_and_geometric_mean.noja index df84cfd..2c41a59 100644 --- a/examples/rosetta_code/arithmetic_and_geometric_mean.noja +++ b/examples/rosetta_code/arithmetic_and_geometric_mean.noja @@ -1,10 +1,3 @@ -Numeric = int | float; - -fun abs(n) { - if n < 0: - return -n; - return n; -} # Calculate the arithmetic-geometric mean of x,y. fun agm(x: Numeric, y: Numeric, diff --git a/examples/scan.noja b/examples/scan.noja index 24a0779..424b581 100644 --- a/examples/scan.noja +++ b/examples/scan.noja @@ -1,15 +1,11 @@ -fun dummy() {} -Func = type(dummy) - | type(print); - Scanner = { src: String, i: int, - hint: Func, - current: Func, - consume: Func, - consumeSpaces: Func + hint: Callable, + current: Callable, + consume: Callable, + consumeSpaces: Callable }; fun hint(scan: Scanner, n: int = 1) { @@ -60,9 +56,3 @@ fun isSpace(c: String) return c == ' ' or c == '\t' or c == '\n'; - -fun min(x, y) { - if x < y: - return x; - return y; -} \ No newline at end of file diff --git a/misc/embedder.c b/misc/embedder.c index 93e3125..df99914 100644 --- a/misc/embedder.c +++ b/misc/embedder.c @@ -58,7 +58,7 @@ int main(int argc, char **argv) } } - fprintf(out_stream, "\n};\n"); + fprintf(out_stream, "\n\t0\n};\n"); fclose(in_stream); fclose(out_stream); diff --git a/src/lib/builtins/start.noja b/src/lib/builtins/start.noja index d7b72d3..f700859 100644 --- a/src/lib/builtins/start.noja +++ b/src/lib/builtins/start.noja @@ -1 +1,88 @@ -name = "Francesco"; \ No newline at end of file + +fun abs(n: Numeric) { + if n < 0: + return -n; + return n; +} + +fun min(x, y) { + if x < y: + return x; + return y; +} + +fun max(x, y) { + if x > y: + return x; + return y; +} + +Func = type(abs); +NFunc = type(print); +Numeric = int | float; +Callable = Func | NFunc; +Collection = List | Map; + +# Stringify a number between 0 and 9. +fun stringFromDigit(digit: int) { + assert(digit >= 0 and digit <= 9); + return string.chr(string.ord("0") + digit); +} + +# Stringify an unsigned integer +fun stringFromInteger(n: int) { + + # This function returns the magnitude of the + # argument and the power of 10 with the same + # magnitude. + fun getIntegerMagnitude(n: int) { + assert(n >= 0); + magn = 0; + powr = 1; + # Basically grow the power until it's + # bigger than the input. + while n >= powr * 10: { + powr = 10 * powr; + magn = 1 + magn; + } + return magn, powr; + } + + negative = (n < 0); + + # Get the power of 10 with the + # magnitude of the input. + _, power = getIntegerMagnitude(n); + + temp = abs(n); # Temporary copy of the input + text = ""; # The output we're about to compute + + while power >= 1: { + # Pop the leftmost digit from [temp]. + digit = temp / power; # Get the leftmost digit + temp = temp % power; # Remove it + + # Add the digit to the output. + text = string.cat(text, stringFromDigit(digit)); + + # Prep for the next iteration. + power = power / 10; + } + + if negative: + text = string.cat("-", text); + return text; +} + +fun floatFromInteger(n: int) + return 1.0 * n; + +fun integerFromDigit(char: String) { + res = ord(char) - ord('0'); + if res < 0 or res > 9: + error("String isn't a digit"); + return res; +} + +fun append(array: List, item) + array[count(array)] = item; \ No newline at end of file diff --git a/src/lib/noja.c b/src/lib/noja.c index baf2fbb..b3e8a7c 100644 --- a/src/lib/noja.c +++ b/src/lib/noja.c @@ -82,7 +82,7 @@ static _Bool interpret(Executable *exe) CompilationErrorType errtyp; Executable *prelude_exe = compile(prelude, (Error*) &error, &errtyp); - if(exe == NULL) { + if(prelude_exe == NULL) { const char *errname; switch(errtyp) { default: @@ -109,6 +109,21 @@ static _Bool interpret(Executable *exe) } Object *noja_bins = rets[0]; + // Need to remake the native built-ins because + // running the script invalidated the previous + // pointer. + native_bins = Object_NewStaticMap(bins_basic, bins_basic_init, runt, (Error*) &error); + if(native_bins == NULL) + { + assert(error.base.occurred == 1); + print_error(NULL, (Error*) &error); + RuntimeError_Free(&error); + Runtime_Free(runt); + Source_Free(prelude); + Executable_Free(prelude_exe); + return 0; + } + Object *all_bins = Object_NewClosure(native_bins, noja_bins, Runtime_GetHeap(runt), (Error*) &error); if (all_bins == NULL) { print_error(NULL, (Error*) &error); diff --git a/src/lib/objects/heap.c b/src/lib/objects/heap.c index a228ded..740c80d 100644 --- a/src/lib/objects/heap.c +++ b/src/lib/objects/heap.c @@ -170,6 +170,7 @@ void Heap_Free(Heap *heap) // it now though. Error_Free(&error); Error_Init(&error); + // Continue the loop.. } } diff --git a/src/lib/objects/o_buffer.c b/src/lib/objects/o_buffer.c index 6f11fab..95a586f 100644 --- a/src/lib/objects/o_buffer.c +++ b/src/lib/objects/o_buffer.c @@ -108,7 +108,7 @@ static _Bool buffer_free(Object *self, Error *error) UNUSED(error); BufferObject *buffer = (BufferObject*) self; - + Payload *payload = buffer->payload; ASSERT(payload != NULL && payload->refs > 0); @@ -142,6 +142,7 @@ Object *Object_SliceBuffer(Object *obj, size_t offset, size_t length, Heap *heap if(slice == NULL) return NULL; + payload->refs++; slice->payload = payload; slice->offset = offset; slice->length = length; diff --git a/src/lib/objects/o_file.c b/src/lib/objects/o_file.c index 0b2b9c8..c1b2ed6 100644 --- a/src/lib/objects/o_file.c +++ b/src/lib/objects/o_file.c @@ -57,9 +57,9 @@ _Bool Object_IsFile(Object *obj) FILE *Object_GetStream(Object *obj) { - if(!Object_IsDir(obj)) { + if(!Object_IsFile(obj)) { Error_Panic("%s expected a " TYPENAME_FILE - "object, but an %s was provided", + " object, but an %s was provided", __func__, Object_GetName(obj)); return NULL; }