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

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
solstice
build
.*_solsbuild

View File

@@ -100,6 +100,7 @@ namespace Solstice {
}
// tokens which are not followed by anything
case '\n':
case ':':
{
if (!buf.empty()) {
addToken(buf);

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;

View File

@@ -57,7 +57,7 @@ namespace Solstice {
enum class SolNodeType {
Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, EqGreater, EqLesser, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, FunctionDef, FunctionCall, Expression, BracketStart, BracketEnd, Puts, Return, InlineGround
Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, EqGreater, EqLesser, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, FunctionDef, FunctionCall, Expression, BracketStart, BracketEnd, Puts, Return, InlineGround, Struct, New
};
enum class SolDataType {

3
tests/struct.sols Normal file
View File

@@ -0,0 +1,3 @@
struct dingus {
x = 5
}