Use inbuilt stdlib instead of hard coded functions

This commit is contained in:
2026-01-12 16:18:59 +11:00
parent 48c130351a
commit 6d5d29f05b
4 changed files with 105 additions and 78 deletions

View File

@@ -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

View File

@@ -1,14 +1,23 @@
#include "parser.h"
#include "error.h"
#include "lexer.h"
#include "solstice_stdlib.h"
#include <groundvm.h>
#include <cstring>
#include <string>
#include <cstdlib>
#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<SolGroundCodeBlock> SolNode::generateCode() {
std::vector<SolGroundCodeBlock> 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
}

34
src/solstice_stdlib.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include <string>
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
)";
}

3
src/solstice_stdlib.h Normal file
View File

@@ -0,0 +1,3 @@
#include <string>
std::string getStdLib();