Fixes, rebrand

This commit is contained in:
2025-12-20 15:09:09 +11:00
parent c04e631180
commit 72ec9c1fb6
11 changed files with 132 additions and 126 deletions

2
.gitignore vendored
View File

@@ -1 +1 @@
hg
solstice

View File

@@ -1,22 +1,20 @@
# High Ground
# Solstice
High Ground is a programming language based on Ground.
It is the reference language designed to teach you how to build your own Ground-based language.
Solstice is a programming language based on Ground.
## Compiling
First, ensure CGround is installed on your system with `sudo make install`. Then, compile with
```
g++ src/main.cpp -o hg -lgroundvm
g++ src/main.cpp -o solstice -lgroundvm
```
## Usage
High Ground files use the `.hg` extension. Run files as you would with any other interpreted language.
Solstice files use the `.sols` extension. Run files as you would with any other interpreted language.
## Using High Ground
## Using Solstice
### Types
@@ -80,7 +78,7 @@ if password == "password123" {
puts "Your password is insecure."
}
if password = "dingus" {
if password == "dingus" {
puts "Cool password!"
}
```

View File

@@ -12,70 +12,70 @@
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
namespace HighGround {
namespace Solstice {
int tmpIdIterator = 0;
int labelIterator = 0;
namespace Parser {
enum class HGNodeType {
enum class SolNodeType {
Add, Subtract, Equal, Inequal, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, Puts
};
enum class HGDataType {
enum class SolDataType {
Int, String, Double, Bool, Char, None
};
class HGNode;
class SolNode;
class HGGroundCodeBlock {
class SolGroundCodeBlock {
public:
std::vector<GroundInstruction> code;
HGGroundCodeBlock() = default;
SolGroundCodeBlock() = default;
};
class HGData {
class SolData {
typedef std::variant<int64_t, std::string, double, bool, char> varData;
varData data;
public:
HGDataType type = HGDataType::Int;
HGData() = default;
HGData(int64_t in) : data(in), type(HGDataType::Int) {}
HGData(double in) : data(in), type(HGDataType::Double) {}
HGData(std::string in) : data(in), type(HGDataType::String) {}
HGData(char in) : data(in), type(HGDataType::Char) {}
HGData(bool in) : data(in), type(HGDataType::Bool) {}
SolDataType type = SolDataType::Int;
SolData() = default;
SolData(int64_t in) : data(in), type(SolDataType::Int) {}
SolData(double in) : data(in), type(SolDataType::Double) {}
SolData(std::string in) : data(in), type(SolDataType::String) {}
SolData(char in) : data(in), type(SolDataType::Char) {}
SolData(bool in) : data(in), type(SolDataType::Bool) {}
std::optional<int64_t> getInt() {
if (type == HGDataType::Int) {
if (type == SolDataType::Int) {
return std::get<int64_t>(data);
} else {
return {};
}
}
std::optional<double> getDouble() {
if (type == HGDataType::Double) {
if (type == SolDataType::Double) {
return std::get<double>(data);
} else {
return {};
}
}
std::optional<std::string> getString() {
if (type == HGDataType::String) {
if (type == SolDataType::String) {
return std::get<std::string>(data);
} else {
return {};
}
}
std::optional<char> getChar() {
if (type == HGDataType::Char) {
if (type == SolDataType::Char) {
return std::get<char>(data);
} else {
return {};
}
}
std::optional<bool> getBool() {
if (type == HGDataType::Bool) {
if (type == SolDataType::Bool) {
return std::get<bool>(data);
} else {
return {};
@@ -83,63 +83,63 @@ namespace HighGround {
}
};
class HGNode {
HGNodeType nodeType = HGNodeType::None;
HGData data;
class SolNode {
SolNodeType nodeType = SolNodeType::None;
SolData data;
public:
std::vector<HGNode> children;
std::vector<SolNode> children;
std::string outputId;
HGNode(HGNodeType nodeType) : nodeType(nodeType) {}
HGNode(HGNodeType nodeType, HGData data) : nodeType(nodeType), data(data) {}
HGNode() = default;
void addNode(HGNode in) {
SolNode(SolNodeType nodeType) : nodeType(nodeType) {}
SolNode(SolNodeType nodeType, SolData data) : nodeType(nodeType), data(data) {}
SolNode() = default;
void addNode(SolNode in) {
children.push_back(in);
}
void setValue(HGData in) {
void setValue(SolData in) {
data = in;
}
const std::vector<HGGroundCodeBlock> generateCode() {
std::vector<HGGroundCodeBlock> code;
if (nodeType != HGNodeType::If) for (auto& child : children) {
const std::vector<SolGroundCodeBlock> generateCode() {
std::vector<SolGroundCodeBlock> code;
if (nodeType != SolNodeType::If && nodeType != SolNodeType::While) for (auto& child : children) {
auto childCode = child.generateCode();
code.insert(code.end(), childCode.begin(), childCode.end());
}
switch (nodeType) {
case HGNodeType::Value: {
case SolNodeType::Value: {
outputId = "tmp_" + std::to_string(tmpIdIterator++);
HGGroundCodeBlock codeBlock;
SolGroundCodeBlock codeBlock;
GroundInstruction gi = groundCreateInstruction(SET);
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
switch (data.type) {
case HGDataType::Int: {
case SolDataType::Int: {
auto dataopt = data.getInt();
if (dataopt) {
groundAddValueToInstruction(&gi, groundCreateValue(INT, dataopt.value()));
}
break;
}
case HGDataType::Double: {
case SolDataType::Double: {
auto dataopt = data.getDouble();
if (dataopt) {
groundAddValueToInstruction(&gi, groundCreateValue(DOUBLE, dataopt.value()));
}
break;
}
case HGDataType::String: {
case SolDataType::String: {
auto dataopt = data.getString();
if (dataopt) {
groundAddValueToInstruction(&gi, groundCreateValue(STRING, dataopt.value().c_str()));
}
break;
}
case HGDataType::Char: {
case SolDataType::Char: {
auto dataopt = data.getChar();
if (dataopt) {
groundAddValueToInstruction(&gi, groundCreateValue(CHAR, dataopt.value()));
}
break;
}
case HGDataType::Bool: {
case SolDataType::Bool: {
auto dataopt = data.getBool();
if (dataopt) {
groundAddValueToInstruction(&gi, groundCreateValue(BOOL, dataopt.value()));
@@ -151,8 +151,8 @@ namespace HighGround {
code.push_back(codeBlock);
break;
}
case HGNodeType::Add: {
HGGroundCodeBlock codeBlock;
case SolNodeType::Add: {
SolGroundCodeBlock codeBlock;
outputId = "tmp_" + std::to_string(tmpIdIterator++);
GroundInstruction gi = groundCreateInstruction(ADD);
if (children.size() < 2) {
@@ -165,8 +165,8 @@ namespace HighGround {
code.push_back(codeBlock);
break;
}
case HGNodeType::Equal: {
HGGroundCodeBlock codeBlock;
case SolNodeType::Equal: {
SolGroundCodeBlock codeBlock;
outputId = "tmp_" + std::to_string(tmpIdIterator++);
GroundInstruction gi = groundCreateInstruction(EQUAL);
if (children.size() < 2) {
@@ -179,8 +179,8 @@ namespace HighGround {
code.push_back(codeBlock);
break;
}
case HGNodeType::Inequal: {
HGGroundCodeBlock codeBlock;
case SolNodeType::Inequal: {
SolGroundCodeBlock codeBlock;
outputId = "tmp_" + std::to_string(tmpIdIterator++);
GroundInstruction gi = groundCreateInstruction(INEQUAL);
if (children.size() < 2) {
@@ -193,8 +193,8 @@ namespace HighGround {
code.push_back(codeBlock);
break;
}
case HGNodeType::Puts: {
HGGroundCodeBlock codeBlock;
case SolNodeType::Puts: {
SolGroundCodeBlock codeBlock;
GroundInstruction gi = groundCreateInstruction(PRINTLN);
if (children.size() < 1) {
std::cout << "Need more stuff to puts\n";
@@ -204,11 +204,11 @@ namespace HighGround {
code.push_back(codeBlock);
break;
}
case HGNodeType::If: {
case SolNodeType::If: {
auto conditionCode = children[0].generateCode();
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
outputId = "tmp_" + std::to_string(tmpIdIterator++);
HGGroundCodeBlock codeBlock;
SolGroundCodeBlock codeBlock;
GroundInstruction gi = groundCreateInstruction(NOT);
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
@@ -232,48 +232,55 @@ namespace HighGround {
code.push_back(codeBlock);
break;
}
case HGNodeType::While: {
HGGroundCodeBlock codeBlock;
case SolNodeType::While: {
SolGroundCodeBlock startLabelBlock;
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
char* startLabelId = (char*) malloc(sizeof(char) * (startLabelIdString.size() + 1));
strcpy(startLabelId, startLabelIdString.data());
char* endLabelId = (char*) malloc(sizeof(char) * (endLabelIdString.size() + 1));
strcpy(endLabelId, endLabelIdString.data());
GroundInstruction startLabel = groundCreateInstruction(CREATELABEL);
groundAddReferenceToInstruction(&startLabel, groundCreateReference(LABEL, startLabelId));
codeBlock.code.push_back(startLabel);
startLabelBlock.code.push_back(startLabel);
code.push_back(startLabelBlock);
auto conditionCode = children[0].generateCode();
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
SolGroundCodeBlock checkBlock;
outputId = "tmp_" + std::to_string(tmpIdIterator++);
GroundInstruction gi = groundCreateInstruction(NOT);
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
codeBlock.code.push_back(gi);
checkBlock.code.push_back(gi);
GroundInstruction gi2 = groundCreateInstruction(IF);
groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, outputId.data()));
groundAddReferenceToInstruction(&gi2, groundCreateReference(LINEREF, endLabelId));
codeBlock.code.push_back(gi2);
code.push_back(codeBlock);
checkBlock.code.push_back(gi2);
code.push_back(checkBlock);
for (size_t i = 1; i < children.size(); i++) {
auto childCode = children[i].generateCode();
code.insert(code.end(), childCode.begin(), childCode.end());
}
codeBlock.code.clear();
SolGroundCodeBlock endBlock;
GroundInstruction gi3 = groundCreateInstruction(JUMP);
groundAddReferenceToInstruction(&gi3, groundCreateReference(LINEREF, startLabelId));
codeBlock.code.push_back(gi3);
endBlock.code.push_back(gi3);
GroundInstruction gi4 = groundCreateInstruction(CREATELABEL);
groundAddReferenceToInstruction(&gi4, groundCreateReference(LABEL, endLabelId));
codeBlock.code.push_back(gi4);
code.push_back(codeBlock);
endBlock.code.push_back(gi4);
code.push_back(endBlock);
break;
}
case HGNodeType::Identifier: {
case SolNodeType::Identifier: {
break;
}
case HGNodeType::Set: {
HGGroundCodeBlock codeBlock;
case SolNodeType::Set: {
SolGroundCodeBlock codeBlock;
GroundInstruction setInstruction = groundCreateInstruction(SET);
groundAddReferenceToInstruction(&setInstruction, groundCreateReference(DIRREF, children[0].outputId.data()));
groundAddReferenceToInstruction(&setInstruction, groundCreateReference(VALREF, children[1].outputId.data()));
@@ -349,97 +356,97 @@ namespace HighGround {
return false;
}
HGDataType getDataType(std::string in) {
SolDataType getDataType(std::string in) {
if (isInt(in)) {
return HGDataType::Int;
return SolDataType::Int;
}
if (isDouble(in)) {
return HGDataType::Double;
return SolDataType::Double;
}
if (isString(in)) {
return HGDataType::String;
return SolDataType::String;
}
if (isChar(in)) {
return HGDataType::Char;
return SolDataType::Char;
}
if (isBool(in)) {
return HGDataType::Bool;
return SolDataType::Bool;
}
return HGDataType::None;
return SolDataType::None;
}
HGNodeType getNodeType(std::string in) {
if (getDataType(in) != HGDataType::None) {
return HGNodeType::Value;
SolNodeType getNodeType(std::string in) {
if (getDataType(in) != SolDataType::None) {
return SolNodeType::Value;
}
if (in == "+") {
return HGNodeType::Add;
return SolNodeType::Add;
}
if (in == "=") {
return HGNodeType::Set;
return SolNodeType::Set;
}
if (in == "==") {
return HGNodeType::Equal;
return SolNodeType::Equal;
}
if (in == "!=") {
return HGNodeType::Inequal;
return SolNodeType::Inequal;
}
if (in == "puts") {
return HGNodeType::Puts;
return SolNodeType::Puts;
}
if (in == "if") {
return HGNodeType::If;
return SolNodeType::If;
}
if (in == "while") {
return HGNodeType::While;
return SolNodeType::While;
}
if (in == "{") {
return HGNodeType::CodeBlockStart;
return SolNodeType::CodeBlockStart;
}
if (in == "}") {
return HGNodeType::CodeBlockEnd;
return SolNodeType::CodeBlockEnd;
}
return HGNodeType::Identifier;
return SolNodeType::Identifier;
}
public:
Parser(std::vector<std::string> in) : tokensToParse(in) {}
HGNode parse() {
SolNode parse() {
current = 0;
size = tokensToParse.size();
HGNode rootNode(HGNodeType::Root);
SolNode rootNode(SolNodeType::Root);
while (auto tokenopt = consume()) {
std::string token = tokenopt.value();
switch (getNodeType(token)) {
case HGNodeType::Value: {
case SolNodeType::Value: {
switch (getDataType(token)) {
case HGDataType::Int: {
HGNode intNode(HGNodeType::Value);
case SolDataType::Int: {
SolNode intNode(SolNodeType::Value);
intNode.setValue((int64_t) std::stoll(token));
rootNode.addNode(intNode);
break;
}
case HGDataType::Double: {
HGNode doubleNode(HGNodeType::Value);
case SolDataType::Double: {
SolNode doubleNode(SolNodeType::Value);
doubleNode.setValue(std::stod(token));
rootNode.addNode(doubleNode);
break;
}
case HGDataType::String: {
HGNode stringNode(HGNodeType::Value);
case SolDataType::String: {
SolNode stringNode(SolNodeType::Value);
stringNode.setValue(token.substr(1, token.size() - 2));
rootNode.addNode(stringNode);
break;
}
case HGDataType::Char: {
HGNode charNode(HGNodeType::Value);
case SolDataType::Char: {
SolNode charNode(SolNodeType::Value);
charNode.setValue(token[1]);
rootNode.addNode(charNode);
break;
}
case HGDataType::Bool: {
HGNode boolNode(HGNodeType::Value);
case SolDataType::Bool: {
SolNode boolNode(SolNodeType::Value);
boolNode.setValue(token == "true");
rootNode.addNode(boolNode);
break;
@@ -447,8 +454,8 @@ namespace HighGround {
}
break;
}
case HGNodeType::Add: {
HGNode addNode(HGNodeType::Add);
case SolNodeType::Add: {
SolNode addNode(SolNodeType::Add);
addNode.addNode(rootNode.children.back());
rootNode.children.pop_back();
auto tokenopt = consume();
@@ -461,8 +468,8 @@ namespace HighGround {
rootNode.addNode(addNode);
break;
}
case HGNodeType::Equal: {
HGNode equalNode(HGNodeType::Equal);
case SolNodeType::Equal: {
SolNode equalNode(SolNodeType::Equal);
equalNode.addNode(rootNode.children.back());
rootNode.children.pop_back();
auto tokenopt = consume();
@@ -475,8 +482,8 @@ namespace HighGround {
rootNode.addNode(equalNode);
break;
}
case HGNodeType::Inequal: {
HGNode inequalNode(HGNodeType::Inequal);
case SolNodeType::Inequal: {
SolNode inequalNode(SolNodeType::Inequal);
inequalNode.addNode(rootNode.children.back());
rootNode.children.pop_back();
auto tokenopt = consume();
@@ -489,8 +496,8 @@ namespace HighGround {
rootNode.addNode(inequalNode);
break;
}
case HGNodeType::Puts: {
HGNode putsNode(HGNodeType::Puts);
case SolNodeType::Puts: {
SolNode putsNode(SolNodeType::Puts);
std::vector<std::string> tokens;
while (auto tokenopt = consume()) {
if (tokenopt.value() == "\n") {
@@ -505,8 +512,8 @@ namespace HighGround {
rootNode.addNode(putsNode);
break;
}
case HGNodeType::If: {
HGNode ifNode(HGNodeType::If);
case SolNodeType::If: {
SolNode ifNode(SolNodeType::If);
std::vector<std::string> tokens;
while (auto tokenopt = consume()) {
if (tokenopt.value() == "\n") {
@@ -547,8 +554,8 @@ namespace HighGround {
rootNode.addNode(ifNode);
break;
}
case HGNodeType::While: {
HGNode whileNode(HGNodeType::While);
case SolNodeType::While: {
SolNode whileNode(SolNodeType::While);
std::vector<std::string> tokens;
while (auto tokenopt = consume()) {
if (tokenopt.value() == "\n") {
@@ -589,8 +596,8 @@ namespace HighGround {
rootNode.addNode(whileNode);
break;
}
case HGNodeType::CodeBlockStart: {
HGNode codeBlockNode(HGNodeType::CodeBlock);
case SolNodeType::CodeBlockStart: {
SolNode codeBlockNode(SolNodeType::CodeBlock);
size_t brackets = 1;
std::vector<std::string> tokens;
while (auto tokenopt = consume()) {
@@ -609,14 +616,14 @@ namespace HighGround {
rootNode.addNode(codeBlockNode);
break;
}
case HGNodeType::Identifier: {
HGNode idNode(HGNodeType::Identifier);
case SolNodeType::Identifier: {
SolNode idNode(SolNodeType::Identifier);
idNode.outputId = token;
rootNode.addNode(idNode);
break;
}
case HGNodeType::Set: {
HGNode setNode(HGNodeType::Set);
case SolNodeType::Set: {
SolNode setNode(SolNodeType::Set);
setNode.addNode(rootNode.children.back());
rootNode.children.pop_back();
std::vector<std::string> tokens;
@@ -637,7 +644,7 @@ namespace HighGround {
}
};
GroundProgram assembleProgram(HGNode& rootNode) {
GroundProgram assembleProgram(SolNode& rootNode) {
GroundProgram gp = groundCreateProgram();
auto code = rootNode.generateCode();
for (int i = 0; i < code.size(); i++) {
@@ -735,6 +742,7 @@ namespace HighGround {
break;
}
// tokens which may be followed by an equals sign
case '!':
case '*':
case '/':
case '=':
@@ -790,7 +798,7 @@ namespace HighGround {
};
} // namespace HighGround
} // namespace HigSolround
int main(int argc, char** argv) {
@@ -801,8 +809,8 @@ int main(int argc, char** argv) {
std::ifstream file(argv[1]);
std::ostringstream ss;
ss << file.rdbuf();
auto lexed = HighGround::Lexer(ss.str()).lex();
auto parsed = HighGround::Parser::Parser(lexed).parse();
GroundProgram program = HighGround::Parser::assembleProgram(parsed);
auto lexed = Solstice::Lexer(ss.str()).lex();
auto parsed = Solstice::Parser::Parser(lexed).parse();
GroundProgram program = Solstice::Parser::assembleProgram(parsed);
groundRunProgram(&program);
}