diff --git a/.fleet/run.json b/.fleet/run.json deleted file mode 100644 index 64c9d3f..0000000 --- a/.fleet/run.json +++ /dev/null @@ -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"] - } - ] -} \ No newline at end of file diff --git a/.fleet/settings.json b/.fleet/settings.json deleted file mode 100644 index 17d0949..0000000 --- a/.fleet/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "plugins": [ - { - "type": "add", - "pluginName": "fleet.vim" - } - ] -} \ No newline at end of file diff --git a/bogus b/bogus index 080e1d7..67128b1 100755 Binary files a/bogus and b/bogus differ diff --git a/examples/loop.bo b/examples/loop.bo new file mode 100644 index 0000000..71ca883 --- /dev/null +++ b/examples/loop.bo @@ -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?"; +} diff --git a/src/Interpreter.cpp b/src/Interpreter.cpp index da1e1a0..d144c54 100644 --- a/src/Interpreter.cpp +++ b/src/Interpreter.cpp @@ -18,10 +18,11 @@ void Interpreter::convertToTokens(vector tokenList) { tokens = tokenList; log.debug("Alright we got " + to_string(tokens.size()) + " tokens"); + whileLoopStartIndex = -1; + while (tokenIndex < static_cast(tokens.size() - 1)) { auto currentToken = consume(); if (!currentToken) break; - vector currentInstruction; currentInstruction.push_back(currentToken.value()); @@ -140,6 +141,7 @@ void Interpreter::convertToTokens(vector 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 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 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 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(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 tokens) { skipScope --; return; } + if (repeatScope > 0) { + vector 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 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 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(tokens[i].value.value)) != variables.end()) { log.debug("Manipulating variable..."); diff --git a/src/Interpreter.h b/src/Interpreter.h index 843f8a2..1ed43f0 100644 --- a/src/Interpreter.h +++ b/src/Interpreter.h @@ -4,10 +4,18 @@ #include "SyntaxError.h" #include "Logger.h" +struct Loop { + vector> instructions; + vector condition; +}; + class Interpreter { private: int skipScope = 0; int repeatScope = 0; + vector loops; + vector currentInstructionForWhileLoop; + int whileLoopStartIndex; SyntaxError syntaxError; vector tokens; map variables; @@ -19,4 +27,4 @@ private: public: void convertToTokens(vector tokenList); void executeCode(vector tokens); -}; \ No newline at end of file +};