Start work on structs

This commit is contained in:
2026-01-25 17:40:07 +11:00
parent 44785185f7
commit 010d155f5d
5 changed files with 174 additions and 4 deletions

View File

@@ -216,7 +216,7 @@ namespace Solstice {
code = parsedStdlib.generateCode();
}
}
if (nodeType != SolNodeType::If && nodeType != SolNodeType::While) for (auto& child : children) {
if (nodeType != SolNodeType::If && nodeType != SolNodeType::While && nodeType != SolNodeType::Struct) for (auto& child : children) {
auto childCode = child.generateCode();
code.insert(code.end(), childCode.begin(), childCode.end());
}
@@ -749,6 +749,51 @@ namespace Solstice {
code.push_back(codeBlock);
break;
}
case SolNodeType::Struct: {
//SolGroundCodeBlock preProcessCodeBlock;
SolGroundCodeBlock codeBlock;
GroundInstruction gi = groundCreateInstruction(STRUCT);
// struct -name
groundAddReferenceToInstruction(&gi, groundCreateReference(TYPEREF, copyString(outputId)));
codeBlock.code.push_back(gi);
// contents of struct
for (SolNode& child : children) {
if (child.nodeType == SolNodeType::Identifier) {
gi = groundCreateInstruction(SET);
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(child.outputId)));
SolNode& valNode = child.children[0];
if (valNode.nodeType == SolNodeType::Value) {
GroundValue gv;
switch (valNode.data.type) {
case SolDataType::String: gv = groundCreateValue(STRING, copyString(valNode.data.getString().value())); break;
case SolDataType::Int: gv = groundCreateValue(INT, valNode.data.getInt().value()); break;
case SolDataType::Double: gv = groundCreateValue(DOUBLE, valNode.data.getDouble().value()); break;
case SolDataType::Char: gv = groundCreateValue(CHAR, valNode.data.getChar().value()); break;
case SolDataType::Bool: gv = groundCreateValue(BOOL, valNode.data.getBool().value()); break;
default: Error::syntaxError("Struct member must be assigned a value or identifier", valNode.line, valNode.lineContent); break;
}
groundAddValueToInstruction(&gi, gv);
} else if (child.nodeType == SolNodeType::Identifier) {
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(valNode.outputId)));
} else {
Error::syntaxError("Struct member must be assigned a value or identifier", valNode.line, valNode.lineContent);
}
codeBlock.code.push_back(gi);
}
if (child.nodeType == SolNodeType::FunctionDef) {
auto fnBlock = child.generateCode();
for (const auto& code : fnBlock) {
codeBlock.code.insert(codeBlock.code.end(), code.code.begin(), code.code.end());
}
}
}
codeBlock.code.push_back(groundCreateInstruction(ENDSTRUCT));
code.push_back(codeBlock);
break;
}
default: {}
}
return code;
@@ -849,7 +894,7 @@ namespace Solstice {
if (in == "/") {
return SolNodeType::Divide;
}
if (in == "=") {
if (in == "=" || in == ":") {
return SolNodeType::Set;
}
if (in == "==") {
@@ -888,6 +933,12 @@ namespace Solstice {
if (in == "ground") {
return SolNodeType::InlineGround;
}
if (in == "struct") {
return SolNodeType::Struct;
}
if (in == "new") {
return SolNodeType::New;
}
if (in == "{") {
return SolNodeType::CodeBlockStart;
}
@@ -1437,7 +1488,6 @@ namespace Solstice {
SolNode groundNode(SolNodeType::InlineGround);
consume(); // some funny token
consume(); // {
consume(); // new line token
while (auto tokenopt = consume()) {
if (tokenopt.value().value == "}") {
break;
@@ -1447,6 +1497,121 @@ namespace Solstice {
rootNode.addNode(groundNode);
break;
}
case SolNodeType::Struct: {
SolNode structNode(SolNodeType::Struct);
structNode.line = tokenObj.line;
structNode.lineContent = tokenObj.lineContent;
auto nameopt = consume();
if (nameopt) {
structNode.outputId = nameopt.value().value;
}
while (peek() && peek().value().value == "\n") {
consume();
}
auto openBrace = consume();
if (!openBrace || openBrace.value().value != "{") {
Error::syntaxError("Expected '{' after struct name", tokenObj.line, tokenObj.lineContent);
}
std::vector<Token> tokens;
int count = 1;
while (auto tokenopt = consume()) {
if (tokenopt.value().value == "{") {
count++;
}
if (tokenopt.value().value == "}") {
count--;
}
if (count < 1) {
break;
}
tokens.push_back(tokenopt.value());
}
if (count != 0) {
Error::syntaxError("Unclosed struct body", tokenObj.line, tokenObj.lineContent);
}
for (size_t i = 0; i < tokens.size(); i++) {
Token token = tokens[i];
if (token.value == "\n") {
continue;
}
if (getNodeType(token.value) == SolNodeType::Identifier) {
if (i + 2 >= tokens.size()) {
Error::syntaxError("Expecting a value after the identifier", token.line, token.lineContent);
continue;
}
if (getNodeType(tokens[i + 1].value) != SolNodeType::Set) {
Error::syntaxError("Expected a set keyword ('=' or ':')", token.line, token.lineContent);
continue;
}
if (getNodeType(tokens[i + 2].value) != SolNodeType::Identifier &&
getNodeType(tokens[i + 2].value) != SolNodeType::Value) {
Error::syntaxError("Expected a value or identifier for default value", token.line, token.lineContent);
continue;
}
SolNode idNode(SolNodeType::Identifier);
idNode.outputId = token.value;
idNode.line = token.line;
idNode.lineContent = token.lineContent;
SolNode valueNode = Parser({tokens[i + 2]}).parse().children[0];
idNode.addNode(valueNode);
structNode.addNode(idNode);
i += 2;
continue;
}
else if (getNodeType(token.value) == SolNodeType::FunctionDef) {
std::vector<Token> functionTokens;
functionTokens.push_back(token);
int funcCount = 0;
i++;
while (i < tokens.size()) {
functionTokens.push_back(tokens[i]);
if (tokens[i].value == "{") {
funcCount++;
}
if (tokens[i].value == "}") {
funcCount--;
if (funcCount == 0) {
break;
}
}
i++;
}
if (funcCount != 0) {
Error::syntaxError("Unclosed function in struct", token.line, token.lineContent);
}
SolNode functionNode = Parser(functionTokens).parse().children[0];
structNode.addNode(functionNode);
} else {
Error::syntaxError("Structs only support set statements and function definition", token.line, token.lineContent);
}
}
rootNode.addNode(structNode);
break;
}
case SolNodeType::New: {
SolNode putsNode(SolNodeType::New);
putsNode.line = tokenObj.line;
putsNode.lineContent = tokenObj.lineContent;
auto typeopt = consume();
rootNode.addNode(putsNode);
break;
}
}
}
return rootNode;