diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 4aa1985..e222712 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -11,6 +11,7 @@ #include "../lexer/SolsType.h" #include "../parser/parser.h" #include "../parser/SolsNode.h" +#include "../typeparser/typeparser.h" #include "../include/estr.h" #include "../include/uthash.h" #include "../include/ansii.h" @@ -291,33 +292,60 @@ static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node, if (node->children.count < 2) { return Error(GroundProgram, charptr, "set requires arguments"); } - if (node->children.at[0].type != SNT_IDENTIFIER) { - return Error(GroundProgram, charptr, "set requires an identifier before '='"); - } - SolsVariable* var = findSolsVariable(scope, node->children.at[0].as.idName); - ResultType(SolsType, charptr) type = getNodeType(&node->children.at[1], scope); - if (type.error) { - return Error(GroundProgram, charptr, type.as.error); - } - if (var == NULL) { - addVariableToScope(scope, node->children.at[0].as.idName, type.as.success); - } else { - ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope); + if (node->children.at[0].type == SNT_IDENTIFIER) { + SolsVariable* var = findSolsVariable(scope, node->children.at[0].as.idName); + ResultType(SolsType, charptr) type = getNodeType(&node->children.at[1], scope); if (type.error) { return Error(GroundProgram, charptr, type.as.error); } - if (compareTypes(&var->typeinfo, &type.as.success) == false) { - return Error(GroundProgram, charptr, "Type of variable cannot be changed"); + if (var == NULL) { + addVariableToScope(scope, node->children.at[0].as.idName, type.as.success); + } else { + ResultType(SolsType, charptr) type = getNodeType(&node->children.at[0], scope); + if (type.error) { + return Error(GroundProgram, charptr, type.as.error); + } + if (compareTypes(&var->typeinfo, &type.as.success) == false) { + return Error(GroundProgram, charptr, "Type of variable cannot be changed"); + } } + + GroundProgram gp = groundCreateProgram(); + GroundInstruction gi = groundCreateInstruction(SET); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].as.idName)); + groundAddReferenceToInstruction(&gi, node->children.at[1].accessArg); + groundAddInstructionToProgram(&gp, gi); + + return Success(GroundProgram, charptr, gp); + } else if (node->children.at[0].type == SNT_DOT) { + ResultType(SolsType, charptr) ltype = getNodeType(&node->children.at[0].children.at[0], scope); + if (ltype.error) { + return Error(GroundProgram, charptr, ltype.as.error); + } + ResultType(SolsType, charptr) rtype = getNodeType(&node->children.at[1], scope); + if (rtype.error) { + return Error(GroundProgram, charptr, rtype.as.error); + } + ResultType(SolsType, charptr) type = findStructMemberType(<ype.as.success, node->children.at[0].children.at[1].as.idName); + if (type.error) { + return Error(GroundProgram, charptr, type.as.error); + } + if (compareTypes(&type.as.success, &rtype.as.success) == false) { + return Error(GroundProgram, charptr, "Type of member cannot be changed"); + } + + // TODO codegen for nested types + + GroundProgram gp = groundCreateProgram(); + GroundInstruction gi = groundCreateInstruction(SETFIELD); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].children.at[0].accessArg.value.refName)); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].children.at[1].as.idName)); + groundAddReferenceToInstruction(&gi, node->children.at[1].accessArg); + groundAddInstructionToProgram(&gp, gi); + return Success(GroundProgram, charptr, gp); + } else { + return Error(GroundProgram, charptr, "set requires an identifier before '='"); } - - GroundProgram gp = groundCreateProgram(); - GroundInstruction gi = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, node->children.at[0].as.idName)); - groundAddReferenceToInstruction(&gi, node->children.at[1].accessArg); - groundAddInstructionToProgram(&gp, gi); - - return Success(GroundProgram, charptr, gp); } static inline ResultType(GroundProgram, charptr) generateAddNode(SolsNode* node, SolsScope* scope) { @@ -976,8 +1004,16 @@ ResultType(GroundProgram, charptr) generateUseNode(SolsNode* node, SolsScope* sc return Error(GroundProgram, charptr, "Error with use"); } + // Detect and parse types + ResultType(SolsTokens, charptr) typed = addTypeInfo(&lexer.as.success.output); + if (typed.error) { + printf("While parsing types in file %s:\n", filePath.str); + printf("%s\n", typed.as.error); + return Error(GroundProgram, charptr, "Error with use"); + } + // Parse file - ResultType(SolsParser, charptr) parser = createSolsParser(&lexer.as.success.output); + ResultType(SolsParser, charptr) parser = createSolsParser(&typed.as.success); if (parser.error) { printf("While parsing file %s:\n", filePath.str); printf("Error while creating parser: %s\n", parser.as.error); diff --git a/src/parser/parser.c b/src/parser/parser.c index 5655842..42cc012 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -175,7 +175,8 @@ static inline ResultType(Nothing, charptr) parseSet(SolsParser* parser) { if (parser->currentParent->children.count < 1) { return Error(Nothing, charptr, "Expecting identifier before '='"); } - if (parser->currentParent->children.at[parser->output.children.count - 1].type != SNT_IDENTIFIER) { + if (parser->currentParent->children.at[parser->output.children.count - 1].type != SNT_IDENTIFIER && + parser->currentParent->children.at[parser->output.children.count - 1].type != SNT_DOT) { return Error(Nothing, charptr, "Expecting identifier before '='"); } @@ -1837,6 +1838,7 @@ ResultType(Nothing, charptr) parseDot(SolsParser* parser) { return Error(Nothing, charptr, "Expecting identifier after '.'"); } addChildToSolsNode(&newNode.as.success, left); + parser->currentParent->children.count--; addChildToSolsNode(&newNode.as.success, ({ ResultType(SolsNode, charptr) _result = createSolsNode(SNT_IDENTIFIER, right.as.success.as.idName); if (_result.error) {