Start work on function calling
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user