From e285b2c59f15268c25fb71f25dcde7c5ff9688ab Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Tue, 27 Jan 2026 14:10:57 +1100 Subject: [PATCH] Use `new` to create an object from a struct --- src/parser.cpp | 86 ++++++++++++++++++++++++++++++++++++++++++++--- src/parser.h | 10 ++++++ tests/struct.sols | 5 +++ 3 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index 69320c9..4a958d4 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -13,6 +13,46 @@ namespace Solstice { namespace Parser { + bool operator==(const SolStruct& left, const SolStruct& right) { + return left.signature == right.signature; + } + + SolStruct::SolStruct(SolNode in) { + signature = "template("; + genSignature = "object("; + bool first = true; + for (auto& node : in.children) { + if (!first) { + signature += ", "; + genSignature += ", "; + } else { + first = false; + } + if (node.nodeType == SolNodeType::FunctionDef) { + // FIXME do this later + } + if (node.nodeType == SolNodeType::Identifier) { + if (node.children[0].nodeType == SolNodeType::Value) { + signature += node.children[0].data.getTypeString(); + genSignature += node.children[0].data.getTypeString(); + } else if (node.children[0].nodeType == SolNodeType::Identifier) { + if (variables.find(node.children[0].outputId) != variables.end()) { + signature += variables[node.children[0].outputId]; + genSignature += variables[node.children[0].outputId]; + } else { + return; + } + } else { + return; + } + signature += " " + node.outputId; + genSignature += " " + node.outputId; + } + } + signature += ")"; + genSignature += ")"; + } + char* copyString(std::string s) { char* str = (char*) malloc(s.size() + 1); strcpy(str, s.c_str()); @@ -23,8 +63,13 @@ namespace Solstice { return id.rfind("tmp_", 0) == 0; } + // Contains the type information for all variables. + // The first string is the variable name, the second is the type. std::map variables; + // Contains type information for all templates. + std::map templates; + std::string checkNodeReturnType(SolNode i) { switch (i.nodeType) { case SolNodeType::Identifier: { @@ -115,6 +160,12 @@ namespace Solstice { return retType; break; } + case SolNodeType::New: { + if (templates.find(i.children[0].outputId) == templates.end()) { + Error::typingError("Cannot find template " + i.children[0].outputId, i.line, i.lineContent); + } + return templates[i.children[0].outputId].genSignature; + } case SolNodeType::Puts: case SolNodeType::If: case SolNodeType::While: @@ -754,6 +805,11 @@ namespace Solstice { SolGroundCodeBlock codeBlock; GroundInstruction gi = groundCreateInstruction(STRUCT); + SolStruct newStruct(*this); + + variables[outputId] = newStruct.signature; + templates[outputId] = newStruct; + // struct -name groundAddReferenceToInstruction(&gi, groundCreateReference(TYPEREF, copyString(outputId))); codeBlock.code.push_back(gi); @@ -794,6 +850,19 @@ namespace Solstice { code.push_back(codeBlock); break; } + case SolNodeType::New: { + SolGroundCodeBlock codeBlock; + GroundInstruction gi = groundCreateInstruction(INIT); + if (templates.find(children[0].outputId) == templates.end()) { + Error::typingError("Unknown template " + children[0].outputId, line, lineContent); + } + outputId = "tmp_" + std::to_string(tmpIdIterator); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(TYPEREF, copyString(children[0].outputId))); + codeBlock.code.push_back(gi); + code.push_back(codeBlock); + break; + } default: {} } return code; @@ -1605,11 +1674,20 @@ namespace Solstice { } case SolNodeType::New: { - SolNode putsNode(SolNodeType::New); - putsNode.line = tokenObj.line; - putsNode.lineContent = tokenObj.lineContent; + SolNode newNode(SolNodeType::New); + newNode.line = tokenObj.line; + newNode.lineContent = tokenObj.lineContent; auto typeopt = consume(); - rootNode.addNode(putsNode); + if (typeopt) { + SolNode typeNode(SolNodeType::Identifier); + typeNode.outputId = typeopt.value().value; + typeNode.line = typeopt.value().line; + typeNode.lineContent = typeopt.value().lineContent; + newNode.addNode(typeNode); + } else { + Error::syntaxError("Expected type name after 'new'", tokenObj.line, tokenObj.lineContent); + } + rootNode.addNode(newNode); break; } } diff --git a/src/parser.h b/src/parser.h index 7609d0e..56259eb 100644 --- a/src/parser.h +++ b/src/parser.h @@ -124,6 +124,16 @@ namespace Solstice { const std::vector generateCode(); }; + class SolStruct { + std::map fields; + public: + std::string signature; // template(...) + std::string genSignature; // object(...) + SolStruct() = default; + friend bool operator==(const SolStruct& left, const SolStruct& right); + SolStruct(SolNode in); + }; + class Parser { std::vector tokensToParse; size_t current; diff --git a/tests/struct.sols b/tests/struct.sols index 431e620..87874a0 100644 --- a/tests/struct.sols +++ b/tests/struct.sols @@ -1,3 +1,8 @@ struct dingus { x = 5 + y = "dingus" } + +e = new dingus +puts e +puts dingus