hell yeah if statements

This commit is contained in:
Maxwell 2025-04-26 20:46:32 +10:00
parent e9f6282446
commit 9ec709d4f2
6 changed files with 83 additions and 45 deletions

BIN
mx

Binary file not shown.

View File

@ -26,7 +26,7 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
// Collect tokens until semicolon // Collect tokens until semicolon
while (auto nextToken = peek(1)) { while (auto nextToken = peek(1)) {
if (nextToken->keyword == keywords::SEMICOLON) { if (nextToken->keyword == keywords::SEMICOLON || nextToken->keyword == keywords::OBRAC || nextToken->keyword == keywords::CBRAC) {
consume(); // consume the semicolon consume(); // consume the semicolon
break; break;
} }
@ -123,21 +123,31 @@ void Interpreter::convertToTokens(vector<Token> tokenList) {
newToken.type = valtype::BOOL; newToken.type = valtype::BOOL;
newToken.value.type = valtype::BOOL; newToken.value.type = valtype::BOOL;
if (currentInstruction.size() < i + 1) syntaxError.mathTooFewArgs(); if (currentInstruction.size() < i + 1) syntaxError.mathTooFewArgs();
if (currentInstruction[i - 1].value.type != currentInstruction[i + 1].value.type) syntaxError.mathTypeMismatch(); if (currentInstruction[i - 1].type != currentInstruction[i + 1].type) syntaxError.mathTypeMismatch();
log.debug("Comparing stuff"); log.debug("Comparing values of type: " + to_string(static_cast<int>(currentInstruction[i - 1].type)));
if (currentInstruction[i - 1].value.type == valtype::INT) {
if (get<int>(currentInstruction[i - 1].value.value) == get<int>(currentInstruction[i + 1].value.value)) newToken.value.value = true; // Make sure both operands are values
else newToken.value.value = false; if (currentInstruction[i - 1].keyword != keywords::VALUE ||
} else if (currentInstruction[i - 1].value.type == valtype::DEC) { currentInstruction[i + 1].keyword != keywords::VALUE) {
if (get<double>(currentInstruction[i - 1].value.value) == get<double>(currentInstruction[i + 1].value.value)) newToken.value.value = true; syntaxError.generalError("Can only compare values");
else newToken.value.value = false; return;
} else if (currentInstruction[i - 1].value.type == valtype::STR) {
if (get<string>(currentInstruction[i - 1].value.value) == get<string>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
else newToken.value.value = false;
} else if (currentInstruction[i - 1].value.type == valtype::BOOL) {
if (get<bool>(currentInstruction[i - 1].value.value) == get<bool>(currentInstruction[i + 1].value.value)) newToken.value.value = true;
else newToken.value.value = false;
} }
// Ensure value types are set correctly
if (currentInstruction[i - 1].value.type == valtype::INT) {
newToken.value.value = (get<int>(currentInstruction[i - 1].value.value) ==
get<int>(currentInstruction[i + 1].value.value));
} else if (currentInstruction[i - 1].value.type == valtype::DEC) {
newToken.value.value = (get<double>(currentInstruction[i - 1].value.value) ==
get<double>(currentInstruction[i + 1].value.value));
} else if (currentInstruction[i - 1].value.type == valtype::STR) {
newToken.value.value = (get<string>(currentInstruction[i - 1].value.value) ==
get<string>(currentInstruction[i + 1].value.value));
} else if (currentInstruction[i - 1].value.type == valtype::BOOL) {
newToken.value.value = (get<bool>(currentInstruction[i - 1].value.value) ==
get<bool>(currentInstruction[i + 1].value.value));
}
currentInstruction[i - 1] = newToken; currentInstruction[i - 1] = newToken;
currentInstruction.erase(currentInstruction.begin() + i); currentInstruction.erase(currentInstruction.begin() + i);
currentInstruction.erase(currentInstruction.begin() + i); currentInstruction.erase(currentInstruction.begin() + i);
@ -153,6 +163,13 @@ void Interpreter::executeCode(vector<Token> tokens) {
SyntaxError syntaxError; SyntaxError syntaxError;
log.debug("Token length for this expression is " + to_string(tokens.size())); log.debug("Token length for this expression is " + to_string(tokens.size()));
for (int i = 0; i < tokens.size(); i++) { for (int i = 0; i < tokens.size(); i++) {
if (skipScope > 0) {
while (tokens[i].keyword != keywords::CBRAC) {
i++;
}
skipScope --;
return;
}
if (tokens[i].keyword == keywords::PRINT) { if (tokens[i].keyword == keywords::PRINT) {
i++; i++;
if (tokens.size() <= i) break; if (tokens.size() <= i) break;
@ -160,21 +177,21 @@ void Interpreter::executeCode(vector<Token> tokens) {
// Handle different value types // Handle different value types
if (nextToken.keyword == keywords::VALUE) { if (nextToken.keyword == keywords::VALUE) {
switch (nextToken.type) { switch (nextToken.type) {
case valtype::INT: case valtype::INT:
cout << get<int>(nextToken.value.value) << endl; cout << get<int>(nextToken.value.value) << endl;
break; break;
case valtype::DEC: case valtype::DEC:
cout << get<double>(nextToken.value.value) << endl; cout << get<double>(nextToken.value.value) << endl;
break; break;
case valtype::STR: case valtype::STR:
cout << get<string>(nextToken.value.value) << endl; cout << get<string>(nextToken.value.value) << endl;
break; break;
case valtype::BOOL: case valtype::BOOL:
cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl; cout << (get<bool>(nextToken.value.value) ? "true" : "false") << endl;
break; break;
default: default:
vector<string> validTypes = {"int", "dec", "str", "bool"}; vector<string> validTypes = {"int", "dec", "str", "bool"};
syntaxError.fnTypeMismatch("print", validTypes, nextToken.type); syntaxError.fnTypeMismatch("print", validTypes, nextToken.type);
} }
} else { } else {
syntaxError.fnNotSufficientArgs("print", 1, 1, 0); syntaxError.fnNotSufficientArgs("print", 1, 1, 0);
@ -185,15 +202,15 @@ void Interpreter::executeCode(vector<Token> tokens) {
Token nextToken = tokens[i]; Token nextToken = tokens[i];
if (nextToken.keyword == keywords::VALUE) { if (nextToken.keyword == keywords::VALUE) {
switch (nextToken.type) { switch (nextToken.type) {
case valtype::INT: case valtype::INT:
exit(get<int>(nextToken.value.value)); exit(get<int>(nextToken.value.value));
break; break;
case valtype::DEC: case valtype::DEC:
exit(get<double>(nextToken.value.value)); exit(get<double>(nextToken.value.value));
break; break;
default: default:
vector<string> validTypes = {"int", "dec"}; vector<string> validTypes = {"int", "dec"};
syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type); syntaxError.fnTypeMismatch("exit", validTypes, nextToken.type);
} }
} }
} else if (tokens[i].keyword == keywords::LET) { } else if (tokens[i].keyword == keywords::LET) {
@ -202,23 +219,23 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.fnNotSufficientArgs("let", 3, 3, tokens.size() - i); syntaxError.fnNotSufficientArgs("let", 3, 3, tokens.size() - i);
break; break;
} }
Token typeToken = tokens[i]; Token typeToken = tokens[i];
Token nameToken = tokens[i + 1]; Token nameToken = tokens[i + 1];
Token valueToken = tokens[i + 2]; Token valueToken = tokens[i + 2];
i += 2; i += 2;
// Validate that we have a valid variable name // Validate that we have a valid variable name
if (nameToken.type != valtype::STR) { if (nameToken.type != valtype::STR) {
vector<string> validTypes = {"str"}; vector<string> validTypes = {"str"};
syntaxError.fnTypeMismatch("let (variable name)", validTypes, nameToken.type); syntaxError.fnTypeMismatch("let (variable name)", validTypes, nameToken.type);
continue; continue;
} }
string varName = get<string>(nameToken.value.value); string varName = get<string>(nameToken.value.value);
Value newValue; Value newValue;
// Check the type declaration matches the value // Check the type declaration matches the value
if (typeToken.keyword == keywords::INT && valueToken.type == valtype::INT) { if (typeToken.keyword == keywords::INT && valueToken.type == valtype::INT) {
newValue.type = valtype::INT; newValue.type = valtype::INT;
@ -245,9 +262,20 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.fnTypeMismatch("let", validTypes, valueToken.type, "Variable name is " + varName); syntaxError.fnTypeMismatch("let", validTypes, valueToken.type, "Variable name is " + varName);
continue; continue;
} }
// Store the variable // Store the variable
variables[varName] = newValue; variables[varName] = newValue;
} else if (tokens[i].keyword == keywords::IF) {
i++;
if (tokens.size() < i) syntaxError.fnNotSufficientArgs("if", 1, 1, 0);
log.debug("IF statement token type: " + to_string(static_cast<int>(tokens[i].type)));
log.debug("IF statement token keyword: " + to_string(static_cast<int>(tokens[i].keyword)));
if (tokens[i].keyword != keywords::VALUE) syntaxError.generalError("if needs a value, not a keyword");
if (tokens[i].type != valtype::BOOL) syntaxError.comparisonTypeError("in an if statement");
if (!get<bool>(tokens[i].value.value)) {
skipScope ++;
return;
}
} else { } else {
if (tokens[i].keyword == keywords::VALUE && tokens[i].value.type == valtype::STR && variables.find(get<string>(tokens[i].value.value)) != variables.end()) { 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..."); log.debug("Manipulating variable...");
@ -300,7 +328,7 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.mathCannotDoOperationOnType("unknown", "any"); syntaxError.mathCannotDoOperationOnType("unknown", "any");
} }
} else { } else {
syntaxError.unknownFn(); if (tokens[i].keyword != keywords::CBRAC) syntaxError.unknownFn();
} }
} }
} }

View File

@ -6,6 +6,8 @@
class Interpreter { class Interpreter {
private: private:
int skipScope = 0;
int repeatScope = 0;
SyntaxError syntaxError; SyntaxError syntaxError;
vector<Token> tokens; vector<Token> tokens;
map<string, Value> variables; map<string, Value> variables;

View File

@ -107,6 +107,8 @@ void Parser::processLines() {
else if (ct == "dec") token.keyword = keywords::DEC; else if (ct == "dec") token.keyword = keywords::DEC;
else if (ct == "str") token.keyword = keywords::STR; else if (ct == "str") token.keyword = keywords::STR;
else if (ct == "bool") token.keyword = keywords::BOOL; else if (ct == "bool") token.keyword = keywords::BOOL;
else if (ct == "if") token.keyword = keywords::IF;
else if (ct == "while") token.keyword = keywords::WHILE;
else if (ct == "{") token.keyword = keywords::OBRAC; else if (ct == "{") token.keyword = keywords::OBRAC;
else if (ct == "}") token.keyword = keywords::CBRAC; else if (ct == "}") token.keyword = keywords::CBRAC;
else if (ct == "(") token.keyword = keywords::OPARE; else if (ct == "(") token.keyword = keywords::OPARE;

View File

@ -55,4 +55,9 @@ void SyntaxError::generalError(string notes) {
void SyntaxError::cannotCompareDifferentTypes(string notes) { void SyntaxError::cannotCompareDifferentTypes(string notes) {
cerr << "ComparisonError: cannot compare two different types" << endl; cerr << "ComparisonError: cannot compare two different types" << endl;
if (!notes.empty()) cerr << "Notes: " << notes << endl; if (!notes.empty()) cerr << "Notes: " << notes << endl;
exit(1);
}
void SyntaxError::comparisonTypeError(string notes) {
cerr << "ComparisonError: cannot use a non-bool type in an if or while statement" << endl;
if (!notes.empty()) cerr << "Notes: " << notes << endl;
} }

View File

@ -11,5 +11,6 @@ public:
void mathTooFewArgs(string notes = ""); void mathTooFewArgs(string notes = "");
void mathCannotDoOperationOnType(string operatorUsed, string type, string notes = ""); void mathCannotDoOperationOnType(string operatorUsed, string type, string notes = "");
void cannotCompareDifferentTypes(string notes = ""); void cannotCompareDifferentTypes(string notes = "");
void comparisonTypeError(string notes = "");
void generalError(string notes = ""); void generalError(string notes = "");
}; };