diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index a634032..3777f70 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -1199,6 +1199,32 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope* } else if (child->type == SNT_CONSTRUCTOR) { constructor = child; continue; + } else if (child->type == SNT_DESTRUCTOR) { + GroundInstruction destructorInst = groundCreateInstruction(FUN); + groundAddReferenceToInstruction(&destructorInst, groundCreateReference(FNREF, "destructor")); + groundAddReferenceToInstruction(&destructorInst, groundCreateReference(TYPEREF, "any")); + groundAddInstructionToProgram(&structDef, destructorInst); + + 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); + + ResultType(GroundProgram, charptr) bodyCode = generateCode(child, &childScope); + if (bodyCode.error) return bodyCode; + for (size_t j = 0; j < bodyCode.as.success.size; j++) { + groundAddInstructionToProgram(&structDef, bodyCode.as.success.instructions[j]); + } + groundAddInstructionToProgram(&structDef, groundCreateInstruction(ENDFUN)); + continue; } ResultType(SolsType, charptr) childType = getNodeType(&child->children.at[1], scope); if (childType.error) { diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 9ac1c39..6360a22 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -65,6 +65,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = { {"subtracts", STT_OP_SUBTO}, {"multiplies", STT_OP_MULTO}, {"divides", STT_OP_DIVTO}, + {"class", STT_KW_STRUCT} #endif }; diff --git a/src/parser/parser.c b/src/parser/parser.c index af01a0a..b17f533 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1775,6 +1775,46 @@ static inline ResultType(Nothing, charptr) parseConstructor(SolsParser* parser) return Success(Nothing, charptr, {}); } +static inline ResultType(Nothing, charptr) parseDestructor(SolsParser* parser) { + ResultType(SolsNode, charptr) node = createSolsNode(SNT_DESTRUCTOR); + ResultType(SolsType, charptr) type = createSolsType(STT_FUN); + if (type.error) { + return Error(Nothing, charptr, type.as.error); + } + type.as.success.returnType = malloc(sizeof(SolsType)); + if (type.as.success.returnType == NULL) { + return Error(Nothing, charptr, "Failed to allocate memory for return type"); + } + type.as.success.returnType->type = STT_NONE; + + // Skip newlines before the opening curly brace + while (parserPeek(parser, 1).as.success.type == STT_LINE_END) { + parserConsume(parser); + } + + ResultType(SolsToken, Nothing) openCurly = parserConsume(parser); + if (openCurly.error || openCurly.as.success.type != STT_OPEN_CURLY) { + return Error(Nothing, charptr, "Expecting opening curly brace ({) for destructor body"); + } + + // Add node to parent + addChildToSolsNode(parser->currentParent, node.as.success); + + // Parse code block + ResultType(Nothing, charptr) res = parseCodeBlock(parser); + if (res.error) return res; + + // Last child of parent is code block, we need to move it + SolsNode codeBlock = parser->currentParent->children.at[parser->currentParent->children.count - 1]; + parser->currentParent->children.count--; + + // We need to get the actual node from the parent to modify it + SolsNode* constructorNode = &parser->currentParent->children.at[parser->currentParent->children.count - 1]; + addChildToSolsNode(constructorNode, codeBlock); + return Success(Nothing, charptr, {}); + +} + static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) { // Get struct name SolsNode structNode = ({ @@ -1854,6 +1894,16 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) { parser->currentParent->children.count--; continue; } + if (keyTok.type == STT_KW_DESTRUCTOR) { + // destructor {} + ResultType(Nothing, charptr) destructorNode = parseDestructor(parser); + if (destructorNode.error) { + return Error(Nothing, charptr, destructorNode.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"); }