From cbc3e6ec8935ba39ab02e6dba984805ba362ef48 Mon Sep 17 00:00:00 2001 From: mtardy Date: Tue, 8 Sep 2020 10:23:36 +0200 Subject: [PATCH] Add factories (#21) * Add Map factory and Integer draft * Fix Integer factory * Add map_isArray() * Fix String factory * Add Symbol factory * Fix Map factory * Add Array factory * Add Function and Syntax factories * Fix _checkType * Add runtimeError for bad arguments in factory functions * Change makeMapCapacity with malloc instead of realloc --- object.c | 68 +++++++++++++++- parse.leg | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 289 insertions(+), 5 deletions(-) diff --git a/object.c b/object.c index b79ba08..f9ef331 100644 --- a/object.c +++ b/object.c @@ -188,7 +188,7 @@ oop _checkType(oop ptr, type_t type, char *file, int line) { assert(ptr); if (getType(ptr) != type) { - fprintf(stderr, "\n%s:%i: expected %i got %i\n", file, line, type, ptr->type); + fprintf(stderr, "\n%s:%i: expected %i got %i\n", file, line, type, getType(ptr)); } assert(getType(ptr) == type); return ptr; @@ -249,13 +249,23 @@ oop makeString(char *value) // value will be used directly oop makeStringFrom(char *value, size_t l) { - oop newString = memcheck(malloc(sizeof(union object))); + oop newString = malloc(sizeof(struct String)); newString->type = String; newString->String.value = value; newString->String.size = l; return newString; } +oop makeStringFromChar(char c, int repeat) +{ + char *str= malloc(sizeof(char) * (repeat + 1)); + for (int i=0; itype= Symbol; + newSymbol->Symbol.name= name; + newSymbol->Symbol.prototype= 0; + return newSymbol; +} + +oop makeSymbolFromChar(char c, int repeat) +{ + char *str= malloc(sizeof(char) * (repeat + 1)); + for (int i=0; i 36 || base < 2) { + runtimeError("base must be between 2 and 36 inclusive"); + } + return makeInteger(strtoll(get(arg, String, value), NULL, base)); + } + } + } + runtimeError("cannot make integer from: %s", printString(arg)); + return NULL; +} + +oop prim_Map(oop scope, oop params) +{ + if (!map_hasIntegerKey(params, 0)) return makeMap(); + oop arg= get(params, Map, elements)[0].value; + switch (getType(arg)) { + case Undefined: { + return makeMap(); + } + case Integer: { + return makeMapCapacity(getInteger(arg)); + } + case Map: { + return clone(arg); + } + } + runtimeError("cannot make map from: %s", printString(arg)); + return NULL; +} + +oop prim_Array(oop scope, oop params) +{ + if (!map_hasIntegerKey(params, 0)) return makeMap(); + oop arg= get(params, Map, elements)[0].value; + switch (getType(arg)) { + case Undefined: { + return makeMap(); + } + case Integer: { + int repeat= getInteger(arg); + oop array= NULL; + if (map_hasIntegerKey(params, 1)) { + array= makeArrayFromElement(get(params, Map, elements)[1].value, repeat); + } else { + array= makeArrayFromElement(null, repeat); + } + return array; + } + case Symbol: { + return makeArrayFromString(get(arg, Symbol, name)); + } + case String: { + return makeArrayFromString(get(arg, String, value)); + } + case Map: { + return clone(arg); + } + } + runtimeError("cannot make array from: %s", printString(arg)); + return NULL; +} + +oop prim_Function(oop scope, oop params) +{ + oop arg= null; + if (map_hasIntegerKey(params, 0)) { + arg= get(params, Map, elements)[0].value; + switch (getType(arg)) { + case Function: { + if (isTrue(get(arg, Function, fixed))) { + oop unfix= clone(arg); + set(unfix, Function, fixed, makeInteger(0)); + return unfix; + } else { + return clone(arg); + } + } + case Map: { + if (map_hasIntegerKey(params, 1) && map_hasIntegerKey(params, 2) && map_hasIntegerKey(params, 3)) { + oop param= arg; + oop body= get(params, Map, elements)[1].value; + oop parentScope= get(params, Map, elements)[2].value; + oop name= get(params, Map, elements)[3].value; + if (is(Map, body) && is(Map, parentScope) && is(Map, name)) { + return makeFunction(NULL, name, param, body, parentScope, makeInteger(0)); + } + } + } + } + } + runtimeError("cannot make function from: %s", printString(arg)); + return NULL; +} + +oop prim_Syntax(oop scope, oop params) +{ + oop arg= null; + if (map_hasIntegerKey(params, 0)) { + arg= get(params, Map, elements)[0].value; + switch (getType(arg)) { + case Function: { + if (isFalse(get(arg, Function, fixed))) { + oop fix= clone(arg); + set(fix, Function, fixed, makeInteger(1)); + return fix; + } else { + return clone(arg); + } + } + case Map: { + if (map_hasIntegerKey(params, 1) && map_hasIntegerKey(params, 2) && map_hasIntegerKey(params, 3)) { + oop param= arg; + oop body= get(params, Map, elements)[1].value; + oop parentScope= get(params, Map, elements)[2].value; + oop name= get(params, Map, elements)[3].value; + if (is(Map, body) && is(Map, parentScope) && is(Map, name)) { + return makeFunction(NULL, name, param, body, parentScope, makeInteger(1)); + } + } + } + } + } + runtimeError("cannot make syntax from: %s", printString(arg)); + return NULL; } oop prim_scope(oop scope, oop params) @@ -1986,6 +2200,12 @@ int main(int argc, char **argv) map_set(globals, intern("import" ), makeFunction(prim_import, intern("import" ), null, null, globals, null)); map_set(globals, intern("microseconds"), makeFunction(prim_microseconds, intern("microseconds"), null, null, globals, null)); map_set(globals, intern("String" ), makeFunction(prim_String , intern("String" ), null, null, globals, null)); + map_set(globals, intern("Integer" ), makeFunction(prim_Integer , intern("Integer" ), null, null, globals, null)); + map_set(globals, intern("Symbol" ), makeFunction(prim_Symbol , intern("Symbol" ), null, null, globals, null)); + map_set(globals, intern("Map" ), makeFunction(prim_Map , intern("Map" ), null, null, globals, null)); + map_set(globals, intern("Array" ), makeFunction(prim_Array , intern("Array" ), null, null, globals, null)); + map_set(globals, intern("Function" ), makeFunction(prim_Function , intern("Function" ), null, null, globals, null)); + map_set(globals, intern("Syntax" ), makeFunction(prim_Syntax , intern("Syntax" ), null, null, globals, null)); map_set(globals, intern("scope"), makeFunction(prim_scope, intern("scope"), null, null, globals, null));