diff --git a/examples/function.io b/examples/function.io index 70f8065..da8a143 100644 --- a/examples/function.io +++ b/examples/function.io @@ -1,3 +1,5 @@ println "Time to define a function"; fun str myFunction(int myNum); + +myFunction(3); diff --git a/src/Interpreter.cpp b/src/Interpreter.cpp index 12200c1..e12ae91 100644 --- a/src/Interpreter.cpp +++ b/src/Interpreter.cpp @@ -57,8 +57,9 @@ valtype Interpreter::keywordToValtype(keywords in) { return valtype::KEYWORD; } -void Interpreter::interpret(vector tokenList) { +optional Interpreter::interpret(vector tokenList, bool isFunction) { if (debugMode) log.toggleDebugPrint(); + if (isFunction) log.debug("Currently executing code for a function"); tokens = tokenList; log.debug("Alright we got " + to_string(tokens.size()) + " tokens"); @@ -194,6 +195,7 @@ void Interpreter::interpret(vector tokenList) { i -= 1; } } + // 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++) { @@ -210,7 +212,7 @@ void Interpreter::interpret(vector tokenList) { if (currentInstruction[i - 1].keyword != keywords::VALUE || currentInstruction[i + 1].keyword != keywords::VALUE) { syntaxError.generalError("Can only compare values"); - return; + return {}; } // Ensure value types are set correctly @@ -246,7 +248,7 @@ void Interpreter::interpret(vector tokenList) { if (currentInstruction[i - 1].keyword != keywords::VALUE || currentInstruction[i + 1].keyword != keywords::VALUE) { syntaxError.generalError("Can only compare values of"); - return; + return {}; } // Ensure value types are set correctly @@ -298,14 +300,53 @@ void Interpreter::interpret(vector tokenList) { currentInstruction.insert(currentInstruction.begin() + startIndex, newToken); } } + // Call functions and assign values + for (int i = 0; i < currentInstruction.size(); i++) { + log.debug("Looking for a function"); + Function empty; + for (int j = 0; j < functionnames.size(); j++) { + log.debug("There is a function called " + functionnames[j]); + //if (tokens[i].type == valtype::STR && functionnames[j] == get(tokens[i].value.value)) log.debug("in theory we should be fine?"); + } + if (currentInstruction[i].type == valtype::STR && functions.find(get(currentInstruction[i].value.value)) != functions.end()) { + log.debug("Found a function"); + Function fnbuf = functions[get(currentInstruction[i].value.value)]; + i++; + if (currentInstruction[i].keyword != keywords::OPARE) syntaxError.generalError("Expecting a '(' when calling a function"); + i++; + vector argsForFn; + int argCount = 0; + if (currentInstruction[i].keyword != keywords::CPARE) while (currentInstruction[i].keyword != keywords::CPARE) { + if (i >= currentInstruction.size()) syntaxError.generalError("Expecting a ')' after function arguments"); + if (currentInstruction[i].value.type != fnbuf.arguments[fnbuf.argNames[argCount]]) syntaxError.fnTypeMismatch(get(currentInstruction[i].value.value), {log.getTypeString(fnbuf.arguments[fnbuf.argNames[argCount]])}, currentInstruction[i].value.type); + variables[fnbuf.argNames[argCount]] = tokens[i].value; + i++; + } + resumePoint.push(tokenIndex); + vector fnTokens; + int l = 1; + int m = 0; + while (l > 0) { + if (tokens[m].keyword == keywords::OBRAC) l++; + if (tokens[m].keyword == keywords::CBRAC) l--; + if (l < 1) break; + fnTokens.push_back(tokens[m]); + m++; + } + interpret(fnTokens, true); + log.debug("This is a test call for a function. Function won't actually be run yet. If you see this everything is fine"); + //tokenIndex = functions[get(currentInstruction[i].value.value)].startToken; + + } + } // Execute the instruction log.debug("Length of line is " + to_string(lengthOfLine)); - executeCode(currentInstruction); + executeCode(currentInstruction, isFunction); lengthOfLine = 0; } } -void Interpreter::executeCode(vector tokens) { +optional Interpreter::executeCode(vector tokens, bool isFunction) { SyntaxError syntaxError; log.debug("Token length for this expression is " + to_string(tokens.size())); for (int i = 0; i < tokens.size(); i++) { @@ -329,7 +370,7 @@ void Interpreter::executeCode(vector tokens) { if (tokens[i].keyword == keywords::CBRAC) { tokenIndex = loop; repeatScope --; - return; + return {}; } } if (tokens[i].keyword == keywords::PRINTLN) { @@ -504,7 +545,7 @@ void Interpreter::executeCode(vector tokens) { if (tokens[i].type != valtype::BOOL) syntaxError.comparisonTypeError("in an if statement"); if (!get(tokens[i].value.value)) { skipScope ++; - return; + return {}; } } else if (tokens[i].keyword == keywords::WHILE) { i++; @@ -532,36 +573,58 @@ void Interpreter::executeCode(vector tokens) { } else if (tokens[i].keyword == keywords::FUN) { i++; Function buf; - if (keywordToValtype(tokens[i].keyword) == valtype::KEYWORD) syntaxError.generalError("fun needs a defining value for arg 1, not a value. "); + if (keywordToValtype(tokens[i].keyword) == valtype::KEYWORD) syntaxError.generalError("fun needs a defining value for arg 1, not a non-value."); buf.type = keywordToValtype(tokens[i].keyword); i++; + tokenIndex ++; string valName; if (tokens[i].value.type == valtype::STR) valName = get(tokens[i].value.value); - buf.startToken = tokenIndex; + functionnames.push_back(valName); i++; + tokenIndex ++; if (tokens[i].keyword != keywords::OPARE) syntaxError.generalError("This is a placeholder"); i++; + tokenIndex ++; map valuetypes; - while (tokens[i].keyword != keywords::CPARE) { + // Get the arguments which we will use in the function + if (tokens[i + 1].keyword != keywords::CPARE) while (tokens[i].keyword != keywords::CPARE) { // We should have a valtype, a name for the variable, and a comma if the thing hasn't ended already if (keywordToValtype(tokens[i].keyword) == valtype::KEYWORD) syntaxError.generalError("Another placeholder"); valtype valbuf = keywordToValtype(tokens[i].keyword); i++; + tokenIndex ++; if (tokens[i].type != valtype::STR) syntaxError.generalError("A third placeholder"); + log.debug("This function needs a " + log.getTypeString(valbuf) + " which is accessible as " + get(tokens[i].value.value)); + buf.argNames.push_back(get(tokens[i].value.value)); valuetypes[get(tokens[i].value.value)] = valbuf; i++; + tokenIndex ++; if (tokens[i].keyword == keywords::CPARE) break; if (tokens[i].keyword != keywords::COMMA) syntaxError.generalError("Yet another placeholder"); i++; + tokenIndex ++; } + else log.debug("Function does not require arguments"); + tokenIndex ++; + buf.arguments = valuetypes; + buf.startToken = tokenIndex; functions[valName] = buf; - log.debug("Init a function"); + log.debug("Init a function with name " + valName + " success. Function starts at index " + to_string(buf.startToken)); + } else if (tokens[i].keyword == keywords::RETURN) { + i++; + if (i >= tokens.size()) syntaxError.fnNotSufficientArgs("return", 1, 1, 0); + if (isFunction){ + return tokens[i++]; + } else { + if (tokens[i].value.type != valtype::INT) syntaxError.improperReturnType(""); + exit(get(tokens[i].value.value)); + } } 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..."); if (tokens.size() <= i + 2) { // Need at least 3 tokens: variable, operator, value syntaxError.mathTooFewArgs(); - return; + return {}; } string varName = get(tokens[i].value.value); i++; @@ -578,7 +641,7 @@ void Interpreter::executeCode(vector tokens) { default: validTypes = {"unknown"}; break; } syntaxError.fnTypeMismatch("assignment", validTypes, valueToken.type); - return; + return {}; } variables[varName].value = valueToken.value.value; i++; // Skip the value token since we've processed it @@ -613,4 +676,5 @@ void Interpreter::executeCode(vector tokens) { } } } + return {}; } diff --git a/src/Interpreter.h b/src/Interpreter.h index 44f3abb..0a1232e 100644 --- a/src/Interpreter.h +++ b/src/Interpreter.h @@ -26,22 +26,23 @@ class Interpreter { private: int skipScope = 0; int repeatScope = 0; - int resumePoint = 0; + stack resumePoint; vector loops; SyntaxError syntaxError; vector tokens; map variables; map functions; + vector functionnames; Logger log; int loop; int lengthOfLine; int tokenIndex = -1; optional consume(); optional peek(int offset = 1); - void executeCode(vector tokens); + optional executeCode(vector tokens, bool isFunction); valtype keywordToValtype(keywords in); public: void initInterpreter(vector args); - void interpret(vector tokenList); + optional interpret(vector tokenList, bool isFunction); }; diff --git a/src/SyntaxError.cpp b/src/SyntaxError.cpp index d4218bc..ed55f96 100644 --- a/src/SyntaxError.cpp +++ b/src/SyntaxError.cpp @@ -67,7 +67,7 @@ void SyntaxError::mathCannotDoOperationOnType(string operatorUsed, string type, } void SyntaxError::generalError(string notes) { - cerr << "GeneralError: Something went awfully wrong and we don't know why lmao" << endl; + cerr << "GeneralError: General error" << endl; if (!notes.empty()) cerr << "Notes: " << notes << endl; exit(1); } @@ -88,7 +88,14 @@ void SyntaxError::listOutOfBounds(string notes) { exit(1); } +void SyntaxError::improperReturnType(string notes) { + cerr << "TypeError: Mismatched function return type" << 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; + exit(1); } diff --git a/src/SyntaxError.h b/src/SyntaxError.h index 1fd8236..dd08b73 100644 --- a/src/SyntaxError.h +++ b/src/SyntaxError.h @@ -32,5 +32,6 @@ public: void comparisonTypeError(string notes = ""); void listTypeMismatch(string notes = ""); void listOutOfBounds(string notes = ""); + void improperReturnType(string notes = ""); void generalError(string notes = ""); }; diff --git a/src/common.h b/src/common.h index 5334979..130f547 100644 --- a/src/common.h +++ b/src/common.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ struct Value { struct Function { valtype type; + vector argNames; map arguments; int startToken; }; diff --git a/src/main.cpp b/src/main.cpp index 96251fa..2942515 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -51,6 +51,6 @@ int main(int argc, char* argv[]) { Interpreter interpreter; // Convert to tokens and run the code interpreter.initInterpreter(args.getAllArgs()); - interpreter.interpret(parser.getTokens()); + interpreter.interpret(parser.getTokens(), false); return 0; }