forked from solstice/solstice
Call methods inside objects
This commit is contained in:
@@ -39,6 +39,9 @@ char* createCodegenError(SolsNode* node, char* what) {
|
||||
}
|
||||
|
||||
static ResultType(SolsType, charptr) resolveValueType(SolsType* type, SolsScope* scope) {
|
||||
if (type == NULL) {
|
||||
return Error(SolsType, charptr, "Type is null");
|
||||
}
|
||||
if (type->identifierType == NULL) {
|
||||
return Success(SolsType, charptr, *type);
|
||||
}
|
||||
@@ -237,22 +240,26 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
||||
}
|
||||
return resolveValueType(&var->typeinfo, scope);
|
||||
}
|
||||
case SNT_LAMBDA: {
|
||||
case SNT_LAMBDA:
|
||||
case SNT_DEF: {
|
||||
return Success(SolsType, charptr, node->as.type);
|
||||
}
|
||||
case SNT_FUNCTION_CALL: {
|
||||
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
||||
if (var == NULL) {
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
||||
//SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
||||
if (type.error) {
|
||||
Estr estr = CREATE_ESTR("Unable to find function ");
|
||||
APPEND_ESTR(estr, node->as.idName);
|
||||
if (node->children.at[0].type == SNT_IDENTIFIER) {
|
||||
APPEND_ESTR(estr, node->children.at[0].as.idName);
|
||||
}
|
||||
return Error(SolsType, charptr, estr.str);
|
||||
}
|
||||
if (var->typeinfo.type != STT_FUN) {
|
||||
if (type.as.success.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 resolveValueType(var->typeinfo.returnType, scope);
|
||||
return resolveValueType(type.as.success.returnType, scope);
|
||||
}
|
||||
case SNT_EXPR_IN_PAREN: {
|
||||
return getNodeType(&node->children.at[node->children.count - 1], scope);
|
||||
@@ -934,42 +941,42 @@ ResultType(GroundProgram, charptr) generateDefNode(SolsNode* node, SolsScope* sc
|
||||
ResultType(GroundProgram, charptr) generateFunctionCallNode(SolsNode* node, SolsScope* scope) {
|
||||
|
||||
// Check whether the function exists and is callable
|
||||
ResultType(SolsType, charptr) type = getNodeType(node, scope);
|
||||
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], 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) {
|
||||
if (node->children.count - 1 != type.as.success.children.count) {
|
||||
return Error(GroundProgram, charptr, "Incorrect amount of arguments for function");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
for (size_t i = 1; 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);
|
||||
}
|
||||
|
||||
ResultType(SolsType, charptr) expectedType = resolveValueType(&var->typeinfo.children.at[i].type, scope);
|
||||
if (expectedType.error) {
|
||||
return Error(GroundProgram, charptr, expectedType.as.error);
|
||||
}
|
||||
|
||||
if (compareTypes(&type.as.success, &expectedType.as.success) == false) {
|
||||
if (compareTypes(&type.as.success, &type.as.success) == 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++) {
|
||||
// Now that everything seems to be fine, call the function
|
||||
GroundInstruction gi;
|
||||
|
||||
// If we're calling a method, use the instruction for that
|
||||
if (node->children.at[0].type == SNT_DOT) {
|
||||
gi = groundCreateInstruction(CALLMETHOD);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].children.at[0].accessArg.value.refName));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(FNREF, node->children.at[0].children.at[1].as.idName));
|
||||
} else {
|
||||
gi = groundCreateInstruction(CALL);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(FNREF, node->children.at[0].accessArg.value.refName));
|
||||
}
|
||||
|
||||
for (size_t i = 1; i < node->children.count; i++) {
|
||||
groundAddReferenceToInstruction(&gi, node->children.at[i].accessArg);
|
||||
}
|
||||
|
||||
@@ -1112,6 +1119,39 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
||||
for (size_t i = 0; i < node->children.count; i++) {
|
||||
// Add to type for type system
|
||||
SolsNode* child = &node->children.at[i];
|
||||
if (child->type == SNT_DEF) {
|
||||
ResultType(SolsType, charptr) childType = getNodeType(child, scope);
|
||||
if (childType.error) {
|
||||
return Error(GroundProgram, charptr, childType.as.error);
|
||||
}
|
||||
addChildToSolsType(&type, childType.as.success, child->children.at[0].as.idName);
|
||||
|
||||
// Add struct members to new scope
|
||||
SolsScope childScope = copySolsScope(scope);
|
||||
|
||||
SolsType selfType = ({
|
||||
ResultType(SolsType, charptr) _result = copySolsType(&type);
|
||||
if (_result.error) {
|
||||
return Error(GroundProgram, charptr, _result.as.error);
|
||||
}
|
||||
_result.as.success;
|
||||
});
|
||||
selfType.type = STT_OBJECT;
|
||||
|
||||
addVariableToScope(&childScope, "self", selfType);
|
||||
|
||||
// Generate the def node and add to struct
|
||||
ResultType(GroundProgram, charptr) defNode = generateDefNode(child, &childScope);
|
||||
if (defNode.error) {
|
||||
return Error(GroundProgram, charptr, defNode.as.error);
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < defNode.as.success.size; j++) {
|
||||
groundAddInstructionToProgram(&structDef, defNode.as.success.instructions[j]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
ResultType(SolsType, charptr) childType = getNodeType(&child->children.at[1], scope);
|
||||
if (childType.error) {
|
||||
return Error(GroundProgram, charptr, childType.as.error);
|
||||
|
||||
@@ -135,8 +135,10 @@ void createParserError(SolsParser* parser, char* what) {
|
||||
APPEND_ESTR(err, "\n\n");
|
||||
// Append line before
|
||||
if (!prevToken.error) {
|
||||
APPEND_ESTR(err, prevToken.as.success.line.content);
|
||||
APPEND_ESTR(err, "\n");
|
||||
if (prevToken.as.success.line.content != NULL) {
|
||||
APPEND_ESTR(err, prevToken.as.success.line.content);
|
||||
APPEND_ESTR(err, "\n");
|
||||
}
|
||||
}
|
||||
// Append the actual content of the line that failed
|
||||
APPEND_ESTR(err, token.line.content);
|
||||
@@ -1436,15 +1438,14 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (parser->currentParent->children.count < 1) {
|
||||
return Error(Nothing, charptr, "Expecting identifier before '(' for function call");
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
node.as.success.as.idName = callee.as.idName;
|
||||
addChildToSolsNode(&node.as.success, callee);
|
||||
node.as.success.line = callee.line;
|
||||
|
||||
// Empty argument list: foo()
|
||||
@@ -1733,6 +1734,16 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
||||
}
|
||||
_result.as.success;
|
||||
});
|
||||
if (keyTok.type == STT_KW_DEF) {
|
||||
// def
|
||||
ResultType(Nothing, charptr) defNode = parseDef(parser);
|
||||
if (defNode.error) {
|
||||
return Error(Nothing, charptr, defNode.as.error);
|
||||
}
|
||||
addChildToSolsNode(&structNode, parser->currentParent->children.at[parser->currentParent->children.count - 1]);
|
||||
parser->currentParent->children.count--;
|
||||
continue;
|
||||
}
|
||||
if (keyTok.type != STT_IDENTIFIER) {
|
||||
return Error(Nothing, charptr, "Expecting struct key");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user