From 6d5d29f05b17a383db1f1e4d352e347fef3cddf2 Mon Sep 17 00:00:00 2001 From: Maxwell Jeffress Date: Mon, 12 Jan 2026 16:18:59 +1100 Subject: [PATCH] Use inbuilt stdlib instead of hard coded functions --- Makefile | 2 +- src/parser.cpp | 144 +++++++++++++++++++--------------------- src/solstice_stdlib.cpp | 34 ++++++++++ src/solstice_stdlib.h | 3 + 4 files changed, 105 insertions(+), 78 deletions(-) create mode 100644 src/solstice_stdlib.cpp create mode 100644 src/solstice_stdlib.h diff --git a/Makefile b/Makefile index 31a1664..c8af9fb 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LDFLAGS = -lgroundvm BUILD_DIR = build SRC_DIR = src -SRCS = $(SRC_DIR)/main.cpp $(SRC_DIR)/argparser.cpp $(SRC_DIR)/lexer.cpp $(SRC_DIR)/parser.cpp $(SRC_DIR)/error.cpp +SRCS = $(SRC_DIR)/main.cpp $(SRC_DIR)/argparser.cpp $(SRC_DIR)/lexer.cpp $(SRC_DIR)/parser.cpp $(SRC_DIR)/error.cpp $(SRC_DIR)/solstice_stdlib.cpp OBJS = $(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.o, $(SRCS)) TARGET = solstice diff --git a/src/parser.cpp b/src/parser.cpp index 6cc29cf..e9e66dc 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,14 +1,23 @@ #include "parser.h" #include "error.h" +#include "lexer.h" +#include "solstice_stdlib.h" #include #include #include +#include #define parseOneToken(token) Parser({token}).parse().children[0] namespace Solstice { namespace Parser { + char* copyString(std::string s) { + char* str = (char*) malloc(s.size() + 1); + strcpy(str, s.c_str()); + return str; + } + bool isTemp(std::string id) { return id.rfind("tmp_", 0) == 0; } @@ -56,13 +65,6 @@ namespace Solstice { break; } case SolNodeType::FunctionCall: { - if (i.children[0].outputId == "input") { - if (i.children.size() > 1) { - ensure(i.children[1], "string", "input function argument"); - } - return "string"; - } - std::string funcName = i.children[0].outputId; if (variables.find(funcName) == variables.end()) { Error::syntaxError("Unknown function " + funcName, i.line, i.lineContent); @@ -205,6 +207,12 @@ namespace Solstice { const std::vector SolNode::generateCode() { std::vector code; + if (nodeType == SolNodeType::Root) { + // Compile and insert standard library + auto parsedStdlib = Parser(Lexer(getStdLib()).lex()).parse(); + parsedStdlib.nodeType = SolNodeType::None; + code = parsedStdlib.generateCode(); + } if (nodeType != SolNodeType::If && nodeType != SolNodeType::While) for (auto& child : children) { auto childCode = child.generateCode(); code.insert(code.end(), childCode.begin(), childCode.end()); @@ -214,7 +222,7 @@ namespace Solstice { outputId = "tmp_" + std::to_string(tmpIdIterator++); SolGroundCodeBlock codeBlock; GroundInstruction gi = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); switch (data.type) { case SolDataType::Int: { auto dataopt = data.getInt(); @@ -268,9 +276,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to add", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -286,9 +294,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to subtract", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -304,9 +312,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to multiply", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -322,9 +330,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to divide", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -339,9 +347,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to equal", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -356,9 +364,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to inequal", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -373,9 +381,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to greater", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -390,9 +398,9 @@ namespace Solstice { if (children.size() < 2) { Error::typingError("Need more stuff to lesser", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); @@ -417,8 +425,8 @@ namespace Solstice { strcpy(endLabelId, endLabelIdString.data()); // greater $tmp_0 $tmp_1 &cond GroundInstruction gi = groundCreateInstruction(GREATER); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, (char*) "internal_cond0")); codeBlock.code.push_back(gi); // if &cond %true @@ -428,8 +436,8 @@ namespace Solstice { codeBlock.code.push_back(gi); // equal $tmp_0 $tmp_1 &cond gi = groundCreateInstruction(EQUAL); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, (char*) "internal_cond1")); codeBlock.code.push_back(gi); // if $cond %true @@ -447,7 +455,7 @@ namespace Solstice { codeBlock.code.push_back(gi); // set &tmp_x true gi = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); groundAddValueToInstruction(&gi, groundCreateValue(BOOL, true)); codeBlock.code.push_back(gi); // jump %end @@ -460,7 +468,7 @@ namespace Solstice { codeBlock.code.push_back(gi); // set &tmp_x false gi = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); groundAddValueToInstruction(&gi, groundCreateValue(BOOL, false)); codeBlock.code.push_back(gi); // @end @@ -490,8 +498,8 @@ namespace Solstice { strcpy(endLabelId, endLabelIdString.data()); // lesser $tmp_0 $tmp_1 &cond GroundInstruction gi = groundCreateInstruction(LESSER); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, (char*) "internal_cond0")); codeBlock.code.push_back(gi); // if &cond %true @@ -501,8 +509,8 @@ namespace Solstice { codeBlock.code.push_back(gi); // equal $tmp_0 $tmp_1 &cond gi = groundCreateInstruction(EQUAL); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[1].outputId))); groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, (char*) "internal_cond1")); codeBlock.code.push_back(gi); // if $cond %true @@ -520,7 +528,7 @@ namespace Solstice { codeBlock.code.push_back(gi); // set &tmp_x true gi = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); groundAddValueToInstruction(&gi, groundCreateValue(BOOL, true)); codeBlock.code.push_back(gi); // jump %end @@ -533,7 +541,7 @@ namespace Solstice { codeBlock.code.push_back(gi); // set &tmp_x false gi = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); groundAddValueToInstruction(&gi, groundCreateValue(BOOL, false)); codeBlock.code.push_back(gi); // @end @@ -552,7 +560,7 @@ namespace Solstice { if (children.size() < 1) { Error::typingError("Need more stuff to puts", children[0].line, children[0].lineContent); } - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); codeBlock.code.push_back(gi); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); code.push_back(codeBlock); @@ -567,14 +575,14 @@ namespace Solstice { codeBlock.toBeDropped.push_back(outputId); if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); GroundInstruction gi = groundCreateInstruction(NOT); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(gi); std::string labelIdString = "if_" + std::to_string(labelIterator++); char* labelId = (char*) malloc(sizeof(char) * labelIdString.size() + 1); strcpy(labelId, labelIdString.data()); GroundInstruction gi2 = groundCreateInstruction(IF); - groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, outputId.data())); + groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, copyString(outputId))); groundAddReferenceToInstruction(&gi2, groundCreateReference(LINEREF, labelId)); codeBlock.code.push_back(gi2); code.push_back(codeBlock); @@ -613,11 +621,11 @@ namespace Solstice { checkBlock.toBeDropped.push_back(outputId); if (isTemp(children[0].outputId)) checkBlock.toBeDropped.push_back(children[0].outputId); GroundInstruction gi = groundCreateInstruction(NOT); - groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, copyString(outputId))); checkBlock.code.push_back(gi); GroundInstruction gi2 = groundCreateInstruction(IF); - groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, outputId.data())); + groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, copyString(outputId))); groundAddReferenceToInstruction(&gi2, groundCreateReference(LINEREF, endLabelId)); checkBlock.code.push_back(gi2); code.push_back(checkBlock); @@ -649,8 +657,8 @@ namespace Solstice { exists(children[1]); SolGroundCodeBlock codeBlock; GroundInstruction setInstruction = groundCreateInstruction(SET); - groundAddReferenceToInstruction(&setInstruction, groundCreateReference(DIRREF, children[0].outputId.data())); - groundAddReferenceToInstruction(&setInstruction, groundCreateReference(VALREF, children[1].outputId.data())); + groundAddReferenceToInstruction(&setInstruction, groundCreateReference(DIRREF, copyString(children[0].outputId))); + groundAddReferenceToInstruction(&setInstruction, groundCreateReference(VALREF, copyString(children[1].outputId))); codeBlock.code.push_back(setInstruction); if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); code.push_back(codeBlock); @@ -660,34 +668,16 @@ namespace Solstice { } case SolNodeType::FunctionCall: { checkNodeReturnType(*this); - // Take care of in built functions - // This will be removed when inline ground is added - if (children[0].outputId == "input") { - ensure(children[1], "string", "input function argument"); - SolGroundCodeBlock inputCodeBlock; - if (children.size() > 1) { - GroundInstruction printInstruction = groundCreateInstruction(PRINT); - groundAddReferenceToInstruction(&printInstruction, groundCreateReference(VALREF, children[1].outputId.data())); - inputCodeBlock.code.push_back(printInstruction); - if (isTemp(children[1].outputId)) inputCodeBlock.toBeDropped.push_back(children[1].outputId); - } - GroundInstruction inputInstruction = groundCreateInstruction(INPUT); - outputId = "tmp_" + std::to_string(tmpIdIterator++); - groundAddReferenceToInstruction(&inputInstruction, groundCreateReference(DIRREF, outputId.data())); - inputCodeBlock.code.push_back(inputInstruction); - code.push_back(inputCodeBlock); - break; - } exists(children[0]); std::string fnToCall = children[0].outputId; outputId = "tmp_" + std::to_string(tmpIdIterator++); SolGroundCodeBlock codeBlock; GroundInstruction callInstruction = groundCreateInstruction(CALL); - groundAddReferenceToInstruction(&callInstruction, groundCreateReference(FNREF, children[0].outputId.data())); + groundAddReferenceToInstruction(&callInstruction, groundCreateReference(FNREF, copyString(children[0].outputId))); for (int i = 1; i < children.size(); i++) { - groundAddReferenceToInstruction(&callInstruction, groundCreateReference(VALREF, children[i].outputId.data())); + groundAddReferenceToInstruction(&callInstruction, groundCreateReference(VALREF, copyString(children[i].outputId))); } - groundAddReferenceToInstruction(&callInstruction, groundCreateReference(DIRREF, outputId.data())); + groundAddReferenceToInstruction(&callInstruction, groundCreateReference(DIRREF, copyString(outputId))); codeBlock.code.push_back(callInstruction); code.push_back(codeBlock); break; @@ -699,7 +689,7 @@ namespace Solstice { } SolGroundCodeBlock codeBlock; GroundInstruction returnInstruction = groundCreateInstruction(RETURN); - groundAddReferenceToInstruction(&returnInstruction, groundCreateReference(VALREF, children[0].outputId.data())); + groundAddReferenceToInstruction(&returnInstruction, groundCreateReference(VALREF, copyString(children[0].outputId))); codeBlock.code.push_back(returnInstruction); code.push_back(codeBlock); break; @@ -725,8 +715,8 @@ namespace Solstice { currentFunctionRetType = function.returnType; for (auto& pair : function.parameters) { - groundAddReferenceToInstruction(&inst, groundCreateReference(TYPEREF, pair.second.data())); - groundAddReferenceToInstruction(&inst, groundCreateReference(DIRREF, pair.first.data())); + groundAddReferenceToInstruction(&inst, groundCreateReference(TYPEREF, copyString(pair.second))); + groundAddReferenceToInstruction(&inst, groundCreateReference(DIRREF, copyString(pair.first))); variables[pair.first] = pair.second; // Correctly map Name -> Type } diff --git a/src/solstice_stdlib.cpp b/src/solstice_stdlib.cpp new file mode 100644 index 0000000..846aa57 --- /dev/null +++ b/src/solstice_stdlib.cpp @@ -0,0 +1,34 @@ +#include + +std::string getStdLib() { + return R"( + +// Solstice stdlib + +def input(string msg) string { + retval = "" + ground { + print $msg + input &retval + } + return retval +} + +def print(string msg) string { + ground { + print $msg + } + return msg +} + +def println(string msg) string { + ground { + println $msg + } + return msg +} + +// End Solstice stdlib + + )"; +} diff --git a/src/solstice_stdlib.h b/src/solstice_stdlib.h new file mode 100644 index 0000000..43361c4 --- /dev/null +++ b/src/solstice_stdlib.h @@ -0,0 +1,3 @@ +#include + +std::string getStdLib();