From 435d2a2270c1717bb5b990d7f50dbcbc66a46916 Mon Sep 17 00:00:00 2001 From: sam-astro <77079540+sam-astro@users.noreply.github.com> Date: Sun, 2 Jan 2022 11:41:53 -0500 Subject: [PATCH] Added strig differentiation, and am making cross-referencable functions that can be made in c++. Also made a "builtin.slg" file to load built-in functions and variables written in slang --- Slang/Main.cpp | 264 +++++++++++++++++++++++++++++------- Slang/Slang.vcxproj | 2 + Slang/Slang.vcxproj.filters | 4 + Slang/builtin.h | 92 +++++++++++++ Slang/builtin.slg | 7 + Slang/script.slg | 17 +-- Slang/strops.cpp | 3 + 7 files changed, 333 insertions(+), 56 deletions(-) create mode 100644 Slang/builtin.h create mode 100644 Slang/builtin.slg diff --git a/Slang/Main.cpp b/Slang/Main.cpp index b35c728..c30600d 100644 --- a/Slang/Main.cpp +++ b/Slang/Main.cpp @@ -8,11 +8,10 @@ #include #include "eval.h" #include "strops.h" +#include "builtin.h" using namespace std; -vector types = { "int", "float", "string", "bool", "void", "null" }; - vector globalVariables; vector globalVariableValues; vector functions; @@ -43,7 +42,7 @@ public: } }; -int ExecuteFunction(string functionName, vector inputVarVals); +string ExecuteFunction(string functionName, vector inputVarVals); bool isNumber(const string& str) { @@ -65,17 +64,53 @@ string AddItem(string varName, string variableContent, string addItem) string StringRaw(string str) { + if (str.size() < 3) + return str; + string withoutQuotes; + if (str[0] != '\"') + withoutQuotes += str[0]; + for (int ch = 1; ch < (int)str.size() - 1; ch++) withoutQuotes += str[ch]; + if (str[str.size() - 1] != '\"') + withoutQuotes += str[str.size() - 1]; + return withoutQuotes; } string Quoted(string str) { - return "\"" + str + "\""; + string withQuotes; + + if (str[0] != '\"') + withQuotes += '\"'; + + withQuotes += str; + + if (str[str.size() - 1] != '\"') + withQuotes += '\"'; + + return withQuotes; +} + +string RMParenthesis(string str) +{ + str = trim(str); + string withoutParenthesis; + + if (str[0] != '(') + withoutParenthesis += str[0]; + + for (int ch = 1; ch < (int)str.size() - 1; ch++) + withoutParenthesis += str[ch]; + + if (str[str.size() - 1] != ')') + withoutParenthesis += str[str.size() - 1]; + + return withoutParenthesis; } string GetVariableValue(string varName, vector& variables, vector& variableVals) @@ -114,27 +149,107 @@ string GetVariableValue(string varName, vector& variables, vector 0) - //{ - // string withoutQuotes; - - // for (int ch = 1; ch < (int)varName.size() - 1; ch++) - // withoutQuotes += varName[ch]; - - // return withoutQuotes; - //} return varName; } +vector VarValues(vector varNames, vector& variables, vector& variableVals) +{ + vector realValues; + + for (int varIndex = 0; varIndex < varNames.size(); varIndex++) + { + string typ = "string"; + bool isVar = false; + + // Checks against global vars + for (int v = 0; v < (int)globalVariables.size(); v++) + if (varNames[varIndex] == split(globalVariables[v], ' ')[1]) + { + typ = split(globalVariables[v], ' ')[0]; + isVar = true; + } + // Checks against local vars + for (int v = 0; v < (int)variables.size(); v++) + if (varNames[varIndex] == split(variables[v], ' ')[1]) + { + typ = split(variables[v], ' ')[0]; + isVar = true; + } + + // If it is a var + if (isVar) + { + // Checks against global vars + for (int v = 0; v < (int)globalVariables.size(); v++) + if (varNames[varIndex] == split(globalVariables[v], ' ')[1]) + { + realValues.push_back(globalVariableValues[v]); + } + // Checks against local vars + for (int v = 0; v < (int)variables.size(); v++) + if (varNames[varIndex] == split(variables[v], ' ')[1]) + { + realValues.push_back(variableVals[v]); + } + } + else + realValues.push_back(varNames[varIndex]); + } + + return realValues; +} + +bool IsFunction(string funcName) +{ + // Iterate through all functions + for (int t = 0; t < (int)functions.size(); t++) + if (trim(funcName) == split(functions[t], ' ')[0]) + return true; + + return false; +} + string EvalExpression(string expression, vector& variables, vector& variableVals) { expression = trim(expression); - cout << "EXPRESSION: " << expression << endl; + //cout << "EXPRESSION: " << expression << endl; // If no operations are applied, then return self - if (count(expression, '+') == 0 && count(expression, '-') == 0 && count(expression, '*') == 0 && count(expression, '/') == 0 && count(expression, '(') == 0 && count(expression, '^') == 0) - return GetVariableValue(expression, variables, variableVals); + if ((count(expression, '+') == 0 && count(expression, '-') == 0 && count(expression, '*') == 0 && count(expression, '/') == 0 && count(expression, '(') == 0 && count(expression, '^') == 0) || split(expression, '.')[0] == "CPP") + { + if (IsFunction(split(expression, '(')[0])) + { + //cout << split(expression, '(')[0] << endl; + string argContents = ""; + int y = indexInStr(expression, '(') + 1; + while (y < expression.size() && expression[y] != ')') + { + argContents += expression[y]; + + y++; + } + //cout << split(expression, '(')[0] << " " << argContents << endl; + string returnVal = ExecuteFunction(split(expression, '(')[0], VarValues(split(argContents, ','), variables, variableVals)); + return returnVal; + } + else if (split(expression, '.')[0] == "CPP") + { + string argContents = ""; + int y = indexInStr(expression, '(') + 1; + while (y < expression.size() && expression[y] != ')') + { + argContents += expression[y]; + + y++; + } + cout << split(expression, '(')[0] << " " << argContents << endl; + string returnVal = CPPFunction(split(expression, '(')[0], VarValues(split(argContents, ','), variables, variableVals)); + return returnVal; + } + else + return GetVariableValue(expression, variables, variableVals); + } string newExpression = ""; bool inQuotes = false; @@ -145,14 +260,44 @@ string EvalExpression(string expression, vector& variables, vector& variables, vector& variables, vector(str.begin() + 2, str.end())) + ")", variables, variableValues); - cout << variables[v] << " is " << variableValues[v] << endl; + //cout << variables[v] << " is " << variableValues[v] << endl; return 0; } } @@ -253,29 +398,35 @@ int evalEqu(vector str, vector& variables, vector& varia else if (str[1] == "/=") globalVariableValues[v] = EvalExpression(variableValues[v] + "/(" + unWrapVec(vector(str.begin() + 2, str.end())) + ")", variables, variableValues); - cout << variables[v] << " is " << variableValues[v] << endl; + //cout << variables[v] << " is " << variableValues[v] << endl; return 0; } } } -int ProcessLine(vector> words, int lineNum, vector& variables, vector& variableValues) +string ProcessLine(vector> words, int lineNum, vector& variables, vector& variableValues) { if (words[lineNum][0][0] == '/' && words[lineNum][0][1] == '/') - return 0; + return ""; - if (words[lineNum][0] == "print") { - cout << EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variables, variableValues) << endl; - return 0; + if (words[lineNum][0] == "print") + { + cout << StringRaw(EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variables, variableValues)) << endl; + return ""; + } + + if (words[lineNum][0] == "return") { + //cout << StringRaw(EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variables, variableValues)) << endl; + return EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variables, variableValues); } // Iterate through all functions for (int t = 0; t < (int)functions.size(); t++) { - if (words[lineNum][0] == split(functions[t], ' ')[0]) + if (split(words[lineNum][0], '(')[0] == split(functions[t], ' ')[0]) { - ExecuteFunction(words[lineNum][0], split(unWrapVec(rangeInVec(words[lineNum], 1, -1)), ',')); - return 0; + ExecuteFunction(split(functions[t], ' ')[0], VarValues(split(RMParenthesis(replace(unWrapVec(words[lineNum]), split(functions[t], ' ')[0], "")), ','), variables, variableValues)); + return ""; } } @@ -292,15 +443,15 @@ int ProcessLine(vector> words, int lineNum, vector& varia { evalEqu(vector(words[lineNum].begin() + 1, words[lineNum].end()), variables, variableValues); - return 0; + return ""; } } //Checks if it is variable variables.push_back(words[lineNum][0] + " " + words[lineNum][1]); variableValues.push_back(EvalExpression(unWrapVec(vector(words[lineNum].begin() + 3, words[lineNum].end())), variables, variableValues)); - cout << variables[(int)variables.size() - 1] << " is " << variableValues[(int)variableValues.size() - 1] << endl; - return 0; + //cout << variables[(int)variables.size() - 1] << " is " << variableValues[(int)variableValues.size() - 1] << endl; + return ""; } } // Second, iterate all existing variable names @@ -310,7 +461,7 @@ int ProcessLine(vector> words, int lineNum, vector& varia { evalEqu(vector(words[lineNum].begin(), words[lineNum].end()), variables, variableValues); - return 0; + return ""; } } // Gathers while loop contents @@ -348,7 +499,7 @@ int ProcessLine(vector> words, int lineNum, vector& varia ProcessLine(words, lineNum, variables, variableValues); } } - return 0; + return ""; } // Gathers if statement contents if (words[lineNum][0] == "if") @@ -385,13 +536,13 @@ int ProcessLine(vector> words, int lineNum, vector& varia ProcessLine(words, lineNum, variables, variableValues); } } - return 0; + return ""; } - return 0; + return ""; } -int ExecuteFunction(string functionName, vector inputVarVals) +string ExecuteFunction(string functionName, vector inputVarVals) { //vector inputVarVals = split(replace(inVals, " ", ""), ','); @@ -413,7 +564,7 @@ int ExecuteFunction(string functionName, vector inputVarVals) { variables.push_back(trim(functionNameParts[i])); variableValues.push_back(EvalExpression(inputVarVals[i], variables, variableValues)); - cout << variables[(int)variables.size() - 1] << " is " << variableValues[(int)variableValues.size() - 1] << endl; + //cout << variables[(int)variables.size() - 1] << " is " << variableValues[(int)variableValues.size() - 1] << endl; } vector> words; for (int i = 0; i < (int)functionLines.size(); i++) @@ -422,9 +573,20 @@ int ExecuteFunction(string functionName, vector inputVarVals) //Iterate through all lines in function for (int lineNum = 0; lineNum < (int)functionLines.size(); lineNum++) { - ProcessLine(words, lineNum, variables, variableValues); + string returnVal = ""; + try + { + string returnVal = ProcessLine(words, lineNum, variables, variableValues); + } + catch (const std::exception&) + { + cout << "\x1B[31mERROR: \'" << unWrapVec(words[lineNum]) << "\'\nIn function: " << functionName << "\nLine: " << lineNum << "\033[0m\t\t" << endl; + exit(1); + } + if (returnVal != "") + return returnVal; } - return 0; + return ""; } int parseSlang(string script) @@ -476,28 +638,38 @@ int parseSlang(string script) functionContents = removeTabs(functionContents, 1); functions.push_back(functName); functionValues.push_back(functionContents); - cout << functName << " is \n" << Vec2Str(functionContents) << endl << endl; + //cout << functName << " is \n" << Vec2Str(functionContents) << endl << endl; } //Checks if it is variable else { globalVariables.push_back(words[lineNum][0] + " " + words[lineNum][1]); globalVariableValues.push_back((string)words[lineNum][3]); - cout << words[lineNum][1] << " is " << words[lineNum][3] << endl; + //cout << words[lineNum][1] << " is " << words[lineNum][3] << endl; } } // Executes main, which is the starting function - ExecuteFunction("Main", vector {"\"hi\"", "7"}); + ExecuteFunction("Main", vector {"\"hi\"", "0"}); return 0; } int main(int argc, char* argv[]) { - ifstream t("../Slang/script.slg"); + ifstream builtin("../Slang/builtin.slg"); + stringstream builtinString; + builtinString << builtin.rdbuf(); + + GetBuiltins(builtinString.str()); + functions = builtinFunctions; + functionValues = builtinFunctionValues; + globalVariables = builtinVars; + globalVariableValues = builtinVarVals; + + ifstream script("../Slang/script.slg"); stringstream scriptString; - scriptString << t.rdbuf(); + scriptString << script.rdbuf(); while (true) { system("pause"); diff --git a/Slang/Slang.vcxproj b/Slang/Slang.vcxproj index 3dae791..2eac382 100644 --- a/Slang/Slang.vcxproj +++ b/Slang/Slang.vcxproj @@ -145,11 +145,13 @@ + + diff --git a/Slang/Slang.vcxproj.filters b/Slang/Slang.vcxproj.filters index baa8bb7..04c9c74 100644 --- a/Slang/Slang.vcxproj.filters +++ b/Slang/Slang.vcxproj.filters @@ -35,8 +35,12 @@ Source Files + + Source Files + + \ No newline at end of file diff --git a/Slang/builtin.h b/Slang/builtin.h new file mode 100644 index 0000000..b56a2bf --- /dev/null +++ b/Slang/builtin.h @@ -0,0 +1,92 @@ +#ifndef BUILTIN_H +#define BUILTIN_H + +#include +#include +#include +#include +#include +#include +#include "strops.h" + +using namespace std; + +vector types = { "int", "float", "string", "bool", "void", "null" }; + +vector builtinFunctions; +vector> builtinFunctionValues; +vector builtinVars; +vector builtinVarVals; + +int GetBuiltins(string script) +{ + script = replace(script, " ", "\t"); + + vector lines = split(script, '\n'); + vector> words; + for (int i = 0; i < (int)lines.size(); i++) + { + words.push_back(split(lines[i], ' ')); + } + + // Go through entire script and iterate through all types to see if line is a + // function declaration, then store it with it's value + for (int lineNum = 0; lineNum < (int)words.size(); lineNum++) + for (int t = 0; t < (int)types.size(); t++) + if (words[lineNum][0] == types[t]) + { + //Checks if it is function + if (words[lineNum][(int)words[lineNum].size() - 1][(int)words[lineNum][(int)words[lineNum].size() - 1].size() - 1] == ')') + { + vector functionContents; + + string functName; + for (int w = 1; w < (int)words[lineNum].size(); w++) { + if (w < (int)words[lineNum].size() - 1) + { + functName += replace(replace(words[lineNum][w], "(", " "), ")", "") + " "; + } + else + { + functName += replace(replace(words[lineNum][w], "(", " "), ")", ""); + } + } + + int numOfBrackets = 1; + for (int p = lineNum + 2; p < (int)words.size(); p++) + { + numOfBrackets += countInVector(words[p], "{") - countInVector(words[p], "}"); + if (numOfBrackets == 0) + break; + functionContents.push_back(""); + for (int w = 0; w < (int)words[p].size(); w++) + { + functionContents[(int)functionContents.size() - 1] += words[p][w] + " "; + } + } + functionContents = removeTabs(functionContents, 1); + builtinFunctions.push_back(functName); + builtinFunctionValues.push_back(functionContents); + } + //Checks if it is variable + else + { + builtinVars.push_back(words[lineNum][0] + " " + words[lineNum][1]); + builtinVarVals.push_back((string)words[lineNum][3]); + //cout << words[lineNum][1] << " is " << words[lineNum][3] << endl; + } + } + + return 0; +} + +string CPPFunction(string name, vector args) +{ + cout << name << " -- " << args[0] << endl; + if (name == "CPP.Math.Sin") + return to_string(sin(stof(args[0]))); + + return ""; +} + +#endif \ No newline at end of file diff --git a/Slang/builtin.slg b/Slang/builtin.slg new file mode 100644 index 0000000..0c9078e --- /dev/null +++ b/Slang/builtin.slg @@ -0,0 +1,7 @@ +float pi = 3.14159265358979 + +float Sin(float input) +{ + float out = CPP.Math.Sin(input) + return out +} \ No newline at end of file diff --git a/Slang/script.slg b/Slang/script.slg index 267427e..9373f28 100644 --- a/Slang/script.slg +++ b/Slang/script.slg @@ -8,17 +8,19 @@ void Next(string in, string sin) print in print sin print green + return "awe" } -void Main(string input, int in2) +void Main(string input, int in) { + print pi int x = 1 int a = 0 int b = 1 print input - print in2 + print in int k = 0 @@ -26,15 +28,10 @@ void Main(string input, int in2) { int k = 1 / (1+2.71828^-x) print k - print "X is " + x - string str = x - - // str= 0+(" :: ") - str += " :: " - str += k + float s = Sin(x) + print "Sin is " + s x += 10 - print str } - Next "seen", "bop" + print Next("seen", "bop") } \ No newline at end of file diff --git a/Slang/strops.cpp b/Slang/strops.cpp index 2a8b19f..1cd112c 100644 --- a/Slang/strops.cpp +++ b/Slang/strops.cpp @@ -25,6 +25,9 @@ string trim(const string& s) { } vector split(string str, char del) { + if (count(str, del) == 0) + return vector{str}; + // declaring temp string to store the curr "word" upto del string temp = ""; vector splitWords;