diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 9173761..6376aa8 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -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++) { + 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); diff --git a/src/parser/parser.c b/src/parser/parser.c index 42cc012..852d1eb 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -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"); }