Function calling now works, only need return
This commit is contained in:
2
build.c
2
build.c
@@ -7,7 +7,7 @@ if [[ ! -v OUTPUT ]]; then
|
||||
fi
|
||||
|
||||
if [[ ! -v CFLAGS ]]; then
|
||||
CFLAGS="-O3 -Wall -Wextra -pedantic"
|
||||
CFLAGS="-O3 -Wall -Wextra -pedantic -ggdb"
|
||||
fi
|
||||
|
||||
gcc "$0" -o "$OUTPUT" $CFLAGS -lgroundvm
|
||||
|
||||
@@ -756,12 +756,31 @@ ResultType(GroundProgram, charptr) generateLambdaNode(SolsNode* node, SolsScope*
|
||||
ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* scope) {
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
|
||||
// Register the function in the current scope so calls can resolve it
|
||||
// node->children.at[0] is the identifier node for the function name
|
||||
if (node->children.count < 2 || node->children.at[0].type != SNT_IDENTIFIER) {
|
||||
return Error(GroundProgram, charptr, "Invalid def node shape (expected name + body)");
|
||||
}
|
||||
|
||||
char* fnName = node->children.at[0].as.idName;
|
||||
SolsVariable* existing = findSolsVariable(scope, fnName);
|
||||
if (existing == NULL) {
|
||||
addVariableToScope(scope, fnName, node->as.type);
|
||||
} else {
|
||||
if (existing->typeinfo.type != STT_FUN) {
|
||||
return Error(GroundProgram, charptr, "A non-function variable already exists with this name");
|
||||
}
|
||||
if (compareTypes(&existing->typeinfo, &node->as.type) == false) {
|
||||
return Error(GroundProgram, charptr, "Function already exists with a different type signature");
|
||||
}
|
||||
}
|
||||
|
||||
// Generate function signature
|
||||
GroundInstruction signature = groundCreateInstruction(FUN);
|
||||
|
||||
node->accessArg = groundCreateReference(VALREF, node->children.at[0].as.idName);
|
||||
node->accessArg = groundCreateReference(VALREF, fnName);
|
||||
|
||||
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, node->children.at[0].as.idName));
|
||||
groundAddReferenceToInstruction(&signature, groundCreateReference(FNREF, fnName));
|
||||
ResultType(GroundArg, charptr) arg = createGroundArgFromSolsType(node->as.type.returnType);
|
||||
if (arg.error) {
|
||||
return Error(GroundProgram, charptr, arg.as.error);
|
||||
@@ -794,7 +813,7 @@ ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* sc
|
||||
for (size_t i = 0; i < bodyCode.as.success.size; i++) {
|
||||
groundAddInstructionToProgram(&gp, bodyCode.as.success.instructions[i]);
|
||||
}
|
||||
|
||||
|
||||
// End the function
|
||||
groundAddInstructionToProgram(&gp, groundCreateInstruction(ENDFUN));
|
||||
|
||||
|
||||
@@ -1407,53 +1407,60 @@ static inline ResultType(Nothing, charptr) parseDef(SolsParser* parser) {
|
||||
}
|
||||
|
||||
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");
|
||||
// The identifier (function name) was already parsed as a node right before '('
|
||||
if (parser->currentParent->children.count < 1 ||
|
||||
parser->currentParent->children.at[parser->currentParent->children.count - 1].type != SNT_IDENTIFIER) {
|
||||
return Error(Nothing, charptr, "Expecting identifier before '(' for function call");
|
||||
}
|
||||
|
||||
node.as.success.as.idName = idToken.as.success.as.idName;
|
||||
SolsNode callee = parser->currentParent->children.at[parser->currentParent->children.count - 1];
|
||||
parser->currentParent->children.count--; // remove callee identifier node; we'll replace it with the call node
|
||||
|
||||
// create a node for each expression between commas
|
||||
node.as.success.as.idName = callee.as.idName;
|
||||
node.as.success.line = callee.line;
|
||||
|
||||
// Empty argument list: foo()
|
||||
ResultType(SolsToken, Nothing) peek = parserPeek(parser, 1);
|
||||
if (peek.error) {
|
||||
return Error(Nothing, charptr, "Expecting ')' or a value");
|
||||
}
|
||||
SolsTokens tokens;
|
||||
if (peek.as.success.type == STT_CLOSE_PAREN) {
|
||||
parserConsume(parser); // consume ')'
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
return Success(Nothing, charptr, {});
|
||||
}
|
||||
|
||||
// Parse each argument expression separated by commas until ')'
|
||||
for (;;) {
|
||||
ResultType(SolsTokens, charptr) resultTokens = createSolsTokens();
|
||||
if (resultTokens.error) {
|
||||
return Error(Nothing, charptr, resultTokens.as.error);
|
||||
}
|
||||
tokens = resultTokens.as.success;
|
||||
SolsTokens 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_OPEN_PAREN) parens++;
|
||||
if (peek.as.success.type == STT_CLOSE_PAREN) {
|
||||
if (parens == 0) {
|
||||
break;
|
||||
}
|
||||
if (parens == 0) break;
|
||||
parens--;
|
||||
}
|
||||
if (peek.as.success.type == STT_OPEN_CURLY) {
|
||||
curlys++;
|
||||
}
|
||||
if (peek.as.success.type == STT_CLOSE_CURLY) {
|
||||
curlys--;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1468,6 +1475,7 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
|
||||
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);
|
||||
@@ -1477,8 +1485,11 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
|
||||
if (newParser.as.success.output.children.count < 1) {
|
||||
return Error(Nothing, charptr, "Expecting a value before ',' or ')'");
|
||||
}
|
||||
|
||||
// One argument expression -> one AST node
|
||||
addChildToSolsNode(&node.as.success, newParser.as.success.output.children.at[0]);
|
||||
|
||||
// Consume ',' or ')'
|
||||
peek = parserConsume(parser);
|
||||
if (peek.error) {
|
||||
return Error(Nothing, charptr, "Expecting ')' or ','");
|
||||
@@ -1486,11 +1497,13 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
|
||||
if (peek.as.success.type == STT_CLOSE_PAREN) {
|
||||
break;
|
||||
}
|
||||
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
|
||||
if (peek.as.success.type != STT_COMMA) {
|
||||
return Error(Nothing, charptr, "Expecting ',' or ')'");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the fully-built call node once
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
return Success(Nothing, charptr, {});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user