Found a hilarious bug where numbers greater than 255 were truncated due to bitwise and with FF on all the shift ops
This commit is contained in:
parent
5b32dd7036
commit
93c6f9eda1
12
file.twss
12
file.twss
|
@ -1,11 +1,11 @@
|
||||||
<!--tws
|
<!--tws
|
||||||
d = list();
|
l = list();
|
||||||
d.add(5);
|
l.add(52);
|
||||||
d.add(6);
|
l.add(52);
|
||||||
d.add("Demi Lovato");
|
l.add(69);
|
||||||
for(i = 0;i<d.count;i++)
|
each(l)
|
||||||
{
|
{
|
||||||
print d.at(i);
|
print item;
|
||||||
print "\n";
|
print "\n";
|
||||||
}
|
}
|
||||||
-->
|
-->
|
|
@ -120,13 +120,25 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::variant<std::string,ObjectType> IttrType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::variant<Undefined,Null,ObjectType,std::string,int64_t,double,bool,char> ScriptType;
|
class IttrKVP {
|
||||||
|
public:
|
||||||
|
IttrType ittr;
|
||||||
|
int64_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::variant<Undefined,Null,ObjectType,IttrKVP,std::string,int64_t,double,bool,char> ScriptType;
|
||||||
|
class Ittr : public Object {
|
||||||
|
public:
|
||||||
|
IttrType ittr;
|
||||||
|
int64_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
inline bool Equals(ScriptType& left, ScriptType& right)
|
inline bool Equals(ScriptType& left, ScriptType& right)
|
||||||
{
|
{
|
||||||
|
@ -191,7 +203,6 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
}
|
}
|
||||||
if(std::holds_alternative<bool>(st))
|
if(std::holds_alternative<bool>(st))
|
||||||
{
|
{
|
||||||
std::cout << (std::get<bool>(st) ? "true" : "false") << std::endl;
|
|
||||||
return std::get<bool>(st);
|
return std::get<bool>(st);
|
||||||
}
|
}
|
||||||
if(std::holds_alternative<char>(st))
|
if(std::holds_alternative<char>(st))
|
||||||
|
@ -209,7 +220,12 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
inline std::string ConvertToString(ScriptType& st);
|
inline std::string ConvertToString(ScriptType& st);
|
||||||
inline std::string ConvertToString(ScriptType& st)
|
inline std::string ConvertToString(ScriptType& st)
|
||||||
{
|
{
|
||||||
|
if(std::holds_alternative<IttrKVP>(st))
|
||||||
|
{
|
||||||
|
auto v = IttrGetValue(st);
|
||||||
|
|
||||||
|
return IttrGetKey(st) + ": " + ConvertToString(v);
|
||||||
|
}
|
||||||
|
|
||||||
if(std::holds_alternative<Null>(st))
|
if(std::holds_alternative<Null>(st))
|
||||||
{
|
{
|
||||||
|
@ -460,6 +476,173 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline ScriptType CreateIttrFor(ScriptType& st)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<std::string>(st))
|
||||||
|
{
|
||||||
|
Ittr* ittr =new Ittr();
|
||||||
|
ittr->index = -1;
|
||||||
|
ittr->ittr = std::get<std::string>(st);
|
||||||
|
ObjectType t(ittr);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<ObjectType>(st))
|
||||||
|
{
|
||||||
|
auto ot = std::get<ObjectType>(st).data;
|
||||||
|
auto ls = dynamic_cast<List*>(ot);
|
||||||
|
auto dict = dynamic_cast<Dictionary*>(ot);
|
||||||
|
if(ls != nullptr)
|
||||||
|
{
|
||||||
|
Ittr* ittr=new Ittr();
|
||||||
|
ittr->index = -1;
|
||||||
|
ittr->ittr = ObjectType(ls);
|
||||||
|
ObjectType t(ittr);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if(dict != nullptr)
|
||||||
|
{
|
||||||
|
Ittr* ittr=new Ittr();
|
||||||
|
ittr->index = -1;
|
||||||
|
ittr->ittr = ObjectType(dict);
|
||||||
|
ObjectType t(ittr);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Null();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IttrMoveNext(ScriptType& st)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<ObjectType>(st))
|
||||||
|
{
|
||||||
|
auto objIttr = std::get<ObjectType>(st).data;
|
||||||
|
auto ittr = dynamic_cast<Ittr*>(objIttr);
|
||||||
|
if(ittr == nullptr) return false;
|
||||||
|
if(std::holds_alternative<std::string>(ittr->ittr))
|
||||||
|
{
|
||||||
|
std::string str = std::get<std::string>(ittr->ittr);
|
||||||
|
if(ittr->index >= -1 && ittr->index + 1 < str.size())
|
||||||
|
{
|
||||||
|
(ittr->index)++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<ObjectType>(ittr->ittr))
|
||||||
|
{
|
||||||
|
auto ot = std::get<ObjectType>(ittr->ittr).data;
|
||||||
|
auto ls = dynamic_cast<List*>(ot);
|
||||||
|
auto dict = dynamic_cast<Dictionary*>(ot);
|
||||||
|
|
||||||
|
if(ls != nullptr)
|
||||||
|
{
|
||||||
|
if(ittr->index >= -1 && ittr->index + 1 < ls->items.size())
|
||||||
|
{
|
||||||
|
(ittr->index)++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dict != nullptr)
|
||||||
|
{
|
||||||
|
if(ittr->index >= -1 && ittr->index + 1 < dict->items.size())
|
||||||
|
{
|
||||||
|
(ittr->index)++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ScriptType IttrCurrent(ScriptType& st)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<ObjectType>(st))
|
||||||
|
{
|
||||||
|
auto objIttr = std::get<ObjectType>(st).data;
|
||||||
|
auto ittr = dynamic_cast<Ittr*>(objIttr);
|
||||||
|
if(ittr == nullptr) return Null();
|
||||||
|
if(std::holds_alternative<std::string>(ittr->ittr))
|
||||||
|
{
|
||||||
|
std::string str = std::get<std::string>(ittr->ittr);
|
||||||
|
if(ittr->index >= 0 && ittr->index < str.size())
|
||||||
|
{
|
||||||
|
return str[ittr->index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(std::holds_alternative<ObjectType>(ittr->ittr))
|
||||||
|
{
|
||||||
|
auto ot = std::get<ObjectType>(ittr->ittr).data;
|
||||||
|
auto ls = dynamic_cast<List*>(ot);
|
||||||
|
auto dict = dynamic_cast<Dictionary*>(ot);
|
||||||
|
|
||||||
|
if(ls != nullptr)
|
||||||
|
{
|
||||||
|
if(ittr->index >= 0 && ittr->index < ls->items.size())
|
||||||
|
{
|
||||||
|
return ls->items[ittr->index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dict != nullptr)
|
||||||
|
{
|
||||||
|
if(ittr->index >= 0 && ittr->index < dict->items.size())
|
||||||
|
{
|
||||||
|
IttrKVP kvp;
|
||||||
|
kvp.index = ittr->index;
|
||||||
|
kvp.ittr = ittr->ittr;
|
||||||
|
return kvp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Null();
|
||||||
|
}
|
||||||
|
inline std::string IttrGetKey(ScriptType& st)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<IttrKVP>(st))
|
||||||
|
{
|
||||||
|
auto ittr = std::get<IttrKVP>(st);
|
||||||
|
|
||||||
|
if(std::holds_alternative<ObjectType>(ittr.ittr))
|
||||||
|
{
|
||||||
|
auto ot = std::get<ObjectType>(ittr.ittr).data;
|
||||||
|
auto dict = dynamic_cast<Dictionary*>(ot);
|
||||||
|
|
||||||
|
|
||||||
|
if(dict != nullptr)
|
||||||
|
{
|
||||||
|
if(ittr.index >= 0 && ittr.index < dict->items.size())
|
||||||
|
{
|
||||||
|
return dict->items[ittr.index].first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return std::string({});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ScriptType IttrGetValue(ScriptType& st)
|
||||||
|
{
|
||||||
|
if(std::holds_alternative<IttrKVP>(st))
|
||||||
|
{
|
||||||
|
auto ittr = std::get<IttrKVP>(st);
|
||||||
|
|
||||||
|
if(std::holds_alternative<ObjectType>(ittr.ittr))
|
||||||
|
{
|
||||||
|
auto ot = std::get<ObjectType>(ittr.ittr).data;
|
||||||
|
auto dict = dynamic_cast<Dictionary*>(ot);
|
||||||
|
|
||||||
|
|
||||||
|
if(dict != nullptr)
|
||||||
|
{
|
||||||
|
if(ittr.index >= 0 && ittr.index < dict->items.size())
|
||||||
|
{
|
||||||
|
return dict->items[ittr.index].second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Null();
|
||||||
|
}
|
||||||
inline ScriptType TypeOf(Environment* env, std::vector<ScriptType> args);
|
inline ScriptType TypeOf(Environment* env, std::vector<ScriptType> args);
|
||||||
class RootEnvironment : public Environment
|
class RootEnvironment : public Environment
|
||||||
{
|
{
|
||||||
|
@ -896,7 +1079,19 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
auto obj = std::get<ObjectType>(member).data;
|
auto obj = std::get<ObjectType>(member).data;
|
||||||
auto ls = dynamic_cast<List*>(obj);
|
auto ls = dynamic_cast<List*>(obj);
|
||||||
auto dict = dynamic_cast<Dictionary*>(obj);
|
auto dict = dynamic_cast<Dictionary*>(obj);
|
||||||
|
auto ittr = dynamic_cast<Ittr*>(obj);
|
||||||
|
if(ittr != nullptr)
|
||||||
|
{
|
||||||
|
if(key == "current")
|
||||||
|
{
|
||||||
|
return IttrCurrent(member);
|
||||||
|
}
|
||||||
|
if(key == "movenext")
|
||||||
|
{
|
||||||
|
return IttrMoveNext(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if(ls != nullptr)
|
if(ls != nullptr)
|
||||||
{
|
{
|
||||||
if(key == "add" && args.size() > 0)
|
if(key == "add" && args.size() > 0)
|
||||||
|
@ -1135,7 +1330,18 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
return (int64_t)str.size();
|
return (int64_t)str.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(std::holds_alternative<IttrKVP>(instance))
|
||||||
|
{
|
||||||
|
if(name == "key")
|
||||||
|
{
|
||||||
|
return IttrGetKey(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name == "value")
|
||||||
|
{
|
||||||
|
return IttrGetValue(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(std::holds_alternative<ObjectType>(instance))
|
if(std::holds_alternative<ObjectType>(instance))
|
||||||
{
|
{
|
||||||
auto inst = std::get<ObjectType>(instance).data;
|
auto inst = std::get<ObjectType>(instance).data;
|
||||||
|
@ -1352,14 +1558,14 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
|
|
||||||
if(ip + 8 <= bytecodeLength)
|
if(ip + 8 <= bytecodeLength)
|
||||||
{
|
{
|
||||||
uint64_t value = ((uint64_t)bytecode[ip++] << 56) & 0xFF;
|
uint64_t value = ((uint64_t)bytecode[ip++] << 56);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 48) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 48);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 40) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 40);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 32) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 32);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 24) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 24);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 16) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 16);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 8) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 8);
|
||||||
value |= (uint64_t)bytecode[ip++] & 0xFF;
|
value |= (uint64_t)bytecode[ip++];
|
||||||
|
|
||||||
stack.push((int64_t)value);
|
stack.push((int64_t)value);
|
||||||
}
|
}
|
||||||
|
@ -1369,14 +1575,14 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
{
|
{
|
||||||
if(ip + 8 <= bytecodeLength)
|
if(ip + 8 <= bytecodeLength)
|
||||||
{
|
{
|
||||||
uint64_t value = ((uint64_t)bytecode[ip++] << 56) & 0xFF;
|
uint64_t value = ((uint64_t)bytecode[ip++] << 56);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 48) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 48);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 40) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 40);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 32) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 32);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 24) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 24);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 16) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 16);
|
||||||
value |= ((uint64_t)bytecode[ip++] << 8) & 0xFF;
|
value |= ((uint64_t)bytecode[ip++] << 8);
|
||||||
value |= (uint64_t)bytecode[ip++] & 0xFF;
|
value |= (uint64_t)bytecode[ip++];
|
||||||
|
|
||||||
|
|
||||||
stack.push(*(double*)&value);
|
stack.push(*(double*)&value);
|
||||||
|
@ -1390,10 +1596,10 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
size_t len = (bytecode[ip++] << 24) & 0xFF;
|
size_t len = ((size_t)bytecode[ip++] << 24);
|
||||||
len |= (bytecode[ip++] << 16) & 0xFF;
|
len |= ((size_t)bytecode[ip++] << 16);
|
||||||
len |= (bytecode[ip++] << 8) & 0xFF;
|
len |= ((size_t)bytecode[ip++] << 8);
|
||||||
len |= bytecode[ip++] & 0xFF;
|
len |= (size_t)bytecode[ip++];;
|
||||||
|
|
||||||
if(ip + len <= bytecodeLength)
|
if(ip + len <= bytecodeLength)
|
||||||
{
|
{
|
||||||
|
@ -1549,10 +1755,10 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
size_t len = (bytecode[ip++] << 24) & 0xFF;
|
size_t len = ((size_t)bytecode[ip++] << 24);
|
||||||
len |= (bytecode[ip++] << 16) & 0xFF;
|
len |= ((size_t)bytecode[ip++] << 16);
|
||||||
len |= (bytecode[ip++] << 8) & 0xFF;
|
len |= ((size_t)bytecode[ip++] << 8);
|
||||||
len |= bytecode[ip++] & 0xFF;
|
len |= (size_t)bytecode[ip++];
|
||||||
if(len < bytecodeLength)
|
if(len < bytecodeLength)
|
||||||
ip = len;
|
ip = len;
|
||||||
else
|
else
|
||||||
|
@ -1569,10 +1775,10 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
size_t len = (bytecode[ip++] << 24) & 0xFF;
|
size_t len = ((size_t)bytecode[ip++] << 24);
|
||||||
len |= (bytecode[ip++] << 16) & 0xFF;
|
len |= ((size_t)bytecode[ip++] << 16);
|
||||||
len |= (bytecode[ip++] << 8) & 0xFF;
|
len |= ((size_t)bytecode[ip++] << 8);
|
||||||
len |= bytecode[ip++] & 0xFF;
|
len |= (size_t)bytecode[ip++];
|
||||||
if(len < bytecodeLength)
|
if(len < bytecodeLength)
|
||||||
{
|
{
|
||||||
auto v = Pop();
|
auto v = Pop();
|
||||||
|
@ -1588,7 +1794,12 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Instruction::ITTR:
|
||||||
|
{
|
||||||
|
auto ittr=Pop();
|
||||||
|
stack.push(CreateIttrFor(ittr));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Instruction::GETFIELD:
|
case Instruction::GETFIELD:
|
||||||
{
|
{
|
||||||
std::string name = PopString();
|
std::string name = PopString();
|
||||||
|
@ -1886,7 +2097,24 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EachNode : public Node {
|
||||||
|
public:
|
||||||
|
Node* item;
|
||||||
|
Node* list;
|
||||||
|
Node* body;
|
||||||
|
EachNode(Node* item,Node* list,Node* body)
|
||||||
|
{
|
||||||
|
this->item = item;
|
||||||
|
this->list = list;
|
||||||
|
this->body = body;
|
||||||
|
}
|
||||||
|
~EachNode()
|
||||||
|
{
|
||||||
|
delete item;
|
||||||
|
delete list;
|
||||||
|
delete body;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class FunctionDeclarationNode : public Node {
|
class FunctionDeclarationNode : public Node {
|
||||||
public:
|
public:
|
||||||
|
@ -2937,7 +3165,26 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
NextTokenIs(";");
|
NextTokenIs(";");
|
||||||
return new WhileNode(cond,body,true);
|
return new WhileNode(cond,body,true);
|
||||||
}
|
}
|
||||||
|
if(NextTokenIs("each"))
|
||||||
|
{
|
||||||
|
Ensure("(");
|
||||||
|
Node* list = ParseExpression();
|
||||||
|
Node* item = nullptr;
|
||||||
|
|
||||||
|
if(NextTokenIs(":"))
|
||||||
|
{
|
||||||
|
item = list;
|
||||||
|
list = ParseExpression();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item = new GetVariableExpression("item");
|
||||||
|
}
|
||||||
|
Ensure(")");
|
||||||
|
Node* body = ParseNode();
|
||||||
|
NextTokenIs(";");
|
||||||
|
return new EachNode(item,list,body);
|
||||||
|
}
|
||||||
if(NextTokenIs("func"))
|
if(NextTokenIs("func"))
|
||||||
{
|
{
|
||||||
Node* fn = ParseExpression();
|
Node* fn = ParseExpression();
|
||||||
|
@ -2984,6 +3231,10 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
return "double";
|
return "double";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(std::holds_alternative<IttrKVP>(item))
|
||||||
|
{
|
||||||
|
return "ittrkvp";
|
||||||
|
}
|
||||||
if(std::holds_alternative<bool>(item))
|
if(std::holds_alternative<bool>(item))
|
||||||
{
|
{
|
||||||
return "bool";
|
return "bool";
|
||||||
|
@ -3003,7 +3254,8 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
auto dict = dynamic_cast<Dictionary*>(ot);
|
auto dict = dynamic_cast<Dictionary*>(ot);
|
||||||
auto ifunc = dynamic_cast<InternalFunction*>(ot);
|
auto ifunc = dynamic_cast<InternalFunction*>(ot);
|
||||||
auto efunc = dynamic_cast<ExternalFunction*>(ot);
|
auto efunc = dynamic_cast<ExternalFunction*>(ot);
|
||||||
|
auto ittr = dynamic_cast<Ittr*>(ot);
|
||||||
|
if(ittr != nullptr) return "ittr";
|
||||||
if(ls != nullptr) return "list";
|
if(ls != nullptr) return "list";
|
||||||
if(dict != nullptr) return "dictionary";
|
if(dict != nullptr) return "dictionary";
|
||||||
if(ifunc != nullptr) return "internal_function";
|
if(ifunc != nullptr) return "internal_function";
|
||||||
|
@ -3276,6 +3528,7 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
|
|
||||||
std::string _cont = {};
|
std::string _cont = {};
|
||||||
|
|
||||||
|
std::stack<std::string> __eachs;
|
||||||
|
|
||||||
int jmpId = 0;
|
int jmpId = 0;
|
||||||
std::string NewJumpId()
|
std::string NewJumpId()
|
||||||
|
@ -3341,6 +3594,7 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
auto whileNode = dynamic_cast<WhileNode*>(n);
|
auto whileNode = dynamic_cast<WhileNode*>(n);
|
||||||
auto breakNode = dynamic_cast<BreakNode*>(n);
|
auto breakNode = dynamic_cast<BreakNode*>(n);
|
||||||
auto cont = dynamic_cast<ContinueNode*>(n);
|
auto cont = dynamic_cast<ContinueNode*>(n);
|
||||||
|
auto eachLoop = dynamic_cast<EachNode*>(n);
|
||||||
auto forLoop = dynamic_cast<ForNode*>(n);
|
auto forLoop = dynamic_cast<ForNode*>(n);
|
||||||
auto lOr = dynamic_cast<LogicalOrExpression*>(n);
|
auto lOr = dynamic_cast<LogicalOrExpression*>(n);
|
||||||
auto lAnd = dynamic_cast<LogicalAndExpression*>(n);
|
auto lAnd = dynamic_cast<LogicalAndExpression*>(n);
|
||||||
|
@ -3382,6 +3636,13 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
}
|
}
|
||||||
if(retNode != nullptr)
|
if(retNode != nullptr)
|
||||||
{
|
{
|
||||||
|
while(!this->__eachs.empty())
|
||||||
|
{
|
||||||
|
auto item = this->__eachs.top();
|
||||||
|
GetVariableExpression gve(item);
|
||||||
|
GenerateFree(&gve,instructions);
|
||||||
|
this->__eachs.pop();
|
||||||
|
}
|
||||||
Compile(retNode->retVal,instructions);
|
Compile(retNode->retVal,instructions);
|
||||||
instructions.push_back(new SimpleInstruction(Instruction::RET));
|
instructions.push_back(new SimpleInstruction(Instruction::RET));
|
||||||
}
|
}
|
||||||
|
@ -3473,7 +3734,62 @@ namespace Tesses::WebServer::ScriptEngine
|
||||||
_cont = oldcont;
|
_cont = oldcont;
|
||||||
_brk = oldbrk;
|
_brk = oldbrk;
|
||||||
}
|
}
|
||||||
|
if(eachLoop != nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
instructions.push_back(new SimpleInstruction(Instruction::SET_LOOP));
|
||||||
|
std::string eachIttr = NewJumpId();
|
||||||
|
__eachs.push(eachIttr);
|
||||||
|
instructions.push_back(new StringInstruction(eachIttr));
|
||||||
|
Compile(eachLoop->list,instructions);
|
||||||
|
instructions.push_back(new SimpleInstruction(Instruction::ITTR));
|
||||||
|
instructions.push_back(new SimpleInstruction(Instruction::SETVARIABLE));
|
||||||
|
instructions.push_back(new SimpleInstruction(Instruction::POP));
|
||||||
|
std::string oldcont = _cont;
|
||||||
|
std::string oldbrk = _brk;
|
||||||
|
std::string yes = NewJumpId();
|
||||||
|
std::string end = NewJumpId();
|
||||||
|
std::string begin = NewJumpId();
|
||||||
|
|
||||||
|
_cont = begin;
|
||||||
|
_brk = end;
|
||||||
|
|
||||||
|
instructions.push_back(new LabelInstruction(begin));
|
||||||
|
GetVariableExpression var(eachIttr);
|
||||||
|
GetMemberExpression mem(&var,"movenext");
|
||||||
|
FunctionCallExpression ce(&mem);
|
||||||
|
Compile(&ce,instructions);
|
||||||
|
ce.name = nullptr;
|
||||||
|
mem.parent=nullptr;
|
||||||
|
|
||||||
|
instructions.push_back(new JumpInstruction(Instruction::JMPC,yes));
|
||||||
|
instructions.push_back(new JumpInstruction(Instruction::JMP,end));
|
||||||
|
instructions.push_back(new LabelInstruction(yes));
|
||||||
|
GetMemberExpression mem2(&var,"current");
|
||||||
|
FunctionCallExpression ce2(&mem2);
|
||||||
|
AssignExpression assignExpr(eachLoop->item,&ce2);
|
||||||
|
|
||||||
|
|
||||||
|
Compile(&assignExpr,instructions);
|
||||||
|
ExpressionPop(&assignExpr,instructions);
|
||||||
|
|
||||||
|
mem2.parent=nullptr;
|
||||||
|
ce2.name=nullptr;
|
||||||
|
|
||||||
|
assignExpr.left=nullptr;
|
||||||
|
assignExpr.right = nullptr;
|
||||||
|
Compile(eachLoop->body,instructions);
|
||||||
|
ExpressionPop(eachLoop->body,instructions);
|
||||||
|
instructions.push_back(new JumpInstruction(Instruction::JMP,begin));
|
||||||
|
instructions.push_back(new LabelInstruction(end));
|
||||||
|
__eachs.pop();
|
||||||
|
|
||||||
|
GenerateFree(&var,instructions);
|
||||||
|
instructions.push_back(new SimpleInstruction(Instruction::DESTROY_LOOP));
|
||||||
|
|
||||||
|
_cont = oldcont;
|
||||||
|
_brk = oldbrk;
|
||||||
|
}
|
||||||
if(whileNode != nullptr)
|
if(whileNode != nullptr)
|
||||||
{
|
{
|
||||||
if(whileNode->isDo)
|
if(whileNode->isDo)
|
||||||
|
|
Loading…
Reference in New Issue