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) {
|
static ResultType(SolsType, charptr) resolveValueType(SolsType* type, SolsScope* scope) {
|
||||||
|
if (type == NULL) {
|
||||||
|
return Error(SolsType, charptr, "Type is null");
|
||||||
|
}
|
||||||
if (type->identifierType == NULL) {
|
if (type->identifierType == NULL) {
|
||||||
return Success(SolsType, charptr, *type);
|
return Success(SolsType, charptr, *type);
|
||||||
}
|
}
|
||||||
@@ -237,22 +240,26 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
|
|||||||
}
|
}
|
||||||
return resolveValueType(&var->typeinfo, scope);
|
return resolveValueType(&var->typeinfo, scope);
|
||||||
}
|
}
|
||||||
case SNT_LAMBDA: {
|
case SNT_LAMBDA:
|
||||||
|
case SNT_DEF: {
|
||||||
return Success(SolsType, charptr, node->as.type);
|
return Success(SolsType, charptr, node->as.type);
|
||||||
}
|
}
|
||||||
case SNT_FUNCTION_CALL: {
|
case SNT_FUNCTION_CALL: {
|
||||||
SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope);
|
||||||
if (var == NULL) {
|
//SolsVariable* var = findSolsVariable(scope, node->as.idName);
|
||||||
|
if (type.error) {
|
||||||
Estr estr = CREATE_ESTR("Unable to find function ");
|
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);
|
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);
|
Estr estr = CREATE_ESTR(node->as.idName);
|
||||||
APPEND_ESTR(estr, " is not a callable function");
|
APPEND_ESTR(estr, " is not a callable function");
|
||||||
return Error(SolsType, charptr, estr.str);
|
return Error(SolsType, charptr, estr.str);
|
||||||
}
|
}
|
||||||
return resolveValueType(var->typeinfo.returnType, scope);
|
return resolveValueType(type.as.success.returnType, scope);
|
||||||
}
|
}
|
||||||
case SNT_EXPR_IN_PAREN: {
|
case SNT_EXPR_IN_PAREN: {
|
||||||
return getNodeType(&node->children.at[node->children.count - 1], scope);
|
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) {
|
ResultType(GroundProgram, charptr) generateFunctionCallNode(SolsNode* node, SolsScope* scope) {
|
||||||
|
|
||||||
// Check whether the function exists and is callable
|
// 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) {
|
if (type.error) {
|
||||||
return Error(GroundProgram, charptr, type.as.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
|
// 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");
|
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);
|
ResultType(SolsType, charptr) type = getNodeType(&node->children.at[i], scope);
|
||||||
if (type.error) {
|
if (type.error) {
|
||||||
return Error(GroundProgram, charptr, type.as.error);
|
return Error(GroundProgram, charptr, type.as.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultType(SolsType, charptr) expectedType = resolveValueType(&var->typeinfo.children.at[i].type, scope);
|
if (compareTypes(&type.as.success, &type.as.success) == false) {
|
||||||
if (expectedType.error) {
|
|
||||||
return Error(GroundProgram, charptr, expectedType.as.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compareTypes(&type.as.success, &expectedType.as.success) == false) {
|
|
||||||
return Error(GroundProgram, charptr, "Types incorrect for function call");
|
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);
|
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++) {
|
for (size_t i = 0; i < node->children.count; i++) {
|
||||||
// Add to type for type system
|
// Add to type for type system
|
||||||
SolsNode* child = &node->children.at[i];
|
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);
|
ResultType(SolsType, charptr) childType = getNodeType(&child->children.at[1], scope);
|
||||||
if (childType.error) {
|
if (childType.error) {
|
||||||
return Error(GroundProgram, charptr, childType.as.error);
|
return Error(GroundProgram, charptr, childType.as.error);
|
||||||
|
|||||||
@@ -135,9 +135,11 @@ void createParserError(SolsParser* parser, char* what) {
|
|||||||
APPEND_ESTR(err, "\n\n");
|
APPEND_ESTR(err, "\n\n");
|
||||||
// Append line before
|
// Append line before
|
||||||
if (!prevToken.error) {
|
if (!prevToken.error) {
|
||||||
|
if (prevToken.as.success.line.content != NULL) {
|
||||||
APPEND_ESTR(err, prevToken.as.success.line.content);
|
APPEND_ESTR(err, prevToken.as.success.line.content);
|
||||||
APPEND_ESTR(err, "\n");
|
APPEND_ESTR(err, "\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Append the actual content of the line that failed
|
// Append the actual content of the line that failed
|
||||||
APPEND_ESTR(err, token.line.content);
|
APPEND_ESTR(err, token.line.content);
|
||||||
APPEND_ESTR(err, "\n");
|
APPEND_ESTR(err, "\n");
|
||||||
@@ -1436,15 +1438,14 @@ static inline ResultType(Nothing, charptr) parseFunctionCall(SolsParser* parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The identifier (function name) was already parsed as a node right before '('
|
// The identifier (function name) was already parsed as a node right before '('
|
||||||
if (parser->currentParent->children.count < 1 ||
|
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");
|
return Error(Nothing, charptr, "Expecting identifier before '(' for function call");
|
||||||
}
|
}
|
||||||
|
|
||||||
SolsNode callee = parser->currentParent->children.at[parser->currentParent->children.count - 1];
|
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
|
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;
|
node.as.success.line = callee.line;
|
||||||
|
|
||||||
// Empty argument list: foo()
|
// Empty argument list: foo()
|
||||||
@@ -1733,6 +1734,16 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
|||||||
}
|
}
|
||||||
_result.as.success;
|
_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) {
|
if (keyTok.type != STT_IDENTIFIER) {
|
||||||
return Error(Nothing, charptr, "Expecting struct key");
|
return Error(Nothing, charptr, "Expecting struct key");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user