Start work on function calling

This commit is contained in:
2026-02-28 21:58:33 +11:00
parent 955927e021
commit dc09883e46
3 changed files with 175 additions and 1 deletions

View File

@@ -3,6 +3,7 @@
#include "SolsScope.h" #include "SolsScope.h"
#include <groundvm.h> #include <groundvm.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include "../parser/SolsNode.h" #include "../parser/SolsNode.h"
@@ -207,6 +208,20 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
case SNT_LAMBDA: { case SNT_LAMBDA: {
return Success(SolsType, charptr, node->as.type); return Success(SolsType, charptr, node->as.type);
} }
case SNT_FUNCTION_CALL: {
SolsVariable* var = findSolsVariable(scope, node->as.idName);
if (var == NULL) {
Estr estr = CREATE_ESTR("Unable to find function ");
APPEND_ESTR(estr, node->as.idName);
return Error(SolsType, charptr, estr.str);
}
if (var->typeinfo.type != STT_FUN) {
Estr estr = CREATE_ESTR(node->as.idName);
APPEND_ESTR(estr, " is not a callable function");
return Error(SolsType, charptr, estr.str);
}
return Success(SolsType, charptr, *var->typeinfo.returnType);
}
} }
return Error(SolsType, charptr, "Not yet implemented"); return Error(SolsType, charptr, "Not yet implemented");
} }
@@ -786,6 +801,59 @@ ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* sc
return Success(GroundProgram, charptr, gp); return Success(GroundProgram, charptr, gp);
} }
ResultType(GroundProgram, charptr) generateFunctionCallNode(SolsNode* node, SolsScope* scope) {
// Check whether the function exists and is callable
ResultType(SolsType, charptr) type = getNodeType(node, scope);
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
SolsVariable* var = findSolsVariable(scope, node->as.idName);
if (var == NULL) {
return Error(GroundProgram, charptr, "Could not find variable");
}
// Ensure the argument types match the function types
if (node->children.count != var->typeinfo.children.count) {
return Error(GroundProgram, charptr, "Incorrect amount of arguments for function");
}
for (size_t i = 0; i < node->children.count; i++) {
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[i], scope);
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
if (compareTypes(&type.as.success, &var->typeinfo.children.at[i].type) == false) {
return Error(GroundProgram, charptr, "Types incorrect for function call");
}
}
// Now that everything seems to be fine, call the function
GroundInstruction gi = groundCreateInstruction(CALL);
groundAddReferenceToInstruction(&gi, groundCreateReference(FNREF, node->as.idName));
for (size_t i = 0; i < node->children.count; i++) {
groundAddReferenceToInstruction(&gi, node->children.at[i].accessArg);
}
char* returnStr = malloc(sizeof(char) * 64);
if (returnStr == NULL) {
return Error(GroundProgram, charptr, "Failed to allocate memory for tmp identifier");
}
snprintf(returnStr, 64, "__SOLS_TMP_CALL_%zu", scope->tmpCounter++);
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, returnStr));
GroundProgram program = groundCreateProgram();
groundAddInstructionToProgram(&program, gi);
node->accessArg = groundCreateReference(VALREF, returnStr);
return Success(GroundProgram, charptr, program);
}
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) { ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
GroundProgram program = groundCreateProgram(); GroundProgram program = groundCreateProgram();
@@ -834,6 +902,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
case SNT_WHILE: generate(While); case SNT_WHILE: generate(While);
case SNT_LAMBDA: generate(Lambda); case SNT_LAMBDA: generate(Lambda);
case SNT_DEF: generate(Def); case SNT_DEF: generate(Def);
case SNT_FUNCTION_CALL: generate(FunctionCall);
} }
return Success(GroundProgram, charptr, program); return Success(GroundProgram, charptr, program);
} }

View File

@@ -11,7 +11,7 @@
#include "../lexer/SolsToken.h" #include "../lexer/SolsToken.h"
typedef enum SolsNodeType { typedef enum SolsNodeType {
SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_LAMBDA, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT SNT_IDENTIFIER, SNT_LITERAL, SNT_TYPE, SNT_CODE_BLOCK, SNT_OP_ADD, SNT_OP_SUB, SNT_OP_MUL, SNT_OP_DIV, SNT_OP_ADDTO, SNT_OP_SUBTO, SNT_OP_MULTO, SNT_OP_DIVTO, SNT_OP_INCREMENT, SNT_OP_DECREMENT, SNT_OP_SET, SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER, SNT_DEF, SNT_LAMBDA, SNT_FUNCTION_CALL, SNT_STRUCT, SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW, SNT_GROUND, SNT_ROOT
} SolsNodeType; } SolsNodeType;
struct SolsNode; struct SolsNode;

