Call methods inside objects

This commit is contained in:
2026-04-11 12:03:10 +10:00
parent 1cf995f7ac
commit 2e7b5b7480
2 changed files with 80 additions and 29 deletions

View File

@@ -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);

View File

@@ -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");
}