From a4f1e048e91b37d71e2914fcb546901094ad8a64 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 26 Aug 2022 01:48:26 +0100 Subject: [PATCH] Function calls, with args and single returns are working --- scripts/function.toy | 13 ++-- source/common.h | 5 +- source/compiler.c | 121 ++++++++++++++--------------- source/interpreter.c | 176 ++++++++++++++++++++++++++++++++++++++++--- source/literal.h | 3 +- source/node.c | 13 ++++ source/node.h | 8 ++ source/opcodes.h | 3 +- source/parser.c | 47 +++++++++++- source/repl_main.c | 1 + source/scope.c | 9 ++- 11 files changed, 316 insertions(+), 83 deletions(-) diff --git a/scripts/function.toy b/scripts/function.toy index 0111790..2af96c6 100644 --- a/scripts/function.toy +++ b/scripts/function.toy @@ -1,9 +1,12 @@ - -fn name(argument: type, arg2: type, ...rest): int { - print "hello world"; - return 0; +fn name(param1, param2) { + print "foobar"; + print param1; + return param2; } +var result = name("hello world", "goodnight world"); -print name; \ No newline at end of file +print "fizz"; +print result; +print "buzz"; diff --git a/source/common.h b/source/common.h index 551641b..efeeee5 100644 --- a/source/common.h +++ b/source/common.h @@ -28,4 +28,7 @@ void initCommand(int argc, const char* argv[]); void usageCommand(int argc, const char* argv[]); void helpCommand(int argc, const char* argv[]); -void copyrightCommand(int argc, const char* argv[]); \ No newline at end of file +void copyrightCommand(int argc, const char* argv[]); + +//NOTE: assigning to a byte from a short loses data +#define AS_USHORT(value) (*(unsigned short*)(&(value))) \ No newline at end of file diff --git a/source/compiler.c b/source/compiler.c index fadb01c..c9824f3 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -10,9 +10,6 @@ #include -//assigning to a byte from a short loses data -#define AS_USHORT(value) (*(unsigned short*)(&(value))) - void initCompiler(Compiler* compiler) { initLiteralArray(&compiler->literalCache); compiler->bytecode = NULL; @@ -21,7 +18,7 @@ void initCompiler(Compiler* compiler) { } //separated out, so it can be recursive -static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal) { +static int writeLiteralTypeToCacheOpt(LiteralArray* literalCache, Literal literal, bool skipDuplicationOptimisation) { //if it's a compound type, recurse and store the results if (AS_TYPE(literal).typeOf == LITERAL_ARRAY || AS_TYPE(literal).typeOf == LITERAL_DICTIONARY) { //I don't like storing types in an array, but it's the easiest and most straight forward method @@ -33,7 +30,7 @@ static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal) for (int i = 0; i < AS_TYPE(literal).count; i++) { //write the values to the cache, and the indexes to the store - int subIndex = writeLiteralTypeToCache(literalCache, ((Literal*)(AS_TYPE(literal).subtypes))[i]); + int subIndex = writeLiteralTypeToCacheOpt(literalCache, ((Literal*)(AS_TYPE(literal).subtypes))[i], false); pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex)); } @@ -42,13 +39,22 @@ static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal) literal.type = LITERAL_TYPE_INTERMEDIATE; //NOTE: tweaking the type usually isn't a good idea } - //BUGFIX: check if exactly this literal array exists - int index = findLiteralIndex(literalCache, literal); - if (index < 0) { - index = pushLiteralArray(literalCache, literal); - } + if (!skipDuplicationOptimisation) { + //BUGFIX: check if exactly this literal array exists + int index = findLiteralIndex(literalCache, literal); + if (index < 0) { + index = pushLiteralArray(literalCache, literal); + } - return index; + return index; + } + else { + return pushLiteralArray(literalCache, literal); + } +} + +static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal) { + return writeLiteralTypeToCacheOpt(literalCache, literal, false); } static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { @@ -155,49 +161,18 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { } static int writeNodeCollectionToCache(Compiler* compiler, Node* node) { - //stored as an array LiteralArray* store = ALLOCATE(LiteralArray, 1); - initLiteralArray(store); //ensure each literal value is in the cache, individually for (int i = 0; i < node->fnCollection.count; i++) { switch(node->fnCollection.nodes[i].type) { case NODE_VAR_DECL: { - //write each piece of the declaration to the bytecode - int identifierIndex = findLiteralIndex(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.identifier); - if (identifierIndex < 0) { - identifierIndex = pushLiteralArray(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.identifier); - } + //write each piece of the declaration to the cache + int identifierIndex = pushLiteralArray(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.identifier); //store without duplication optimisation + int typeIndex = writeLiteralTypeToCacheOpt(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.typeLiteral, false); - int typeIndex = writeLiteralTypeToCache(&compiler->literalCache, node->fnCollection.nodes[i].varDecl.typeLiteral); - - //embed the info into the bytecode - if (identifierIndex >= 256 || typeIndex >= 256) { - //push a "long" declaration - compiler->bytecode[compiler->count++] = OP_VAR_DECL_LONG; //1 byte - - *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)identifierIndex; //2 bytes - compiler->count += sizeof(unsigned short); - - *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)typeIndex; //2 bytes - compiler->count += sizeof(unsigned short); - } - else { - //push a declaration - compiler->bytecode[compiler->count++] = OP_VAR_DECL; //1 byte - compiler->bytecode[compiler->count++] = (unsigned char)identifierIndex; //1 byte - compiler->bytecode[compiler->count++] = (unsigned char)typeIndex; //1 byte - } - } - break; - - case NODE_LITERAL: { - //values - int val = findLiteralIndex(&compiler->literalCache, node->fnCollection.nodes[i].atomic.literal); - if (val < 0) { - val = pushLiteralArray(&compiler->literalCache, node->fnCollection.nodes[i].atomic.literal); - } - pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + pushLiteralArray(store, TO_INTEGER_LITERAL(identifierIndex)); + pushLiteralArray(store, TO_INTEGER_LITERAL(typeIndex)); } break; @@ -207,7 +182,7 @@ static int writeNodeCollectionToCache(Compiler* compiler, Node* node) { } } - //push the store to the cache, with instructions about how pack it + //store the store return pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); } @@ -371,9 +346,9 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd //run a compiler over the function Compiler* fnCompiler = ALLOCATE(Compiler, 1); initCompiler(fnCompiler); - writeCompiler(fnCompiler, node->fnDecl.arguments); - writeCompiler(fnCompiler, node->fnDecl.returns); - writeCompiler(fnCompiler, node->fnDecl.block); + writeCompiler(fnCompiler, node->fnDecl.arguments); //can be empty, but not NULL + writeCompiler(fnCompiler, node->fnDecl.returns); //can be empty, but not NULL + writeCompiler(fnCompiler, node->fnDecl.block); //can be empty, but not NULL //create the function in the literal cache (by storing the compiler object) Literal fnLiteral = TO_FUNCTION_LITERAL(fnCompiler, 0); @@ -409,21 +384,41 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd break; case NODE_FN_COLLECTION: { + //embed these in the bytecode... int index = writeNodeCollectionToCache(compiler, node); - //push the node opcode to the bytecode - if (index >= 256) { - //push a "long" index - compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte - *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)index; //2 bytes + compiler->bytecode[compiler->count] = (unsigned short)index; //2 bytes + compiler->count += sizeof(unsigned short); + } + break; - compiler->count += sizeof(unsigned short); - } - else { - //push the index - compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte - compiler->bytecode[compiler->count++] = (unsigned char)index; //1 byte + case NODE_FN_CALL: { + //NOTE: assume the function definition/name is above us + + for (int i = 0; i < node->fnCall.arguments->fnCollection.count; i++) { //reverse order, to count from the beginning in the interpreter + //write each argument to the bytecode + int argumentsIndex = findLiteralIndex(&compiler->literalCache, node->fnCall.arguments->fnCollection.nodes[i].atomic.literal); + if (argumentsIndex < 0) { + argumentsIndex = pushLiteralArray(&compiler->literalCache, node->fnCall.arguments->fnCollection.nodes[i].atomic.literal); + } + + //push the node opcode to the bytecode + if (argumentsIndex >= 256) { + //push a "long" index + compiler->bytecode[compiler->count++] = OP_LITERAL_LONG; //1 byte + + *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)argumentsIndex; //2 bytes + compiler->count += sizeof(unsigned short); + } + else { + //push the index + compiler->bytecode[compiler->count++] = OP_LITERAL; //1 byte + compiler->bytecode[compiler->count++] = (unsigned char)argumentsIndex; //1 byte + } } + + //call the function + //DO NOT call the collection, this is done in binary } break; @@ -605,7 +600,7 @@ static void writeCompilerWithJumps(Compiler* compiler, Node* node, void* breakAd } //push the return, with the number of literals - compiler->bytecode[compiler->count++] = OP_RETURN; //1 byte + compiler->bytecode[compiler->count++] = OP_FN_RETURN; //1 byte *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)(node->path.thenPath->fnCollection.count); //2 bytes compiler->count += sizeof(unsigned short); diff --git a/source/interpreter.c b/source/interpreter.c index 37f5674..4948b8c 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -51,9 +51,7 @@ void freeInterpreter(Interpreter* interpreter) { } freeLiteralArray(&interpreter->literalCache); - while (interpreter->scope) { - interpreter->scope = popScope(interpreter->scope); - } + interpreter->scope = popScope(interpreter->scope); freeLiteralArray(&interpreter->stack); } @@ -156,7 +154,7 @@ static bool execPrint(Interpreter* interpreter) { printLiteralCustom(lit, interpreter->printOutput); - freeLiteral(lit); + // freeLiteral(lit); //it's a reference (to the dictionaries), so don't free it return true; } @@ -397,6 +395,47 @@ static bool execVarDecl(Interpreter* interpreter, bool lng) { return true; } +static bool execFnDecl(Interpreter* interpreter, bool lng) { + //read the index in the cache + int identifierIndex = 0; + int functionIndex = 0; + Scope* scope = pushScope(interpreter->scope); + + if (lng) { + identifierIndex = (int)readShort(interpreter->bytecode, &interpreter->count); + functionIndex = (int)readShort(interpreter->bytecode, &interpreter->count); + } + else { + identifierIndex = (int)readByte(interpreter->bytecode, &interpreter->count); + functionIndex = (int)readByte(interpreter->bytecode, &interpreter->count); + } + + Literal identifier = interpreter->literalCache.literals[identifierIndex]; + Literal function = interpreter->literalCache.literals[functionIndex]; + + function.as.function.scope = scope; //hacked in + + Literal type = TO_TYPE_LITERAL(LITERAL_FUNCTION, true); + + if (!declareScopeVariable(interpreter->scope, identifier, type)) { + printf(ERROR "ERROR: Can't redefine the function \""); + printLiteral(identifier); + printf("\"\n" RESET); + popScope(scope); + return false; + } + + if (!setScopeVariable(interpreter->scope, identifier, function, false)) { + printf(ERROR "ERROR: Incorrect type assigned to variable \""); + printLiteral(identifier); + printf("\"\n" RESET); + popScope(scope); + return false; + } + + return true; +} + static bool execVarAssign(Interpreter* interpreter) { Literal rhs = popLiteralArray(&interpreter->stack); Literal lhs = popLiteralArray(&interpreter->stack); @@ -703,8 +742,111 @@ static bool execFalseJump(Interpreter* interpreter) { return true; } +//forward declare +static void execInterpreter(Interpreter*); +static void readInterpreterSections(Interpreter* interpreter); + +static bool execFnCall(Interpreter* interpreter) { + LiteralArray arguments; + initLiteralArray(&arguments); + + //unpack the arguments + while (interpreter->stack.count > 1) { + pushLiteralArray(&arguments, popLiteralArray(&interpreter->stack)); //NOTE: also reverses the order + } + + Literal identifier = popLiteralArray(&interpreter->stack); + + Literal func = identifier; + parseIdentifierToValue(interpreter, &func); + + //set up a new interpreter + Interpreter inner; + + //init the inner interpreter manually + initLiteralArray(&inner.literalCache); + inner.scope = pushScope(func.as.function.scope); + inner.bytecode = AS_FUNCTION(func); + inner.length = func.as.function.length; + inner.count = 0; + initLiteralArray(&inner.stack); + setInterpreterPrint(&inner, interpreter->printOutput); + setInterpreterAssert(&inner, interpreter->assertOutput); + + //prep the sections + readInterpreterSections(&inner); + + //prep the arguments + LiteralArray* paramArray = AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]); + LiteralArray* returnArray = AS_ARRAY(inner.literalCache.literals[ readShort(inner.bytecode, &inner.count) ]); + + for (int i = 0; i < paramArray->count; i += 2) { //contents is the indexes of identifier & type + //declare and define each entry in the scope + if (!declareScopeVariable(inner.scope, paramArray->literals[i], paramArray->literals[i + 1])) { + printf(ERROR "[internal] Could not redeclare parameter\n" RESET); + freeInterpreter(&inner); + return false; + } + + if (!setScopeVariable(inner.scope, paramArray->literals[i], popLiteralArray(&arguments), false)) { + printf(ERROR "[internal] Could not redefine parameter\n" RESET); + freeInterpreter(&inner); + return false; + } + } + + //execute the interpreter + execInterpreter(&inner); + + //accept the stack as the results + LiteralArray returns; + initLiteralArray(&returns); + + //unpack the results + while (inner.stack.count > 0) { + pushLiteralArray(&returns, popLiteralArray(&inner.stack)); //NOTE: also reverses the order + } + + for (int i = 0; i < returns.count; i++) { + pushLiteralArray(&interpreter->stack, popLiteralArray(&returns)); //NOTE: reverses again + } + + //free + freeLiteralArray(&returns); + freeLiteralArray(&arguments); + freeInterpreter(&inner); + + //actual bytecode persists until next call + return true; +} + +static bool execFnReturn(Interpreter* interpreter) { + LiteralArray returns; + initLiteralArray(&returns); + + //get the values of everything on the stack + while (interpreter->stack.count > 0) { + Literal lit = popLiteralArray(&interpreter->stack); + parseIdentifierToValue(interpreter, &lit); + pushLiteralArray(&returns, lit); //reverses the order + } + + //and back again + while (returns.count > 0) { + pushLiteralArray(&interpreter->stack, popLiteralArray(&returns)); + } + + freeLiteralArray(&returns); + + //finally + return false; +} + //the heart of toy static void execInterpreter(Interpreter* interpreter) { + //set the starting point for the interpreter + interpreter->codeStart = interpreter->count; + unsigned char opcode = readByte(interpreter->bytecode, &interpreter->count); while(opcode != OP_EOF && opcode != OP_SECTION_END) { @@ -790,6 +932,13 @@ static void execInterpreter(Interpreter* interpreter) { } break; + case OP_FN_DECL: + case OP_FN_DECL_LONG: + if (!execFnDecl(interpreter, opcode == OP_FN_DECL_LONG)) { + return; + } + break; + case OP_VAR_ASSIGN: if (!execVarAssign(interpreter)) { return; @@ -868,6 +1017,18 @@ static void execInterpreter(Interpreter* interpreter) { } break; + case OP_FN_CALL: + if (!execFnCall(interpreter)) { + return; + } + break; + + case OP_FN_RETURN: + if (!execFnReturn(interpreter)) { + return; + } + break; + default: printf(ERROR "Error: Unknown opcode found %d, terminating\n" RESET, opcode); printLiteralArray(&interpreter->stack, "\n"); @@ -1085,7 +1246,7 @@ static void readInterpreterSections(Interpreter* interpreter) { //read the function code (literal cache and all) unsigned char* bytes = ALLOCATE(unsigned char, size); - memcpy(bytes, interpreter->bytecode + interpreter->count, size); + memcpy(bytes, interpreter->bytecode + interpreter->count, size); //TODO: -1 for the ending mark interpreter->count += size; //assert that the last memory slot is function end @@ -1100,10 +1261,7 @@ static void readInterpreterSections(Interpreter* interpreter) { } } - //TODO - - //set the starting point for the interpreter - interpreter->codeStart = interpreter->count; + consumeByte(OP_SECTION_END, interpreter->bytecode, &interpreter->count); //terminate the function section } void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int length) { diff --git a/source/literal.h b/source/literal.h index 0268677..973f247 100644 --- a/source/literal.h +++ b/source/literal.h @@ -39,6 +39,7 @@ typedef struct { struct { void* ptr; + void* scope; int length; } function; @@ -86,7 +87,7 @@ typedef struct { #define TO_STRING_LITERAL(value) _toStringLiteral(value) #define TO_ARRAY_LITERAL(value) ((Literal){LITERAL_ARRAY, { .array = value }}) #define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }}) -#define TO_FUNCTION_LITERAL(value, l) ((Literal){LITERAL_FUNCTION, { .function.ptr = value, .function.length = l }}) +#define TO_FUNCTION_LITERAL(value, l) ((Literal){LITERAL_FUNCTION, { .function.ptr = value, .function.scope = NULL, .function.length = l }}) #define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value, strlen(value)) #define TO_TYPE_LITERAL(value, c) ((Literal){ LITERAL_TYPE, { .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }}) diff --git a/source/node.c b/source/node.c index bb20192..50dafce 100644 --- a/source/node.c +++ b/source/node.c @@ -76,6 +76,10 @@ void freeNode(Node* node) { FREE_ARRAY(Node, node->fnCollection.nodes, node->fnCollection.capacity); break; + case NODE_FN_CALL: + freeNode(node->fnCall.arguments); + break; + case NODE_PATH_IF: case NODE_PATH_WHILE: case NODE_PATH_FOR: @@ -198,6 +202,15 @@ void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node *nodeHandle = tmp; } +void emitFnCall(Node** nodeHandle, Node* arguments) { + Node* tmp = ALLOCATE(Node, 1); + + tmp->type = NODE_FN_CALL; + tmp->fnCall.arguments = arguments; + + *nodeHandle = tmp; +} + void emitNodeFnCollection(Node** nodeHandle) { Node* tmp = ALLOCATE(Node, 1); diff --git a/source/node.h b/source/node.h index fa4d3b6..df64109 100644 --- a/source/node.h +++ b/source/node.h @@ -20,6 +20,7 @@ typedef enum NodeType { NODE_VAR_DECL, //contains identifier literal, typenode, expression definition NODE_FN_DECL, //containd identifier literal, arguments node, returns node, block node NODE_FN_COLLECTION, //parts of a function + NODE_FN_CALL, NODE_PATH_IF, //for control flow NODE_PATH_WHILE, //for control flow NODE_PATH_FOR, //for control flow @@ -101,6 +102,11 @@ typedef struct NodeFnCollection { int count; } NodeFnCollection; +typedef struct NodeFnCall { + NodeType type; + Node* arguments; +} NodeFnCall; + typedef struct NodePath { NodeType type; Node* preClause; @@ -129,6 +135,7 @@ union _node { NodeVarDecl varDecl; NodeFnDecl fnDecl; NodeFnCollection fnCollection; + NodeFnCall fnCall; NodePath path; NodeIncrement increment; }; @@ -144,6 +151,7 @@ void emitNodePair(Node** nodeHandle, Node* left, Node* right); void emitNodeVarTypes(Node** nodeHandle, Literal literal); void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression); void emitNodeFnDecl(Node** nodeHandle, Literal identifier, Node* arguments, Node* returns, Node* block); +void emitFnCall(Node** nodeHandle, Node* arguments); void emitNodeFnCollection(Node** nodeHandle); void emitNodePath(Node** nodeHandle, NodeType type, Node* preClause, Node* postClause, Node* condition, Node* thenPath, Node* elsePath); void emiteNodePrefixIncrement(Node** nodeHandle, Literal identifier, int increment); diff --git a/source/opcodes.h b/source/opcodes.h index 7f1a1cc..1189eb9 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -60,7 +60,8 @@ typedef enum Opcode { //jumps, and conditional jumps (absolute) OP_JUMP, OP_IF_FALSE_JUMP, - OP_RETURN, + OP_FN_CALL, + OP_FN_RETURN, //meta OP_FN_END, //different from SECTION_END diff --git a/source/parser.c b/source/parser.c index 49e6027..ed9b6b4 100644 --- a/source/parser.c +++ b/source/parser.c @@ -627,6 +627,51 @@ static Opcode decrementInfix(Parser* parser, Node** nodeHandle) { return OP_EOF; } +static Opcode fnCall(Parser* parser, Node** nodeHandle) { + advance(parser); + + //binary() is an infix rule - so only get the RHS of the operator + switch(parser->previous.type) { + //arithmetic + case TOKEN_PAREN_LEFT: { + Node* arguments = NULL; + emitNodeFnCollection(&arguments); + + //if there's arguments + if (!match(parser, TOKEN_PAREN_RIGHT)) { + //read each argument + do { + //emit the node to the argument list (grow the node if needed) + if (arguments->fnCollection.capacity < arguments->fnCollection.count + 1) { + int oldCapacity = arguments->fnCollection.capacity; + + arguments->fnCollection.capacity = GROW_CAPACITY(oldCapacity); + arguments->fnCollection.nodes = GROW_ARRAY(Node, arguments->fnCollection.nodes, oldCapacity, arguments->fnCollection.capacity); + } + + Node* node = NULL; + parsePrecedence(parser, &node, PREC_TERNARY); + arguments->fnCollection.nodes[arguments->fnCollection.count++] = *node; + } while(match(parser, TOKEN_COMMA)); + + consume(parser, TOKEN_PAREN_RIGHT, "Expected ')' at end of argument list"); + } + + //emit the call + emitFnCall(nodeHandle, arguments); + + return OP_FN_CALL; + } + break; + + default: + error(parser, parser->previous, "Unexpected token passed to function call precedence rule"); + return OP_EOF; + } + + return OP_EOF; +} + ParseRule parseRules[] = { //must match the token types //types {atomic, NULL, PREC_PRIMARY},// TOKEN_NULL, @@ -685,7 +730,7 @@ ParseRule parseRules[] = { //must match the token types {NULL, binary, PREC_ASSIGNMENT},// TOKEN_ASSIGN, //logical operators - {grouping, NULL, PREC_CALL},// TOKEN_PAREN_LEFT, + {grouping, fnCall, PREC_CALL},// TOKEN_PAREN_LEFT, {NULL, NULL, PREC_NONE},// TOKEN_PAREN_RIGHT, {compound, NULL, PREC_CALL},// TOKEN_BRACKET_LEFT, {NULL, NULL, PREC_NONE},// TOKEN_BRACKET_RIGHT, diff --git a/source/repl_main.c b/source/repl_main.c index 8969ee1..b1b7958 100644 --- a/source/repl_main.c +++ b/source/repl_main.c @@ -129,6 +129,7 @@ void runSource(char* source) { // for (size_t i = 0; i < size; i++) { // printf("%d, ", tb[i]); // } + // printf("\n"); runBinary(tb, size); } diff --git a/source/scope.c b/source/scope.c index d2f491a..cf11ecd 100644 --- a/source/scope.c +++ b/source/scope.c @@ -90,7 +90,12 @@ static bool checkType(Literal typeLiteral, Literal value) { } } - //TODO: function type checking + if (IS_FUNCTION(value)) { + //check value's type + if (AS_TYPE(typeLiteral).typeOf != LITERAL_FUNCTION) { + return false; + } + } if (AS_TYPE(typeLiteral).typeOf == LITERAL_TYPE && !IS_TYPE(value)) { return false; @@ -108,7 +113,7 @@ Scope* pushScope(Scope* ancestor) { //tick up all scope reference counts scope->references = 0; - for (Scope* ptr = scope; ptr; ptr = ptr->ancestor) { + for (Scope* ptr = scope; ptr != NULL; ptr = ptr->ancestor) { ptr->references++; }