More stuff related to lists

This commit is contained in:
2025-05-12 20:04:38 +10:00
parent 7f4e87f768
commit b7febe7f1c
10 changed files with 101 additions and 8 deletions

View File

@@ -1,4 +1,4 @@
![Iodine programming language logo](https://git.maxwellj.xyz/iodine/iodine/raw/commit/a782c09f913ecc38df7a84665f305e4ea89fb7d7/branding/Iodine_250px.png)
![Iodine programming language logo](https://chookspace.com/iodine/iodine/raw/branch/master/branding/Iodine_250px.png)
# Iodine - a statically typed, interpreted language

View File

@@ -1 +0,0 @@
println args;

1
examples/list.io Normal file
View File

@@ -0,0 +1 @@
printlist ["This is an element in the list" "And this is another" "Oh look another list element" "How fun!"];

View File

@@ -249,6 +249,34 @@ void Interpreter::interpret(vector<Token> tokenList) {
i -= 1;
}
}
// Find lists and create list objects
for (int i = 0; i < currentInstruction.size(); i++) {
if (currentInstruction[i].keyword == keywords::OSQUA) {
log.debug("Making a list");
int startIndex = i;
currentInstruction.erase(currentInstruction.begin() + i);
List buf;
buf.type = currentInstruction[i].value.type;
while (currentInstruction[i].keyword != keywords::CSQUA) {
if (buf.type == currentInstruction[i].value.type) {
buf.value.push_back(currentInstruction[i].value);
currentInstruction.erase(currentInstruction.begin() + i);
} else {
syntaxError.listTypeMismatch();
}
}
currentInstruction.erase(currentInstruction.begin() + i);
Value newValue;
newValue.type = valtype::LIST;
newValue.value = buf;
Token newToken;
newToken.type = valtype::LIST;
newToken.value.type = valtype::LIST;
newToken.value.value = buf;
newToken.keyword = keywords::LIST;
currentInstruction.insert(currentInstruction.begin() + startIndex, newToken);
}
}
// Execute the instruction
log.debug("Length of line is " + to_string(lengthOfLine));
executeCode(currentInstruction);
@@ -285,7 +313,7 @@ void Interpreter::executeCode(vector<Token> tokens) {
}
if (tokens[i].keyword == keywords::PRINTLN) {
i++;
if (tokens.size() <= i) break;
if (tokens.size() <= i) syntaxError.fnNotSufficientArgs("println", 1, 1, 0);
Token nextToken = tokens[i];
// Handle different value types
if (nextToken.keyword == keywords::VALUE) {
@@ -307,7 +335,7 @@ void Interpreter::executeCode(vector<Token> tokens) {
syntaxError.fnTypeMismatch("println", validTypes, nextToken.type);
}
} else {
syntaxError.fnNotSufficientArgs("println", 1, 1, 0);
syntaxError.fnTypeMismatch("println", {}, nextToken.type);
}
} else if (tokens[i].keyword == keywords::PRINT) {
i++;
@@ -335,6 +363,39 @@ void Interpreter::executeCode(vector<Token> tokens) {
} else {
syntaxError.fnNotSufficientArgs("print", 1, 1, 0);
}
} else if (tokens[i].keyword == keywords::PRINTLIST) {
i++;
if (tokens.size() <= i) syntaxError.fnNotSufficientArgs("printlist", 1, 1, 0);
Token nextToken = tokens[i];
log.debug("Printing a list. Type of next token is " + log.getTypeString(nextToken.value.type));
if (nextToken.keyword == keywords::LIST && nextToken.type == valtype::LIST) {
List list = get<List>(nextToken.value.value);
log.debug("List obtained");
if (list.value[0].type == valtype::INT) {
for (int j = 0; j < list.value.size(); j++) {
cout << get<int>(list.value[j].value) << ", ";
}
}
else if (list.value[0].type == valtype::DEC) {
for (int j = 0; j < list.value.size(); j++) {
cout << get<double>(list.value[j].value) << ", ";
}
}
else if (list.value[0].type == valtype::STR) {
for (int j = 0; j < list.value.size(); j++) {
cout << get<string>(list.value[j].value) << ", ";
}
}
else if (list.value[0].type == valtype::BOOL) {
for (int j = 0; j < list.value.size(); j++) {
cout << (get<bool>(list.value[j].value) ? "true" : "false") << ", ";
}
}
cout << endl;
} else {
syntaxError.fnTypeMismatch("printlist", {}, valtype::UNKNOWN);
}
break;
} else if (tokens[i].keyword == keywords::EXIT) {
i++;
if (tokens.size() <= i) break;

View File

@@ -52,3 +52,25 @@ void Logger::debug(string in) {
if (isDebug) cout << "Debug: " + in + "\n";
writeToLog("Debug", in);
}
string Logger::getTypeString(valtype in) {
switch (in) {
case valtype::STR:
return "string";
case valtype::INT:
return "int";
case valtype::DEC:
return "dec";
case valtype::BOOL:
return "bool";
case valtype::LIST:
return "list";
case valtype::KEYWORD:
return "keyword";
case valtype::UNKNOWN:
return "unknown";
default:
return "unknown";
}
return "error";
}

View File

@@ -32,4 +32,5 @@ public:
void fatalError(string in, int code);
void info(string in);
void debug(string in);
string getTypeString(valtype in);
};

View File

@@ -72,7 +72,7 @@ void Parser::parseLines(string in, Logger log) {
}
terms.push_back(termBuffer);
termBuffer.clear();
} else if ((c == ',' || c == '{' || c == '}' || c == '(' || c == ')') && !isString) {
} else if ((c == ',' || c == '{' || c == '}' || c == '(' || c == ')' || c == '[' || c == ']') && !isString) {
if (!buffer.empty()) {
termBuffer.push_back(buffer);
buffer.clear();
@@ -120,6 +120,7 @@ void Parser::processLines() {
else if (ct == "let") token.keyword = keywords::LET;
else if (ct == "print") token.keyword = keywords::PRINT;
else if (ct == "println") token.keyword = keywords::PRINTLN;
else if (ct == "printlist") token.keyword = keywords::PRINTLIST;
else if (ct == "input") token.keyword = keywords::INPUT;
else if (ct == "return") token.keyword = keywords::RETURN;
else if (ct == "exit") token.keyword = keywords::EXIT;

View File

@@ -30,7 +30,8 @@ void SyntaxError::fnTypeMismatch(string function, vector<string> validTypes, val
else if (typeGiven == valtype::DEC) cerr << "dec";
else if (typeGiven == valtype::STR) cerr << "str";
else if (typeGiven == valtype::BOOL) cerr << "bool";
else cerr << "unknown";
else if (typeGiven == valtype::LIST) cerr << "list";
else cerr << "other or unknown";
cerr << "' instead" << endl;
if (!notes.empty()) cerr << "Notes: " << notes << endl;
exit(1);
@@ -75,6 +76,12 @@ void SyntaxError::cannotCompareDifferentTypes(string notes) {
if (!notes.empty()) cerr << "Notes: " << notes << endl;
exit(1);
}
void SyntaxError::listTypeMismatch(string notes) {
cerr << "TypeError: List type mismatch" << 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

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

View File

@@ -38,8 +38,8 @@ enum class keywords {
ADD, SUBTRACT, MULTIPLY, DIVIDE,
EQUAL, INEQUAL, LESS, GREATER, EQLESS, EQGREATER,
INCREMENT, DECREMENT,
PRINT, PRINTLN, LET, INPUT, EXIT,
VALUE, SEMICOLON, VARIABLE,
PRINT, PRINTLN, PRINTLIST, LET, INPUT, EXIT,
VALUE, LIST, SEMICOLON, VARIABLE,
COMMENT
};