forked from ground/ground
More reliable scoping
This commit is contained in:
0
docs/writing-a-program
Normal file
0
docs/writing-a-program
Normal file
25
docs/writing-a-program.md
Normal file
25
docs/writing-a-program.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Writing programs with Ground
|
||||
|
||||
Ground is a very easy language to learn. In this guide, you will learn how to write a simple calculator in Ground, as well as best practices (which there aren't many of, since Ground is so simple).
|
||||
|
||||
Note: This assumes you've read and understand the syntax.md document in this folder.
|
||||
|
||||
### Let's start!
|
||||
|
||||
Open a new file with the `.grnd` extension. Should look something like this:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
(Real empty in that file.)
|
||||
|
||||
Let's add some code! Create a label for the start, since we'll loop back once we've calculated, and ask for the user's input:
|
||||
|
||||
```
|
||||
@start
|
||||
stdout "Calculation: "
|
||||
stdin &calc
|
||||
```
|
||||
|
||||
At the calc variable, we have whatever the user typed in. This should look something like `9+10`, `1 / 3` or who knows what else. But first we should organise this data. Let's create a loop to iterate through this input, and a counter to keep moving forward:
|
77
src/main.cpp
77
src/main.cpp
@@ -39,7 +39,6 @@
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <filesystem>
|
||||
@@ -269,12 +268,6 @@ map<string, Function> functions;
|
||||
*/
|
||||
vector<Literal> fnArgs;
|
||||
|
||||
/*
|
||||
localArgStack stack
|
||||
This keeps track of all the local arguments in functions that are being called.
|
||||
*/
|
||||
stack<vector<Direct>> localArgStack;
|
||||
|
||||
/*
|
||||
error function
|
||||
Takes a string (which is a debug message) and prints it to the console, letting the
|
||||
@@ -563,9 +556,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = varContents;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -639,9 +629,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
if (lists[listref.listName].val.size() > ref) {
|
||||
bool existed = variables.count(var.varName) > 0;
|
||||
variables[var.varName] = lists[listref.listName].val[ref];
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(var);
|
||||
}
|
||||
} else {
|
||||
error("Index " + to_string(ref) + " out of range of list " + listref.listName);
|
||||
}
|
||||
@@ -695,9 +682,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
newLit.val = instr[ref];
|
||||
bool existed = variables.count(var.varName) > 0;
|
||||
variables[var.varName] = newLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(var);
|
||||
}
|
||||
} else {
|
||||
error("Index " + to_string(ref) + " out of range of string " + instr);
|
||||
}
|
||||
@@ -809,9 +793,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
newLit.val = int(lists[ref.listName].val.size());
|
||||
bool existed = variables.count(var.varName) > 0;
|
||||
variables[var.varName] = newLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(var);
|
||||
}
|
||||
} else {
|
||||
error("Couldn't find the list " + ref.listName);
|
||||
}
|
||||
@@ -850,9 +831,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
newLit.val = int(ref.size());
|
||||
bool existed = variables.count(var.varName) > 0;
|
||||
variables[var.varName] = newLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(var);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -890,9 +868,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
newLit.val = stoi(toConv);
|
||||
bool existed = variables.count(ref.varName) > 0;
|
||||
variables[ref.varName] = newLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(ref);
|
||||
}
|
||||
} else {
|
||||
error("Cannot convert the value " + toConv + " to an int");
|
||||
}
|
||||
@@ -932,9 +907,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
newLit.val = stod(toConv);
|
||||
bool existed = variables.count(ref.varName) > 0;
|
||||
variables[ref.varName] = newLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(ref);
|
||||
}
|
||||
} else {
|
||||
error("Cannot convert the value " + toConv + " to a decimal");
|
||||
}
|
||||
@@ -983,9 +955,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(ref.varName) > 0;
|
||||
variables[ref.varName] = newLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(ref);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
@@ -1006,9 +975,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
userLit.val = userIn;
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = userLit;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
} else {
|
||||
error("First argument of stdin must be a direct reference");
|
||||
}
|
||||
@@ -1069,9 +1035,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1122,9 +1085,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1175,9 +1135,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1240,9 +1197,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1299,9 +1253,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1358,9 +1309,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1394,9 +1342,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = boolean;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1453,9 +1398,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1512,9 +1454,6 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
bool existed = variables.count(varRef.varName) > 0;
|
||||
variables[varRef.varName] = final;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(varRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -1704,7 +1643,8 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
" arguments, got " + to_string(fnArgs.size()));
|
||||
}
|
||||
|
||||
localArgStack.push(vector<Direct>());
|
||||
// Create backup of variables to be restored
|
||||
map<string, Literal> scopeBackup = variables;
|
||||
|
||||
// Create function arguments with type checking
|
||||
for (int m = 0; m < functions[ref.fnName].args.size(); m++) {
|
||||
@@ -1718,27 +1658,20 @@ Literal exec(vector<Instruction> in, bool executingFunction) {
|
||||
|
||||
// Create the variable
|
||||
variables[arg.ref.varName] = fnArgs[m];
|
||||
localArgStack.top().push_back(arg.ref);
|
||||
}
|
||||
|
||||
// Call the function
|
||||
Literal retVal = exec(functions[ref.fnName].instructions, true);
|
||||
|
||||
// Remove variables that were declared in this scope
|
||||
for (Direct delref : localArgStack.top()) {
|
||||
variables.erase(delref.varName);
|
||||
}
|
||||
localArgStack.pop();
|
||||
|
||||
// Restore scope
|
||||
variables = scopeBackup;
|
||||
|
||||
// Clear function arguments for next call
|
||||
fnArgs.clear();
|
||||
|
||||
// Now, assign the return value in the current scope.
|
||||
bool existed = variables.count(returnRef.varName) > 0;
|
||||
variables[returnRef.varName] = retVal;
|
||||
if (!localArgStack.empty() && !existed) {
|
||||
localArgStack.top().push_back(returnRef);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Instructions::Use:
|
||||
|
Reference in New Issue
Block a user