diff --git a/scripts/funky.toy b/scripts/funky.toy index 1891fd7..bfa6dab 100644 --- a/scripts/funky.toy +++ b/scripts/funky.toy @@ -1,22 +1,17 @@ -fn name(param1, param2, param3, param4) { +fn name() { //return 42; } -//params (group -> aggregate): -// left: varAccess (name string "param1") -// right (aggregate): -// left: varAccess (name string "param2") -// right (aggregate): -// //continues -/* -fn name(param1: int, param2: float) { - return 42; +fn name(param1: int, param2: float, param3: string, param4) { + //return 42; } -*/ +fn name(foobar: bool const) { + //return 42; +} \ No newline at end of file diff --git a/source/toy_module_compiler.c b/source/toy_module_compiler.c index e4be5ae..a9410f0 100644 --- a/source/toy_module_compiler.c +++ b/source/toy_module_compiler.c @@ -900,6 +900,24 @@ static unsigned int writeInstructionAccess(Toy_ModuleCompiler** mb, Toy_AstVarAc } static unsigned int writeInstructionFnDeclare(Toy_ModuleCompiler** mb, Toy_AstFnDeclare ast) { + /* + FnDeclare: name, params, body + + fn name(param1: int, param2: float, param3: string, param4) { + // + } + + ast->params->aggregate + .left->aggregate + .left->aggregate + .left->aggregate + .left = (NULL) + .right->value.value.as.string.name (param1: int) + .right->value.value.as.string.name (param2: float) + .right->value.value.as.string.name (param3: string) + .right->value.value.as.string.name (param4: any) + */ + //URGENT: currently a no-op (void)mb; (void)ast; @@ -1054,9 +1072,9 @@ static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast) unsigned int capacity = 0, count = 0; int codeAddr = 0; int jumpsAddr = 0; - // int paramAddr = 0; + int paramAddr = 0; int dataAddr = 0; - // int subsAddr = 0; + int subsAddr = 0; emitInt(&buffer, &capacity, &count, 0); //total size (overwritten later) emitInt(&buffer, &capacity, &count, mb->jumpsCount); //jumps size @@ -1074,7 +1092,7 @@ static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast) emitInt(&buffer, &capacity, &count, 0); //jumps } if (mb->paramCount > 0) { - // paramAddr = count; + paramAddr = count; emitInt(&buffer, &capacity, &count, 0); //params } if (mb->dataCount > 0) { @@ -1082,7 +1100,7 @@ static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast) emitInt(&buffer, &capacity, &count, 0); //data } if (mb->subsCount > 0) { - // subsAddr = count; + subsAddr = count; emitInt(&buffer, &capacity, &count, 0); //subs } @@ -1103,7 +1121,13 @@ static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast) count += mb->jumpsCount; } - //TODO: param region + if (mb->paramCount > 0) { + expand(&buffer, &capacity, &count, mb->paramCount); + memcpy((buffer + count), mb->param, mb->paramCount); + + *((int*)(buffer + paramAddr)) = count; + count += mb->paramCount; + } if (mb->dataCount > 0) { expand(&buffer, &capacity, &count, mb->dataCount); @@ -1113,7 +1137,13 @@ static unsigned char* writeModuleCompiler(Toy_ModuleCompiler* mb, Toy_Ast* ast) count += mb->dataCount; } - //TODO: subs region + if (mb->subsCount > 0) { + expand(&buffer, &capacity, &count, mb->subsCount); + memcpy((buffer + count), mb->subs, mb->subsCount); + + *((int*)(buffer + subsAddr)) = count; + count += mb->subsCount; + } //finally, record the total size within the header, and return the result ((int*)buffer)[0] = count; diff --git a/source/toy_parser.c b/source/toy_parser.c index b7ee2c8..7c33dbe 100644 --- a/source/toy_parser.c +++ b/source/toy_parser.c @@ -921,14 +921,54 @@ static void makeFunctionDeclarationStmt(Toy_Bucket** bucketHandle, Toy_Parser* p Toy_Token nameToken = parser->previous; Toy_String* nameStr = Toy_createNameStringLength(bucketHandle, nameToken.lexeme, nameToken.length, TOY_VALUE_FUNCTION, true); - //read the function parameters, as a grouping + //read the function parameters (done manually to avoid other syntax issues) Toy_Ast* params = NULL; - parsePrecedence(bucketHandle, parser, ¶ms, PREC_GROUP); + + if (!match(parser, TOY_TOKEN_OPERATOR_PAREN_LEFT)) { + printError(parser, parser->previous, "Expected '(' at the beginning of parameter list"); + Toy_private_emitAstError(bucketHandle, rootHandle); + return; + } + + unsigned int paramIterations = 0; + + while (parser->current.type != TOY_TOKEN_OPERATOR_PAREN_RIGHT && (paramIterations++ == 0 || match(parser, TOY_TOKEN_OPERATOR_COMMA))) { + //grab the name token + advance(parser); + Toy_Token nameToken = parser->previous; + + //read the type specifier if present + Toy_ValueType varType = TOY_VALUE_ANY; + bool constant = false; + + if (match(parser, TOY_TOKEN_OPERATOR_COLON)) { + varType = readType(parser); + + if (match(parser, TOY_TOKEN_KEYWORD_CONST)) { + constant = true; + } + } + + //emit the parameter as a name string + Toy_String* name = Toy_createNameStringLength(bucketHandle, nameToken.lexeme, nameToken.length, varType, constant); + Toy_Value value = TOY_VALUE_FROM_STRING(name); + Toy_Ast* ast = NULL; + Toy_private_emitAstValue(bucketHandle, &ast, value); + + //add to the params aggregate (is added backwards, because weird) + Toy_private_emitAstAggregate(bucketHandle, ¶ms, TOY_AST_FLAG_COLLECTION, ast); + } + + consume(parser, TOY_TOKEN_OPERATOR_PAREN_RIGHT, "Expected ')' at the end of parameter list"); //read the body + consume(parser, TOY_TOKEN_OPERATOR_BRACE_LEFT, "Expected '{' at the beginning of function body"); + Toy_Ast* body = NULL; makeBlockStmt(bucketHandle, parser, &body); + consume(parser, TOY_TOKEN_OPERATOR_BRACE_RIGHT, "Expected '}' at the end of function body"); + //finally, emit the declaration as an Ast Toy_private_emitAstFunctionDeclaration(bucketHandle, rootHandle, nameStr, params, body); }