This commit is contained in:
2025-08-10 15:42:52 +10:00
parent 2e388c6e68
commit 3f2482d7ea
5 changed files with 62 additions and 10 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
ground ground
Bobfile

View File

@@ -1,4 +1,5 @@
compiler "g++"; compiler "g++";
binary "ground"; binary "ground";
source "src/main.cpp"; source "src/main.cpp";
flag "O3";
compile; compile;

View File

@@ -32,7 +32,13 @@ Reference a line (a line reference) with a percent symbol before a line number:
jump %10 jump %10
``` ```
(WORK IN PROGRESS) Alternatively, set a label and jump to that (setting labels will be discussed below): Alternatively, set a label:
```
@myLabel
```
and jump to that (setting labels will be discussed below):
``` ```
jump %myLabel jump %myLabel

View File

@@ -72,7 +72,7 @@ enum class Instructions {
See also parser function See also parser function
*/ */
enum class Types { enum class Types {
Int, Double, String, Char, Bool, Value, Direct, Line, ListRef Int, Double, String, Char, Bool, Value, Direct, Line, ListRef, Label
}; };
/* /*
@@ -146,6 +146,12 @@ map<string, Literal> variables;
*/ */
map<string, List> lists; map<string, List> lists;
/*
labels map
Contains all labels made in the program, for ease of jumping around the code.
*/
map<string, int> labels;
/* /*
ValueRef struct ValueRef struct
If the program being executed makes a value reference, it is stored in a ValueRef If the program being executed makes a value reference, it is stored in a ValueRef
@@ -186,6 +192,8 @@ struct Direct {
*/ */
struct Line { struct Line {
int lineNum; int lineNum;
bool isLabel = false;
string label;
}; };
/* /*
@@ -282,6 +290,11 @@ bool isLine(string in) {
else return false; else return false;
} }
bool isLabel(string in) {
if (in.size() >= 1 && in[0] == '@') return true;
else return false;
}
bool isListRef(string in) { bool isListRef(string in) {
if (in.size() >= 1 && in[0] == '*') return true; if (in.size() >= 1 && in[0] == '*') return true;
else return false; else return false;
@@ -301,6 +314,7 @@ Types getType(string in) {
if (isValue(in)) return Types::Value; if (isValue(in)) return Types::Value;
if (isDirect(in)) return Types::Direct; if (isDirect(in)) return Types::Direct;
if (isLine(in)) return Types::Line; if (isLine(in)) return Types::Line;
if (isLabel(in)) return Types::Label;
if (isListRef(in)) return Types::ListRef; if (isListRef(in)) return Types::ListRef;
error("Could not determine type of \"" + in + "\""); error("Could not determine type of \"" + in + "\"");
return Types::Int; return Types::Int;
@@ -315,7 +329,7 @@ Types getType(string in) {
void exec(vector<Instruction> in) { void exec(vector<Instruction> in) {
for (int i = 0; i < in.size(); i++) { for (int i = 0; i < in.size(); i++) {
Instruction l = in[i]; Instruction l = in[i];
// Pre process value references // Pre process value references and labels
for (int j = 0; j < l.args.size(); j++) { for (int j = 0; j < l.args.size(); j++) {
if (holds_alternative<ValueRef>(l.args[j])) { if (holds_alternative<ValueRef>(l.args[j])) {
if (variables.find(get<ValueRef>(l.args[j]).varName) != variables.end()) { if (variables.find(get<ValueRef>(l.args[j]).varName) != variables.end()) {
@@ -323,6 +337,17 @@ void exec(vector<Instruction> in) {
} else { } else {
error("Could not find variable " + get<ValueRef>(l.args[j]).varName); error("Could not find variable " + get<ValueRef>(l.args[j]).varName);
} }
} else if (holds_alternative<Line>(l.args[j])) {
Line ln = get<Line>(l.args[j]);
if (ln.isLabel) {
if (labels.find(ln.label) != labels.end()) {
Line newLine;
newLine.lineNum = labels[ln.label];
l.args[j] = newLine;
} else {
error("Could not find label " + ln.label);
}
}
} }
} }
switch (l.inst) { switch (l.inst) {
@@ -1124,16 +1149,25 @@ vector<vector<string>> lexer(string in) {
vector<Instruction> parser(vector<vector<string>> in) { vector<Instruction> parser(vector<vector<string>> in) {
vector<Instruction> out; vector<Instruction> out;
int lineNum = 1;
for (vector<string> lineTokens : in) { for (vector<string> lineTokens : in) {
if (lineTokens.empty()) continue; lineNum ++;
Instruction newInst; Instruction newInst;
if (lineTokens.empty()) {
out.push_back(newInst);
continue;
};
bool firstInst = true; bool firstInst = true;
for (string i : lineTokens) { for (string i : lineTokens) {
if (firstInst) { if (firstInst) {
firstInst = false; firstInst = false;
if (i == "stdin") newInst.inst = Instructions::Stdin; if (isLabel(i)) {
labels[i.substr(1)] = lineNum;
out.push_back(newInst);
continue;
}
else if (i == "stdin") newInst.inst = Instructions::Stdin;
else if (i == "stdout") newInst.inst = Instructions::Stdout; else if (i == "stdout") newInst.inst = Instructions::Stdout;
else if (i == "stdlnout") newInst.inst = Instructions::Stdlnout; else if (i == "stdlnout") newInst.inst = Instructions::Stdlnout;
else if (i == "jump") newInst.inst = Instructions::Jump; else if (i == "jump") newInst.inst = Instructions::Jump;
@@ -1170,10 +1204,18 @@ vector<Instruction> parser(vector<vector<string>> in) {
newInst.args.push_back(newDirect); newInst.args.push_back(newDirect);
} }
break; break;
case Types::Label:
error("Label should be defined as first token");
break;
case Types::Line: case Types::Line:
{ {
Line newLine; Line newLine;
newLine.lineNum = stoi(i.substr(1)); if (isInt(i.substr(1))) newLine.lineNum = stoi(i.substr(1));
else {
newLine.isLabel = true;
newLine.label = i.substr(1);
newLine.lineNum = 0;
}
newInst.args.push_back(newLine); newInst.args.push_back(newLine);
} }
break; break;

View File

@@ -1,7 +1,9 @@
@begin
stdout "Do you like cheese? " stdout "Do you like cheese? "
stdin &userin stdin &userin
equal $userin "yes" &condition equal $userin "yes" &condition
if $condition %7 if $condition %end
stdlnout "That is sad" stdlnout "That is sad"
jump %1 jump %begin
@end
stdlnout "Awesome! I do too!" stdlnout "Awesome! I do too!"