View File

@@ -1406,6 +1406,103 @@ static inline ResultType(Nothing, charptr) parseDef(SolsParser* parser) {
return Success(Nothing, charptr, {}); return Success(Nothing, charptr, {});
} }
static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser) {
ResultType(SolsNode, charptr) node = createSolsNode(SNT_FUNCTION_CALL);
if (node.error) {
return Error(Nothing, charptr, node.as.error);
}
ResultType(SolsToken, Nothing) idToken = parserPeek(parser, -1);
if (idToken.error) {
return Error(Nothing, charptr, "Couldn't get id token for some odd reason");
}
node.as.success.as.idName = idToken.as.success.as.idName;
// create a node for each expression between commas
ResultType(SolsToken, Nothing) peek = parserPeek(parser, 1);
if (peek.error) {
return Error(Nothing, charptr, "Expecting ')' or a value");
}
SolsTokens tokens;
for (;;) {
ResultType(SolsTokens, charptr) resultTokens = createSolsTokens();
if (resultTokens.error) {
return Error(Nothing, charptr, resultTokens.as.error);
}
tokens = resultTokens.as.success;
size_t curlys = 0;
size_t parens = 0;
for (;;) {
peek = parserPeek(parser, 1);
if (peek.error) {
return Error(Nothing, charptr, "Expecting ')'");
}
if (peek.as.success.type == STT_OPEN_PAREN) {
parens++;
}
if (peek.as.success.type == STT_CLOSE_PAREN) {
if (parens == 0) {
break;
}
parens--;
}
if (peek.as.success.type == STT_OPEN_CURLY) {
curlys++;
}
if (peek.as.success.type == STT_CLOSE_CURLY) {
curlys--;
}
if (curlys == 0 && parens == 0 && peek.as.success.type == STT_COMMA) {
break;
}
addTokenToSolsTokens(&tokens, peek.as.success);
parserConsume(parser);
}
ResultType(SolsParser, charptr) newParser = createSolsParser(&tokens);
if (newParser.error) {
return Error(Nothing, charptr, newParser.as.error);
}
newParser.as.success.currentParent = &newParser.as.success.output;
ResultType(Nothing, charptr) parsed = parse(&newParser.as.success);
if (parsed.error) {
addToParserErrors(parser, parsed.as.error);
return Success(Nothing, charptr, {});
}
if (newParser.as.success.output.children.count < 1) {
return Error(Nothing, charptr, "Expecting a value before ',' or ')'");
}
addChildToSolsNode(&node.as.success, newParser.as.success.output.children.at[0]);
peek = parserConsume(parser);
if (peek.error) {
return Error(Nothing, charptr, "Expecting ')' or ','");
}
if (peek.as.success.type == STT_CLOSE_PAREN) {
break;
}
addChildToSolsNode(parser->currentParent, node.as.success);
}
return Success(Nothing, charptr, {});
}
static inline ResultType(Nothing, charptr) parseOpenParen(SolsParser* parser) {
return Error(Nothing, charptr, "WIP");
}
static inline ResultType(Nothing, charptr) parseCloseParen(SolsParser* parser) {
(void)parser;
return Error(Nothing, charptr, "Extra closing parenthases");
}
ResultType(Nothing, charptr) parse(SolsParser* parser) { ResultType(Nothing, charptr) parse(SolsParser* parser) {
parser->currentParent = &parser->output; parser->currentParent = &parser->output;
for (;;) { for (;;) {
@@ -1434,6 +1531,14 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
case STT_OP_EQLESSER: PARSER_HANDLE(EqLesser); case STT_OP_EQLESSER: PARSER_HANDLE(EqLesser);
case STT_OPEN_CURLY: PARSER_HANDLE(CodeBlock); case STT_OPEN_CURLY: PARSER_HANDLE(CodeBlock);
case STT_CLOSE_CURLY: PARSER_HANDLE(CloseCurly); case STT_CLOSE_CURLY: PARSER_HANDLE(CloseCurly);
case STT_OPEN_PAREN: {
if (parser->output.children.count > 0 && parser->output.children.at[parser->output.children.count - 1].type == SNT_IDENTIFIER) {
PARSER_HANDLE(FunctionCall);
} else {
PARSER_HANDLE(OpenParen);
}
}
case STT_CLOSE_PAREN: PARSER_HANDLE(CloseParen);
} }
} }
if (parser->errors.count > 0) { if (parser->errors.count > 0) {