crappy loops (we segfaulting)

This commit is contained in:
Maxwell 2025-05-01 10:56:10 +10:00
parent 330a511f85
commit 2686f88d52
6 changed files with 132 additions and 40 deletions

View File

@ -1,30 +0,0 @@
{
"configurations": [
{
"type": "command",
"name": "Compile",
"program": "bob"
},
{
"type": "command",
"name": "Run",
"program": "$PROJECT_DIR$/mx",
"workingDir": "$PROJECT_DIR$",
"args": ["test.mx"]
},
{
"type": "command",
"name": "Compile and run",
"program": "fish",
"workingDir": "$PROJECT_DIR$",
"args": ["test.fish"]
},
{
"type": "command",
"name": "Run with --debug",
"program": "$PROJECT_DIR$/mx",
"workingDir": "$PROJECT_DIR$",
"args": ["--debug", "test.mx"]
}
]
}

View File

@ -1,8 +0,0 @@
{
"plugins": [
{
"type": "add",
"pluginName": "fleet.vim"
}
]
}

BIN
bogus

Binary file not shown.

6
examples/loop.bo Normal file
View File

@ -0,0 +1,6 @@
print "What is the secret word?";
while input != "dingus" {
println "That is not the secret word!";
print "What is the secret word?";
}

View File

@ -18,10 +18,11 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
tokens = tokenList;
log.debug("Alright we got " + to_string(tokens.size()) + " tokens");
whileLoopStartIndex = -1;
while (tokenIndex < static_cast<int>(tokens.size() - 1)) {
auto currentToken = consume();
if (!currentToken) break;
vector<Token> currentInstruction;
currentInstruction.push_back(currentToken.value());
@ -140,6 +141,7 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
i -= 1;
}
}
currentInstructionForWhileLoop = currentInstruction;
// Detect any comparisons and convert
// Start at 1 to avoid having to do more crappy memory safety stuff
for (int i = 1; i < currentInstruction.size(); i++) {
@ -216,6 +218,99 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
i -= 1;
}
}
if (currentInstruction[0].keyword == keywords::WHILE) {
Loop whileLoop;
whileLoopStartIndex = tokenIndex;
// Store the condition
for (size_t i = 1; i < currentInstruction.size(); i++) {
if (currentInstruction[i].keyword == keywords::OBRAC) break;
whileLoop.condition.push_back(currentInstruction[i]);
}
// Collect loop body instructions
int bracketCount = 1;
vector<Token> currentBody;
while (bracketCount > 0 && tokenIndex < tokens.size()) {
auto token = peek(1);
if (!token) break;
if (token->keyword == keywords::OBRAC) bracketCount++;
if (token->keyword == keywords::CBRAC) bracketCount--;
if (bracketCount == 0) break;
consume();
currentBody.push_back(token.value());
if (token->keyword == keywords::SEMICOLON ||
token->keyword == keywords::CBRAC) {
if (!currentBody.empty()) {
whileLoop.instructions.push_back(currentBody);
currentBody.clear();
}
}
}
// Store the start position of the while loop
whileLoopStartIndex = tokenIndex;
vector<Token> whileCondition;
// The condition should be everything after WHILE until OBRAC
whileCondition.clear();
for (size_t i = 1; i < currentInstruction.size(); i++) {
if (currentInstruction[i].keyword == keywords::OBRAC) break;
whileCondition.push_back(currentInstruction[i]);
}
// Skip processing until we find the matching closing brace
while (bracketCount > 0 && tokenIndex < tokens.size()) {
auto token = consume();
if (!token) break;
if (token->keyword == keywords::OBRAC) bracketCount++;
if (token->keyword == keywords::CBRAC) bracketCount--;
}
// Execute the loop
loops.push_back(whileLoop);
while (true) {
// Check condition
bool conditionMet = false;
for (const auto& condToken : whileLoop.condition) {
if (condToken.type == valtype::BOOL) {
conditionMet = get<bool>(condToken.value.value);
break;
}
}
if (!conditionMet) break;
// Execute body
for (const auto& instruction : whileLoop.instructions) {
currentInstructionForWhileLoop = instruction;
// Process each instruction using your existing logic
// You might want to create a helper method for this
}
}
loops.pop_back();
// Skip to end of loop
while (bracketCount >= 0) {
auto token = consume();
if (!token) break;
if (token->keyword == keywords::CBRAC) bracketCount--;
}
}
// Handle the closing brace of while loop
if (currentInstruction[0].keyword == keywords::CBRAC && whileLoopStartIndex != -1) {
// Go back to evaluate the condition again
tokenIndex = whileLoopStartIndex;
continue;
}
// Execute the instruction
executeCode(currentInstruction);
}
@ -232,6 +327,17 @@ void Interpreter::executeCode(vector<Token> tokens) {
skipScope --;
return;
}
if (repeatScope > 0) {
vector<Token> buffer;
while (tokens[i].keyword != keywords::CBRAC) {
buffer.push_back(tokens[i]);
i++;
if (tokens[i].keyword == keywords::SEMICOLON) {
loops[i].instructions.push_back(buffer);
buffer.clear();
}
}
}
if (tokens[i].keyword == keywords::PRINTLN) {
i++;
if (tokens.size() <= i) break;
@ -364,6 +470,16 @@ void Interpreter::executeCode(vector<Token> tokens) {
skipScope ++;
return;
}
} else if (tokens[i].keyword == keywords::WHILE) {
i++;
if (tokens.size() < i) syntaxError.fnNotSufficientArgs("while", 1, 1, 0);
if (tokens[i].keyword != keywords::VALUE) syntaxError.generalError("while needs a value, not a keyword");
if (tokens[i].type != valtype::BOOL) syntaxError.comparisonTypeError("in a while statement");
Loop newLoop;
vector<Token> condition;
for (int i = 0; i < currentInstructionForWhileLoop.size(); i++) if (currentInstructionForWhileLoop[i].keyword == keywords::VALUE || currentInstructionForWhileLoop[i].keyword == keywords::EQUAL || currentInstructionForWhileLoop[i].keyword == keywords::INEQUAL) condition.push_back(currentInstructionForWhileLoop[i]);
newLoop.condition = condition;
repeatScope ++;
} else {
if (tokens[i].keyword == keywords::VALUE && tokens[i].value.type == valtype::STR && variables.find(get<string>(tokens[i].value.value)) != variables.end()) {
log.debug("Manipulating variable...");

View File

@ -4,10 +4,18 @@
#include "SyntaxError.h"
#include "Logger.h"
struct Loop {
vector<vector<Token>> instructions;
vector<Token> condition;
};
class Interpreter {
private:
int skipScope = 0;
int repeatScope = 0;
vector<Loop> loops;
vector<Token> currentInstructionForWhileLoop;
int whileLoopStartIndex;
SyntaxError syntaxError;
vector<Token> tokens;
map<string, Value> variables;