From 15d1d5bbe502c1fba317b250667fb8cff92d5caa Mon Sep 17 00:00:00 2001 From: cozis Date: Sat, 12 Mar 2022 20:48:43 +0100 Subject: [PATCH] docs docs docs --- TODO.txt | 4 +++- docs/language.md | 2 +- src/builtins/README.md | 1 + src/o_staticmap.c | 27 +++++++++++++++++++++ src/runtime/o_func.c | 52 ++++++++++++++++++++++++++++++----------- src/runtime/o_nfunc.c | 53 ++++++++++++++++++++++++++++++++---------- 6 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 src/builtins/README.md diff --git a/TODO.txt b/TODO.txt index 899a63b..548ad18 100644 --- a/TODO.txt +++ b/TODO.txt @@ -6,4 +6,6 @@ the second sub-expr. "A.name != none" raises an error if the first one "type(A) == type({})" isn't true, but doesn't need to be evaluated in - that case. \ No newline at end of file + that case. + +- Implement the `count` method for static maps. \ No newline at end of file diff --git a/docs/language.md b/docs/language.md index fee4b1a..7fbbfea 100644 --- a/docs/language.md +++ b/docs/language.md @@ -8,7 +8,7 @@ Here's an overview: `string`. `list` (array), `map` (associative array), `none` (null) 3. No implicit casts. 2. Arithmetic operations only allowed on numbers. -3. Division between `ints` rounds down. +3. Division between `int`s rounds down. 4. Logical operators expect boolean operands. 5. Assignments are expressions that return the newly assigned value. 6. No for loop (yet) diff --git a/src/builtins/README.md b/src/builtins/README.md new file mode 100644 index 0000000..60d3209 --- /dev/null +++ b/src/builtins/README.md @@ -0,0 +1 @@ +Here are implemented the language's builtin variables. Each file define it's values and exposes them through a `StaticMapSlot` array. These values can then be accessed from within the language by wrapping these arrays in static map objects (check src/o_staticmap.c to know more). \ No newline at end of file diff --git a/src/o_staticmap.c b/src/o_staticmap.c index 22923e6..848b8af 100644 --- a/src/o_staticmap.c +++ b/src/o_staticmap.c @@ -1,3 +1,30 @@ +/* + * + * -- WHAT IS THIS FILE? -------------------------------------------- + * This file implements the "static map" object. The static map + * object behaves like a read-only "map". (Note that "implementing + * an object" means a very specific thing in this interpreter. If + * you didn't know, check the src/objects folder.) + * ------------------------------------------------------------------ + * + * -- THE STATIC MAP OBJECT ----------------------------------------- + * The statis map is a read-only collection of objects. You can see + * it as an interface for static arrays. You can define an array of + * `StaticMapSlot`s and then wrap it in this object. When the map is + * accessed, a lookup is performed into the array. Something to note + * is that the array is converted to noja objects lazily when they + * are accessed, which makes the start-up times lower than a general + * purpose map. + * ------------------------------------------------------------------ + * + * NOTES: + * - This object, unlike the others implemented in src/objects, + * depends on the Runtime objects. This is because it needs + * to be able to create `NativeFuncObject`s. + * + * - Only strings can be keys. There is no intrinsic reason why + * it should be like that, it's just simpler. + */ #include #include #include "o_staticmap.h" diff --git a/src/runtime/o_func.c b/src/runtime/o_func.c index baff43e..05200d7 100644 --- a/src/runtime/o_func.c +++ b/src/runtime/o_func.c @@ -12,19 +12,6 @@ typedef struct { Object *closure; } FunctionObject; -static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error); -static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp); -static _Bool free_(Object *self, Error *error); - -static TypeObject t_func = { - .base = (Object) { .type = &t_type, .flags = Object_STATIC }, - .name = "function", - .size = sizeof (FunctionObject), - .call = call, - .walk = walk, - .free = free_, -}; - static _Bool free_(Object *self, Error *error) { (void) error; @@ -103,6 +90,45 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, return result; } +static TypeObject t_func = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "function", + .size = sizeof (FunctionObject), + .call = call, + .walk = walk, + .free = free_, +}; + +/* Symbol: Object_FromNojaFunction + * + * Creates an object from a noja executable structure. + * + * Args: + * - runtime: The reference to an instanciated Runtime. + * + * - exe: A noja executable. + * + * - index: The index of the first bytecode instruction + * of the noja function within the executable. + * + * - argc: The number of arguments the function expects. + * It must be positive (unlike [Object_FromNativeFunction], + * where -1 means variadic). + * + * - closure: An object containing variables that will be + * accessible from the noja function other than + * the ones that will be defined inside it. + * + * - heap: The heap that will be used to allocate the object. + * It can't be NULL. + * + * - error: Output parameter where error information is stored. + * It can't be NULL. + * + * Returns: + * The newly created object. If an error occurred, NULL is returned + * and information about the error is stored in the [error] argument. + */ Object *Object_FromNojaFunction(Runtime *runtime, Executable *exe, int index, int argc, Object *closure, Heap *heap, Error *error) { assert(runtime != NULL); diff --git a/src/runtime/o_nfunc.c b/src/runtime/o_nfunc.c index ecbe7d6..3b77e07 100644 --- a/src/runtime/o_nfunc.c +++ b/src/runtime/o_nfunc.c @@ -1,3 +1,9 @@ +/* + * WHAT IS THIS FILE? + * This file implements an object that makes it possible + * to call native functions from within noja code. + * + */ #include #include #include "../utils/defs.h" @@ -11,15 +17,6 @@ typedef struct { int argc; } NativeFunctionObject; -static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error); - -static TypeObject t_nfunc = { - .base = (Object) { .type = &t_type, .flags = Object_STATIC }, - .name = "native function", - .size = sizeof (NativeFunctionObject), - .call = call, -}; - static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *error) { assert(self != NULL); @@ -84,7 +81,10 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, assert(func->callback != NULL); Object *result = func->callback(func->runtime, argv2, argc2, error); - // NOTE: Every object reference is invalidated from here. + // NOTE: Since the callback may have executed some bytecode, a GC + // cycle may have been triggered, therefore we must assume + // every object reference that was locally saved is invalidated + // from here (the returned object is good tho). if(result == NULL && error->occurred == 0) Error_Report(error, 1, "Native callback returned NULL but didn't report errors"); @@ -95,11 +95,40 @@ static Object *call(Object *self, Object **argv, unsigned int argc, Heap *heap, return result; } +static TypeObject t_nfunc = { + .base = (Object) { .type = &t_type, .flags = Object_STATIC }, + .name = "native function", + .size = sizeof (NativeFunctionObject), + .call = call, +}; + +/* Symbol: Object_FromNativeFunction + * + * Creates an object from a function pointer. + * + * Args: + * - runtime: The reference to an instanciated Runtime. This must be + * provided so that the callback can also access it. + * + * - callback: The native function to be executed when this object + * is called. + * + * - argc: The number of arguments the function expects. If -1 is + * provided, then the function is considered to be variadic. + * + * - heap: The heap that will be used to allocate the object. + * It can't be NULL. + * + * - error: Output parameter where error information is stored. + * It can't be NULL. + * + * Returns: + * The newly created object. If an error occurred, NULL is returned + * and information about the error is stored in the [error] argument. + */ Object *Object_FromNativeFunction(Runtime *runtime, Object *(*callback)(Runtime*, Object**, unsigned int, Error*), int argc, Heap *heap, Error *error) { assert(callback != NULL); - assert(heap != NULL); - assert(error != NULL); NativeFunctionObject *func = (NativeFunctionObject*) Heap_Malloc(heap, &t_nfunc, error);