|
|
@@ -33,6 +33,14 @@ std::string typeOfStorage(js_internal_storage *storage) { |
|
|
|
return "unknown"; |
|
|
|
} |
|
|
|
|
|
|
|
bool isStrInt(std::string s) { |
|
|
|
return (s.find_first_not_of( "0123456789" ) == std::string::npos); |
|
|
|
} |
|
|
|
|
|
|
|
bool isStrRational(std::string s) { |
|
|
|
return (s.find_first_not_of( "0123456789." ) == std::string::npos); |
|
|
|
} |
|
|
|
|
|
|
|
bool jsIsFalse(js_internal_storage *generic) { |
|
|
|
std::string type = typeOfStorage(generic); |
|
|
|
if (type == "string") { |
|
|
@@ -291,14 +299,42 @@ std::vector<std::string> jsGetTokens(const std::string &source, const size_t sta |
|
|
|
return tokens; |
|
|
|
} |
|
|
|
|
|
|
|
js_internal_storage *jsFunctionCall(std::string funcName, js_function *func, std::string params, js_function &scope) { |
|
|
|
js_internal_storage *jsFunctionCall(std::string funcName, js_function *func, std::string paramsStr, js_function &scope) { |
|
|
|
if (isConstruct(funcName)) { |
|
|
|
return executeConstruct(funcName, params, scope); |
|
|
|
return executeConstruct(funcName, paramsStr, scope); |
|
|
|
} else { |
|
|
|
if (func == nullptr) { |
|
|
|
std::cout << "passed null into jsFunctionCall\n"; |
|
|
|
std::cout << "HALT passed null into jsFunctionCall" << std::endl; |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
// what about the params? |
|
|
|
if (paramsStr != "") { |
|
|
|
// FIXME: need to parse them ... |
|
|
|
std::vector<std::string> opens, closes; |
|
|
|
opens.push_back("{"); |
|
|
|
opens.push_back("'"); |
|
|
|
opens.push_back("\""); |
|
|
|
closes.push_back("}"); |
|
|
|
closes.push_back("'"); |
|
|
|
closes.push_back("\""); |
|
|
|
auto params = parseSepButNotBetween(paramsStr, ",", opens, closes); |
|
|
|
// get the prototype, so we know where to assign this variables into the scope |
|
|
|
//std::cout << "parameters supported [" << func->parameters.size() << "]" << std::endl; |
|
|
|
uint16_t i = 0; |
|
|
|
for(auto it = func->parameters.begin(); it != func->parameters.end(); ++it) { |
|
|
|
std::string value = ""; |
|
|
|
if (i < params.size()) { |
|
|
|
value = params[i]; |
|
|
|
} |
|
|
|
js_internal_storage *storeVal = doExpression(scope, value); |
|
|
|
std::cout << "Assigning prototype[" << *it << "] = [" << value << "]" << std::endl; |
|
|
|
scope.locals.value[*it] = storeVal; |
|
|
|
assignfile << *it << "=" << value << "\n"; |
|
|
|
i++; |
|
|
|
} |
|
|
|
// well it's implemented, just not sure how well |
|
|
|
//std::cout << "HALT/writeme! jsFunctionCall has params[" << paramsStr << "]!" << std::endl; |
|
|
|
} |
|
|
|
return jsParseTokens(func->tokens, &scope); |
|
|
|
} |
|
|
|
} |
|
|
@@ -621,6 +657,31 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// handle assignemnt to stack |
|
|
|
if (trimmedToken == "=") { |
|
|
|
state = 6; |
|
|
|
continue; |
|
|
|
} |
|
|
|
/* |
|
|
|
if (trimmedToken[0] == '[') { |
|
|
|
// like [0] potentially longer? |
|
|
|
size_t n = std::count(trimmedToken.begin(), trimmedToken.end(), ']'); |
|
|
|
if (n != 1) { |
|
|
|
std::cout << "we dont support multiple deindexes, write me\n"; |
|
|
|
} |
|
|
|
// deindex |
|
|
|
js_array *arr = dynamic_cast<js_array *>(stack); |
|
|
|
if (!arr) { |
|
|
|
std::cout << "we only deindex arrarys [" << typeOfStorage(stack) << "], write me\n"; |
|
|
|
} else { |
|
|
|
|
|
|
|
} |
|
|
|
// don't try and deference (object.value) |
|
|
|
continue; |
|
|
|
} |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
// function name |
|
|
|
// ( |
|
|
|
if (trimmedToken == "(") { |
|
|
@@ -650,9 +711,13 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
|
|
|
|
// variable |
|
|
|
|
|
|
|
// object.property |
|
|
|
// object.property or object[property] or [0] |
|
|
|
// well first lets parse the key out |
|
|
|
// then resolve the key |
|
|
|
// then resolve the value |
|
|
|
bool deref = dereferenceHasBase(trimmedToken, &rootScope); |
|
|
|
if (deref) { |
|
|
|
// if trimmedToken is [0] it needs the stack... |
|
|
|
js_internal_storage *dereferenceTest = dereferenceObject(trimmedToken, &rootScope); |
|
|
|
if (dereferenceTest) { |
|
|
|
if (typeOfStorage(dereferenceTest)=="func") { |
|
|
@@ -697,6 +762,8 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
// number constant |
|
|
|
bool allDigits = isStrRational(trimmedToken); |
|
|
|
/* |
|
|
|
bool allDigits = true; |
|
|
|
for(auto it2 : trimmedToken) { |
|
|
|
if (it2 >= '0' && it2 <= '9') { |
|
|
@@ -707,14 +774,16 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
*/ |
|
|
|
if (allDigits) { |
|
|
|
js_number *jnum = new js_number; |
|
|
|
// FIXME: float double support |
|
|
|
jnum->value = std::stoi(trimmedToken); |
|
|
|
std::cout << "allDigits value[" << trimmedToken << "] => jnum[" << jnum->value << "]\n"; |
|
|
|
stack = jnum; |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
js_internal_storage **isVar = getObjectKeyPointer(it, &rootScope); |
|
|
|
if (isVar != nullptr) { |
|
|
|
std::cout << "isVar [" << isVar << "]\n"; |
|
|
@@ -758,6 +827,7 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
rootScope.locals.value[remainingExpr] = new js_internal_storage; |
|
|
|
} |
|
|
|
stack = rootScope.locals.value[remainingExpr]; |
|
|
|
|
|
|
|
/* |
|
|
|
rootScope.locals.value[remainingExpr] = new js_internal_storage; |
|
|
|
js_internal_storage *exprRes = doExpression(rootScope, remainingExpr); |
|
|
@@ -779,7 +849,7 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (state == 1) { |
|
|
|
} else if (state == 1) { // call function? |
|
|
|
// in func call, double check the ( |
|
|
|
if (it == "(") { |
|
|
|
state = 2; |
|
|
@@ -789,10 +859,10 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
stack = callFunc; |
|
|
|
state = 0; |
|
|
|
} |
|
|
|
} else if (state == 2) { |
|
|
|
} else if (state == 2) { // start function call? |
|
|
|
params = it; |
|
|
|
state = 3; |
|
|
|
} else if (state == 3) { |
|
|
|
} else if (state == 3) { // finish function call |
|
|
|
// in func call, double check the ) |
|
|
|
if (it == ")") { |
|
|
|
/* |
|
|
@@ -815,14 +885,14 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
stack = callFunc; |
|
|
|
state = 0; |
|
|
|
} |
|
|
|
} else if (state == 4) { |
|
|
|
} else if (state == 4) { // NOT operator |
|
|
|
js_internal_storage *expRes = doExpression(rootScope, it); |
|
|
|
// invert expRes; |
|
|
|
js_bool *jb = new js_bool; |
|
|
|
jb->value = !jsIsFalse(expRes); |
|
|
|
stack = jb; |
|
|
|
state = 0; |
|
|
|
} else if (state == 5) { |
|
|
|
} else if (state == 5) { // JSON |
|
|
|
/* |
|
|
|
js_function *objectScope = new js_function; |
|
|
|
js_object *newObject = new js_object; |
|
|
@@ -840,6 +910,9 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
stack = jsGetObject(rootScope, it); |
|
|
|
std::cout << "doExpression getObject got [" << stack << "]\n"; |
|
|
|
state = 0; |
|
|
|
} else if (state == 6) { // stack = |
|
|
|
std::cout << "State 6 = got [" << it << "]\n"; |
|
|
|
params += it; |
|
|
|
} else { |
|
|
|
std::cout << "doExpression unknown state[" << std::to_string(state) << "]\n"; |
|
|
|
} |
|
|
@@ -851,6 +924,14 @@ js_internal_storage *doExpression(js_function &rootScope, std::string token) { |
|
|
|
std::cout << "doExpressionEND1 - stack is [" << stack << "] will now have to set it to [" << callFunc << "]\n"; |
|
|
|
stack = callFunc; |
|
|
|
state = 0; |
|
|
|
} else |
|
|
|
if (state == 6) { |
|
|
|
std::cout << "Finishing state 6 [" << params << "]\n"; |
|
|
|
std::cout << "Store result in [" << typeOfStorage(stack) << "]\n"; |
|
|
|
auto resStack = doExpression(rootScope, params); |
|
|
|
// store resStack where ever stack is pointing |
|
|
|
params = ""; |
|
|
|
state = 0; |
|
|
|
} |
|
|
|
if (state != 0) { |
|
|
|
std::cout << "doExpression final state[" << std::to_string(state) << "]\n"; |
|
|
@@ -1038,7 +1119,7 @@ size_t getNextExpression(const std::string source, const size_t start) { |
|
|
|
size_t parenLevel = 0; |
|
|
|
size_t stateStart = 0; |
|
|
|
for (size_t cursor = start; cursor < source.length(); cursor++) { |
|
|
|
std::cout << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression(" << getNextExpressionLevel << ") scanning[" << source[cursor] << "] at[" << cursor << "/" << source.length() << "] state[" << std::to_string(state) << "] parenLevel[" << parenLevel << "]\n"; |
|
|
|
//std::cout << std::string(getNextExpressionLevel * 2, ' ') << "getNextExpression(" << getNextExpressionLevel << ") scanning[" << source[cursor] << "] at[" << cursor << "/" << source.length() << "] state[" << std::to_string(state) << "] parenLevel[" << parenLevel << "]\n"; |
|
|
|
switch(state) { |
|
|
|
case 0: |
|
|
|
// start function call |
|
|
@@ -1342,7 +1423,9 @@ js_function *makeFunctionFromString(const std::string body, const std::string pr |
|
|
|
std::cout << "makeFunctionFromString [" << prototype << "][" << body << "]\n"; |
|
|
|
js_function *func = new js_function; |
|
|
|
func->tokens = jsGetTokens(body, 0); |
|
|
|
// FIXME: needs to be smarter |
|
|
|
func->parameters = split(prototype, ','); |
|
|
|
//for(auto it = func->parameters.begin(); it != func->) |
|
|
|
if (!func->tokens.size()) { |
|
|
|
std::cout << "empty function?\n"; |
|
|
|
} |
|
|
@@ -1355,7 +1438,7 @@ js_array *jsGetArray(js_function &rootScope, std::string token) { |
|
|
|
js_array *jsArr = new js_array; |
|
|
|
parseJSON(*objectScope, token); |
|
|
|
for(auto it2 : objectScope->locals.value) { |
|
|
|
jsArr->value.push_back(*it2.second); |
|
|
|
jsArr->value.push_back(it2.second); |
|
|
|
} |
|
|
|
return jsArr; |
|
|
|
} |
|
|
@@ -1820,6 +1903,7 @@ void parseJSON(js_function &rootScope, std::string token) { |
|
|
|
} |
|
|
|
|
|
|
|
// return value is if there was any error (false for error, true for no error) |
|
|
|
// actually assignments are expressions |
|
|
|
int doAssignmentLevel = 0; |
|
|
|
bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
doAssignmentLevel++; |
|
|
@@ -2168,6 +2252,7 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
std::cout << std::string(doAssignmentLevel * 2, ' ') << "doAssignment expression(" << doAssignmentLevel << ") token[" << it << "]" << std::to_string(state) << std::endl; |
|
|
|
// default: put token in left, get op (usually =) and then get right side |
|
|
|
std::string trimmedToken = trim(it); |
|
|
|
if (trimmedToken == "") continue; // whitespace should be meaningless |
|
|
|
if (state==0) { |
|
|
|
negate = false; |
|
|
|
prototype = ""; |
|
|
@@ -2193,15 +2278,26 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
std::cout << std::string(doAssignmentLevel * 2, ' ') << "doAssignment - function expr start Adjust left[" << left << "] to [" << left.substr(0, cursor) << "]\n"; |
|
|
|
state = 3; |
|
|
|
} |
|
|
|
if (trimmedToken == "?") { |
|
|
|
std::cout << "Ternany" << std::endl; |
|
|
|
// FIXME: our current value should determine what expr we replace our value with |
|
|
|
state = 11; // ternary operator |
|
|
|
continue; |
|
|
|
} |
|
|
|
// most likely a function call |
|
|
|
// but also can be an expression |
|
|
|
// (function() {}()) |
|
|
|
// token will matter here |
|
|
|
// check for () |
|
|
|
if (trimmedToken == "(") { |
|
|
|
if (lastToken == "for") { |
|
|
|
std::cout << "not an assignment, fix doExpression\n"; |
|
|
|
} |
|
|
|
callFuncName = lastToken; |
|
|
|
state = 8; |
|
|
|
} |
|
|
|
} else if (state == 1) { |
|
|
|
// expression part of the assignment (the value part of what we're setting) |
|
|
|
if (trimmedToken == "") continue; // skip empties, don't fire the assignment too early |
|
|
|
if (it == " ") continue; // skip empties, don't fire the assignment too early |
|
|
|
if (trimmedToken == "!") continue; // valid expression |
|
|
@@ -2236,13 +2332,18 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
if (storage) { |
|
|
|
// state 1 can be an expression that we need to push the result onto the stack for && || |
|
|
|
stack = storage; |
|
|
|
|
|
|
|
// if it's a function value, it's a function naming (var bob = func), not a call |
|
|
|
/* |
|
|
|
js_function *funcTest = dynamic_cast<js_function*>(storage); |
|
|
|
if (funcTest) { |
|
|
|
std::cout << "assigning " << trimmedToken << " to some value" << std::endl; |
|
|
|
callFuncName = trimmedToken; |
|
|
|
callFunc = funcTest; |
|
|
|
state = 9; |
|
|
|
continue; |
|
|
|
} |
|
|
|
*/ |
|
|
|
std::string tLeft = trim(left); |
|
|
|
if (tLeft[0]=='"' && tLeft[tLeft.length() - 1]=='"') { |
|
|
|
//std::cout << "dequoting[" << tLeft << "]" << std::endl; |
|
|
@@ -2257,6 +2358,9 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
alreadySet = true; |
|
|
|
*key = storage; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// no dot |
|
|
|
std::cout << "Does tLeft[" << tLeft << "] has .?" << std::endl; |
|
|
|
} |
|
|
|
if (!alreadySet) { |
|
|
|
std::cout << "doAssignment final assign[" << tLeft << "] of type[" << typeOfStorage(storage) << "] storageFalse[" << jsIsFalse(storage) <<"] scope[" << &rootScope << "]\n"; |
|
|
@@ -2264,6 +2368,11 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
jsDisplayScope(&rootScope, 0); |
|
|
|
left = ""; // reset left |
|
|
|
assignfile << tLeft << "=" << it << "\n"; |
|
|
|
} else { |
|
|
|
std::cout << "doAssignment final re-assigned[" << tLeft << "] of type[" << typeOfStorage(storage) << "] storageFalse[" << jsIsFalse(storage) <<"] scope[" << &rootScope << "]" << std::endl; |
|
|
|
rootScope.locals.value[tLeft] = storage; |
|
|
|
left = ""; // reset left |
|
|
|
assignfile << tLeft << "=" << it << "\n"; |
|
|
|
} |
|
|
|
} else { |
|
|
|
std::cout << std::string(doAssignmentLevel * 2, ' ') << "HALT can't get value from [" << it << "]\n"; |
|
|
@@ -2383,8 +2492,24 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
if (trimmedToken == ")") { |
|
|
|
state = 0; // reset state |
|
|
|
} else { |
|
|
|
// call params |
|
|
|
std::cout << std::string(doAssignmentLevel * 2, ' ') << "HALT need to parse these params[" << it << "]\n"; |
|
|
|
// call params |
|
|
|
// we pass the params str to jsFunctionCall |
|
|
|
|
|
|
|
//js_internal_storage *paramValue = doExpression(rootScope, trimmedToken); |
|
|
|
// actually call function? |
|
|
|
// resolve func by name |
|
|
|
std::cout << "calling function [" << callFuncName << "](" << params << ")\n"; |
|
|
|
|
|
|
|
js_internal_storage *func = jsLocateKey(&rootScope, callFuncName); |
|
|
|
if (!func) { |
|
|
|
std::cout << "function 404[" << callFuncName << "]\n"; |
|
|
|
} |
|
|
|
callFunc = dynamic_cast<js_function *>(func); |
|
|
|
if (!callFunc) { |
|
|
|
std::cout << "found but not a function[" << callFuncName << "]\n"; |
|
|
|
} |
|
|
|
js_internal_storage *storage = jsFunctionCall(callFuncName, callFunc, trimmedToken, rootScope); |
|
|
|
std::cout << std::string(doAssignmentLevel * 2, ' ') << "HALT need to parse these params[" << it << "]\n"; |
|
|
|
} |
|
|
|
} else if (state == 9) { // are we a function call with return value, or assigning a function reference |
|
|
|
js_internal_storage *storage = nullptr; |
|
|
@@ -2460,13 +2585,24 @@ bool doAssignment(js_function &rootScope, std::string token) { |
|
|
|
// collect params |
|
|
|
params = trimmedToken; |
|
|
|
} |
|
|
|
} else if (state == 11) { // lastToken ? expr1 : expr2 |
|
|
|
std::cout << "next token: [" << trimmedToken << "]" << std::endl; |
|
|
|
state = 12; |
|
|
|
} else if (state == 12) { // : expr2 |
|
|
|
if (trimmedToken == ":") { |
|
|
|
state = 13; |
|
|
|
} else { |
|
|
|
std::cout << "need to handle: [" << trimmedToken << "]" << std::endl; |
|
|
|
} |
|
|
|
} else if (state == 13) { // expr2 |
|
|
|
std::cout << "final token: [" << trimmedToken << "]" << std::endl; |
|
|
|
} |
|
|
|
// { starts JSON capture (should be exactly one block before the } token) |
|
|
|
// you create a scope for that variable and recurse |
|
|
|
lastToken = it; |
|
|
|
} |
|
|
|
std::cout << std::string(doAssignmentLevel * 2, ' ') << "expression end, state " << std::to_string(state) << std::endl << std::endl; |
|
|
|
//displayScope(&rootScope, 0); |
|
|
|
//jsDisplayScope(&rootScope, 0); |
|
|
|
/* |
|
|
|
auto hasTripleEqual = token.find("==="); |
|
|
|
auto hasDoubleEqual = std::string::npos; |
|
|
@@ -2595,6 +2731,58 @@ bool dereferenceHasBase(const std::string input, const js_function *scope) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// detect stirng constants, rationals and variables |
|
|
|
js_internal_storage *resolveStringToKey(const std::string key, js_function &scope) { |
|
|
|
char lastChar = key[key.length() - 1]; |
|
|
|
if (isStrRational(key)) { |
|
|
|
js_number *num = new js_number; |
|
|
|
num->value = std::stoi(key); |
|
|
|
return num; |
|
|
|
} else if((key[0] == '"' && lastChar == '"') || (key[0] == '\'' && lastChar == '\'')) { |
|
|
|
js_string *str = new js_string; |
|
|
|
str->value = key.substr(1, key.length() - 2); |
|
|
|
return str; |
|
|
|
} else { |
|
|
|
// get variable's value |
|
|
|
return doExpression(scope, key); |
|
|
|
} |
|
|
|
return nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
/// look into stack for key (stack.key or stack[key]), think `return bob()[0]` where the stack isn't going to be in the string |
|
|
|
// key can be a stirng constant or a number |
|
|
|
// what about variable? you figure that before hand and deference it and get it's current value and pass that in |
|
|
|
js_internal_storage *dereferenceStorage(js_internal_storage *stack, const std::string key, const js_function *scope) { |
|
|
|
js_object *jobj = dynamic_cast<js_object*>(stack); |
|
|
|
if (jobj) { |
|
|
|
std::cout << "deindexObject bracket style [<" << key << ">\n"; |
|
|
|
if (jobj->value.find(key) != jobj->value.end()) { |
|
|
|
std::cout << "dereferenceObject - number[" << key << "] is inside base" << std::endl; |
|
|
|
return jobj->value[key]; // we will now point to this storage |
|
|
|
} |
|
|
|
} |
|
|
|
js_array *arr = dynamic_cast<js_array *>(stack); |
|
|
|
if (arr) { |
|
|
|
std::cout << "deindexArray bracket style [<" << key << ">\n"; |
|
|
|
int idx = std::stoi(key); |
|
|
|
if (arr->value.size() > idx) { |
|
|
|
return arr->value[idx]; |
|
|
|
} |
|
|
|
} |
|
|
|
js_string *str = dynamic_cast<js_string *>(stack); |
|
|
|
if (str) { |
|
|
|
std::cout << "deindexString bracket style [<" << key << ">\n"; |
|
|
|
int idx = std::stoi(key); |
|
|
|
if (str->value.size() > idx) { |
|
|
|
js_string *nchar = new js_string(); |
|
|
|
nchar->value = std::string(1, str->value[idx]); |
|
|
|
return nchar; |
|
|
|
} |
|
|
|
} |
|
|
|
std::cout << "Couldn't deindex [" << key <<"] on type [" << typeOfStorage(stack) << "]\n"; |
|
|
|
return nullptr; // or should we return a js_bool false? probably should return js_undefined |
|
|
|
} |
|
|
|
|
|
|
|
js_internal_storage *dereferenceObject(const std::string input, const js_function *scope) { |
|
|
|
// FIXME: too simple, catches quoted strings with . in them |
|
|
|
// FIXME: make sure we're not inside quotes |
|
|
@@ -2635,7 +2823,36 @@ js_internal_storage *dereferenceObject(const std::string input, const js_functio |
|
|
|
char lastChar = part2[part2.length() - 1]; |
|
|
|
// probably should run this through doExpression... |
|
|
|
// FIXME: "asdf" + var + "zxcv" |
|
|
|
if ((part2[0] == '"' && lastChar == '"') || (part2[0] == '\'' && lastChar == '\'')) { |
|
|
|
if (isStrRational(part2)) { |
|
|
|
// part2 is just an index because array[0] |
|
|
|
js_object *jobj = dynamic_cast<js_object*>(baseStorage); |
|
|
|
if (jobj) { |
|
|
|
std::cout << "deindexObject bracket style <" << baseObj << ">[<" << part2 << "><" << input.substr(end) << ">\n"; |
|
|
|
if (jobj->value.find(part2) != jobj->value.end()) { |
|
|
|
std::cout << "dereferenceObject - number[" << part2 << "] is inside base" << std::endl; |
|
|
|
return jobj->value[part2]; // we will now point to this storage |
|
|
|
} |
|
|
|
} |
|
|
|
js_array *arr = dynamic_cast<js_array *>(baseStorage); |
|
|
|
if (arr) { |
|
|
|
std::cout << "deindexArray bracket style <" << baseObj << ">[<" << part2 << "><" << input.substr(end) << ">\n"; |
|
|
|
int idx = std::stoi(part2); |
|
|
|
if (arr->value.size() > idx) { |
|
|
|
return arr->value[idx]; |
|
|
|
} |
|
|
|
} |
|
|
|
js_string *str = dynamic_cast<js_string *>(baseStorage); |
|
|
|
if (str) { |
|
|
|
std::cout << "deindexString bracket style <" << baseObj << ">[<" << part2 << "><" << input.substr(end) << ">\n"; |
|
|
|
int idx = std::stoi(part2); |
|
|
|
if (str->value.size() > idx) { |
|
|
|
js_string *nchar = new js_string(); |
|
|
|
nchar->value = std::string(1, str->value[idx]); |
|
|
|
return nchar; |
|
|
|
} |
|
|
|
} |
|
|
|
std::cout << "Couldn't deindex [" << part2 <<"] on type [" << typeOfStorage(baseStorage) << "] baseObj[" << baseObj << "] lastChar[" << input.substr(end) << "]\n"; |
|
|
|
} else if ((part2[0] == '"' && lastChar == '"') || (part2[0] == '\'' && lastChar == '\'')) { |
|
|
|
js_object *jobj = dynamic_cast<js_object*>(baseStorage); |
|
|
|
if (jobj) { |
|
|
|
std::cout << "dereferenceObject bracket style <" << baseObj << ">[<" << part2 << "><" << input.substr(end) << ">\n"; |
|
|
@@ -2725,9 +2942,70 @@ js_internal_storage *jsParseTokens(const std::vector<std::string> &tokens, js_fu |
|
|
|
// now execute remaining code |
|
|
|
// FIXME: there should be no expressions after an if statement |
|
|
|
js_internal_storage *lastRes = doExpression(*scope, lastToken); |
|
|
|
// FIXME: what do we with lastRes, do we have a stack? |
|
|
|
} |
|
|
|
//std::cout << "HALT if not implemented" << std::endl; |
|
|
|
//return nullptr; |
|
|
|
} else if (ttoken.substr(0, 3)=="for") { |
|
|
|
std::cout << "ForToken[" << ttoken << "]\n"; |
|
|
|
|
|
|
|
// FIXME: detect for in |
|
|
|
|
|
|
|
size_t pos = findClosing(ttoken, 0, '(', ')'); |
|
|
|
std::string afterFor = ttoken.substr(4, pos - 4); // -4 because we started at 4 (it's a size, not pos) but won't include ( or ) |
|
|
|
std::cout << "afterFor[" << afterFor << "]\n"; |
|
|
|
|
|
|
|
std::string forScope = ttoken.substr(pos + 2); |
|
|
|
std::cout << "forScope[" << forScope << "]\n"; |
|
|
|
|
|
|
|
|
|
|
|
// good idea but getNextExpression goes up to first comma (var x,y) and we need to first ; |
|
|
|
/* |
|
|
|
size_t end = getNextExpression(afterFor, 0); // works great so far |
|
|
|
//end = ifStr.find(')'); |
|
|
|
std::string forStages = afterFor.substr(0, end); |
|
|
|
std::cout << "initialization[" << forStages << "]\n"; |
|
|
|
|
|
|
|
size_t end2 = getNextExpression(afterFor, end); // works great so far |
|
|
|
std::string forStages2 = afterFor.substr(end, end2); |
|
|
|
std::cout << "condition[" << forStages2 << "]\n"; |
|
|
|
|
|
|
|
//size_t end3 = getNextExpression(afterFor, end2); // works great so far |
|
|
|
std::string forStages3 = afterFor.substr(end2); |
|
|
|
std::cout << "iterator[" << forStages3 << "]\n"; |
|
|
|
*/ |
|
|
|
|
|
|
|
// get initializer, condition and iterator |
|
|
|
std::vector<std::string> opens, closes; |
|
|
|
opens.push_back("("); |
|
|
|
opens.push_back("'"); |
|
|
|
opens.push_back("\""); |
|
|
|
closes.push_back(")"); |
|
|
|
closes.push_back("'"); |
|
|
|
closes.push_back("\""); |
|
|
|
auto varList = parseSepButNotBetween(afterFor, ";", opens, closes); |
|
|
|
if (varList.size() < 3) { |
|
|
|
std::cout << "HALT/badjs - not enough params for FOR loop\n"; |
|
|
|
} |
|
|
|
std::string initialization = varList[0]; |
|
|
|
std::string condition = varList[1]; |
|
|
|
std::string iterator = varList[2]; |
|
|
|
std::cout << "initialization[" << initialization << "]\n"; |
|
|
|
std::cout << "condition[" << condition << "]\n"; |
|
|
|
std::cout << "iterator[" << iterator << "]\n"; |
|
|
|
|
|
|
|
// FIXME: we probably should populate this current scope but nest a new one |
|
|
|
doExpression(*scope, initialization); // for initialization ignores the return value of it |
|
|
|
js_internal_storage *condRes = doExpression(*scope, condition); |
|
|
|
while(!jsIsFalse(condRes)) { |
|
|
|
// run content... |
|
|
|
// run jsParseTokens forScope |
|
|
|
// FIXME: handle break / return |
|
|
|
doExpression(*scope, iterator); // for iterator ignores the return value of it |
|
|
|
condRes = doExpression(*scope, condition); // check condition again |
|
|
|
} |
|
|
|
|
|
|
|
std::cout << "HALT writeme! for loop" << std::endl; |
|
|
|
} else if (ttoken.substr(0, 3)=="var") { |
|
|
|
std::string listStr = it.substr(3); |
|
|
|
// FIXME: , in quotes or {} (JSON) <= top priority for 4chan |
|
|
@@ -2796,16 +3074,22 @@ js_internal_storage *jsParseTokens(const std::vector<std::string> &tokens, js_fu |
|
|
|
// find { (func start) |
|
|
|
end = defStr.find('{'); |
|
|
|
defStr = defStr.substr(end + 1, defStr.size() - 2); // from { to the end |
|
|
|
|
|
|
|
js_function *newFunc = makeFunctionFromString(defStr, prototype, scope); |
|
|
|
|
|
|
|
/* |
|
|
|
//std::cout << "jsParseTokens Function Declartion start[" << defStr[0] << "] last[" << defStr[defStr.length() - 1] << "]\n"; |
|
|
|
auto funcTokens = jsGetTokens(defStr, 0); |
|
|
|
//std::cout << "function [" << funcName << "] prototype [" << prototype << "] has [" << funcTokens.size() << "] tokens" << std::endl; |
|
|
|
// __netrunner_function_definition is 31 chars |
|
|
|
//scope->variables[funcName] = "__netrunner_function_definition = { prototype: \"" + prototype + "\", code: \"" + defStr + "\" }"; |
|
|
|
js_function *newFunc = new js_function; |
|
|
|
newFunc->parameters.push_back(prototype); |
|
|
|
newFunc->tokens = funcTokens; |
|
|
|
newFunc->parentScope = scope; |
|
|
|
*/ |
|
|
|
scope->locals.value[funcName] = newFunc; |
|
|
|
execfile << "function declaration [" << funcName << "](" << prototype << ") tokens[" << funcTokens.size() << "]\n"; |
|
|
|
execfile << "function declaration [" << funcName << "](" << prototype << ") tokens[" << newFunc->tokens.size() << "]\n"; |
|
|
|
} else if (ttoken.substr(0, 6)=="return") { |
|
|
|
std::string afterReturn = ttoken.substr(7); |
|
|
|
return doExpression(*scope, afterReturn); |