Add reflective variables and fields
This commit is contained in:
@ -1945,7 +1945,15 @@ class GC {
|
||||
|
||||
TObject GetAt(GCList& ls, int64_t index);
|
||||
|
||||
void SetAt(GCList& ls, int64_t index, TObject val);
|
||||
TObject SetAt(GCList& ls, int64_t index, TObject val);
|
||||
|
||||
TObject Add(GCList& ls, TObject v);
|
||||
TObject Insert(GCList& ls, int64_t index, TObject v);
|
||||
TObject RemoveAllEqual(GCList& ls, TObject v);
|
||||
TObject Remove(GCList& ls, TObject v);
|
||||
TObject RemoveAt(GCList& ls, int64_t v);
|
||||
TObject Clear(GCList& ls);
|
||||
TObject ToString(GCList& ls);
|
||||
|
||||
~TDynamicList();
|
||||
};
|
||||
@ -1961,7 +1969,7 @@ class GC {
|
||||
|
||||
TObject GetField(GCList& ls, std::string key);
|
||||
|
||||
void SetField(GCList& ls, std::string key, TObject value);
|
||||
TObject SetField(GCList& ls, std::string key, TObject value);
|
||||
|
||||
TObject CallMethod(GCList& ls, std::string name, std::vector<TObject> args);
|
||||
|
||||
|
||||
@ -1021,16 +1021,16 @@ namespace Tesses::CrossLang
|
||||
instructions.push_back(new JumpStyleInstruction(JMP,myJmp));
|
||||
}
|
||||
}
|
||||
else if(adv.nodeName == GetVariableExpression && adv.nodes.size() == 1 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||
else if(adv.nodeName == GetVariableExpression && adv.nodes.size() == 1)
|
||||
{
|
||||
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(adv.nodes[0]))));
|
||||
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||
instructions.push_back(new SimpleInstruction(GETVARIABLE));
|
||||
}
|
||||
else if(adv.nodeName == GetFieldExpression && adv.nodes.size() == 2 && std::holds_alternative<std::string>(adv.nodes[1]))
|
||||
else if(adv.nodeName == GetFieldExpression && adv.nodes.size() == 2)
|
||||
{
|
||||
|
||||
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(adv.nodes[1]))));
|
||||
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||
|
||||
instructions.push_back(new SimpleInstruction(GETFIELD));
|
||||
|
||||
@ -1047,9 +1047,9 @@ namespace Tesses::CrossLang
|
||||
{
|
||||
auto varNode = std::get<AdvancedSyntaxNode>(adv.nodes[0]);
|
||||
|
||||
if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1 && std::holds_alternative<std::string>(varNode.nodes[0]))
|
||||
if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1)
|
||||
{
|
||||
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0]))));
|
||||
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||
instructions.push_back(new SimpleInstruction(SETVARIABLE));
|
||||
}
|
||||
@ -1067,7 +1067,7 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative<std::string>(varNode.nodes[0]))
|
||||
{
|
||||
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0]))));
|
||||
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||
instructions.push_back(new SimpleInstruction(DECLAREVARIABLE));
|
||||
}
|
||||
@ -1091,7 +1091,8 @@ namespace Tesses::CrossLang
|
||||
else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2 && std::holds_alternative<std::string>(varNode.nodes[1]))
|
||||
{
|
||||
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[1]))));
|
||||
|
||||
GenNode(instructions,varNode.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||
instructions.push_back(new SimpleInstruction(SETFIELD));
|
||||
}
|
||||
@ -1394,6 +1395,7 @@ namespace Tesses::CrossLang
|
||||
{
|
||||
name.push_back(GetString(std::get<std::string>(res.nodes[1])));
|
||||
}
|
||||
|
||||
}
|
||||
else if(res.nodeName == GetVariableExpression && res.nodes.size() == 1)
|
||||
{
|
||||
|
||||
@ -547,6 +547,20 @@ namespace Tesses::CrossLang
|
||||
i++;
|
||||
|
||||
}
|
||||
else if(tokens[i].type == LexTokenType::Symbol && tokens[i].text == ".")
|
||||
{
|
||||
i++;
|
||||
if(IsSymbol("["))
|
||||
{
|
||||
node = AdvancedSyntaxNode::Create(GetVariableExpression,true,{ParseExpression()});
|
||||
EnsureSymbol("]");
|
||||
}
|
||||
else
|
||||
{
|
||||
node = AdvancedSyntaxNode::Create(RelativePathExpression, true, {});
|
||||
|
||||
}
|
||||
}
|
||||
else if(IsSymbol("<"))
|
||||
{
|
||||
uint32_t htmlId = NewId();
|
||||
@ -590,7 +604,15 @@ namespace Tesses::CrossLang
|
||||
auto variable = tokens[i];
|
||||
|
||||
i++;
|
||||
if(variable.type == LexTokenType::Symbol && variable.text == "[")
|
||||
if(variable.type == LexTokenType::Symbol && variable.text == ".")
|
||||
{
|
||||
EnsureSymbol("[");
|
||||
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{
|
||||
AdvancedSyntaxNode::Create(GetVariableExpression ,true,{ParseExpression()})
|
||||
});
|
||||
EnsureSymbol("]");
|
||||
}
|
||||
else if(variable.type == LexTokenType::Symbol && variable.text == "[")
|
||||
{
|
||||
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{
|
||||
AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()})
|
||||
@ -725,6 +747,13 @@ namespace Tesses::CrossLang
|
||||
if(tkn.text == ".")
|
||||
{
|
||||
if(i>=tokens.size()) throw std::out_of_range("End of file");
|
||||
if(IsSymbol("["))
|
||||
{
|
||||
|
||||
node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {node, ParseExpression()});
|
||||
EnsureSymbol("]");
|
||||
continue;
|
||||
}
|
||||
if(tokens[i].type != LexTokenType::Identifier) throw std::exception();
|
||||
std::string name = tokens[i].text;
|
||||
if(name == "operator")
|
||||
@ -807,10 +836,7 @@ namespace Tesses::CrossLang
|
||||
return AdvancedSyntaxNode::Create(RootPathExpression,true,{});
|
||||
}
|
||||
}
|
||||
else if(IsSymbol("."))
|
||||
{
|
||||
return AdvancedSyntaxNode::Create(RelativePathExpression, true, {});
|
||||
}
|
||||
|
||||
|
||||
return ParseValue();
|
||||
}
|
||||
|
||||
@ -311,7 +311,7 @@ namespace Tesses::CrossLang
|
||||
{
|
||||
|
||||
|
||||
ctx->StartWebSocketSession([dict,&ls](std::function<void(WebSocketMessage&)> sendMessage,std::function<void()> ping)->void{
|
||||
ctx->StartWebSocketSession([dict,&ls](std::function<void(WebSocketMessage&)> sendMessage,std::function<void()> ping,std::function<void()> close)->void{
|
||||
GCList ls2(ls.GetGC());
|
||||
dict->CallMethod(ls2,"Open",{
|
||||
TExternalMethod::Create(ls2,"Send a message",{"messageTextOrByteArray"},[sendMessage](GCList& ls,std::vector<TObject> args)->TObject{
|
||||
@ -332,6 +332,10 @@ namespace Tesses::CrossLang
|
||||
TExternalMethod::Create(ls2, "Ping client", {},[ping](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
ping();
|
||||
return nullptr;
|
||||
}),
|
||||
TExternalMethod::Create(ls2, "Close client",{},[close](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
close();
|
||||
return nullptr;
|
||||
})
|
||||
});
|
||||
}, [dict,&ls](WebSocketMessage& msg)->void {
|
||||
@ -359,6 +363,8 @@ namespace Tesses::CrossLang
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
|
||||
|
||||
//dict->DeclareFunction(gc,"getOriginalPathWithQuery","Get original path with query parameters",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return ctx->GetOriginalPathWithQuery();});
|
||||
dict->DeclareFunction(gc,"getPath","Get path",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {return ctx->path;});
|
||||
dict->DeclareFunction(gc,"setPath","Set path",{},[ctx](Tesses::CrossLang::GCList &ls2, std::vector<Tesses::CrossLang::TObject> args2)->TObject {
|
||||
@ -833,7 +839,119 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_WebSocketClient(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string url;
|
||||
TList* headers;
|
||||
TDictionary* dict;
|
||||
|
||||
TCallable* callable=nullptr;
|
||||
|
||||
TObject _obj;
|
||||
if(GetArgument(args,0,url) && GetArgumentHeap(args,1,headers) && GetArgumentHeap(args,2,dict))
|
||||
{
|
||||
GetArgumentHeap(args,3,callable);
|
||||
HttpDictionary hdict;
|
||||
for(int64_t index = 0; index < headers->Count();index ++)
|
||||
{
|
||||
_obj = headers->Get(index);
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(_obj,dict))
|
||||
{
|
||||
std::string key={};
|
||||
std::string value={};
|
||||
_obj = dict->GetValue("Key");
|
||||
GetObject(_obj,key);
|
||||
_obj = dict->GetValue("Value");
|
||||
|
||||
hdict.AddValue(key,value);
|
||||
}
|
||||
}
|
||||
CallbackWebSocketConnection conn([dict,&ls](std::function<void(WebSocketMessage&)> sendMessage,std::function<void()> ping,std::function<void()> close)->void{
|
||||
GCList ls2(ls.GetGC());
|
||||
dict->CallMethod(ls2,"Open",{
|
||||
TExternalMethod::Create(ls2,"Send a message",{"messageTextOrByteArray"},[sendMessage](GCList& ls,std::vector<TObject> args)->TObject{
|
||||
std::string str;
|
||||
TByteArray* bArray;
|
||||
if(GetArgument(args,0,str))
|
||||
{
|
||||
WebSocketMessage msg(str);
|
||||
sendMessage(msg);
|
||||
}
|
||||
else if(GetArgumentHeap(args,0,bArray))
|
||||
{
|
||||
WebSocketMessage msg(bArray->data);
|
||||
sendMessage(msg);
|
||||
}
|
||||
return nullptr;
|
||||
}),
|
||||
TExternalMethod::Create(ls2, "Ping client", {},[ping](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
ping();
|
||||
return nullptr;
|
||||
}),
|
||||
TExternalMethod::Create(ls2, "Close client",{},[close](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
close();
|
||||
return nullptr;
|
||||
})
|
||||
});
|
||||
}, [dict,&ls](WebSocketMessage& msg)->void {
|
||||
GCList ls2(ls.GetGC());
|
||||
|
||||
TObject v;
|
||||
|
||||
if(msg.isBinary)
|
||||
{
|
||||
auto r = TByteArray::Create(ls2);
|
||||
r->data = msg.data;
|
||||
v = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = msg.ToString();
|
||||
}
|
||||
|
||||
dict->CallMethod(ls2,"Receive",{v});
|
||||
}, [dict,&ls](bool close)->void {
|
||||
GCList ls2(ls.GetGC());
|
||||
dict->CallMethod(ls2,"Close",{close});
|
||||
});
|
||||
WebSocketClient(url, hdict, conn, [&ls,callable](Tesses::Framework::Http::HttpDictionary& dict, bool success)->bool {
|
||||
if(callable != nullptr)
|
||||
return ToBool(callable->Call(ls,{CreateDictionaryFromHttpDictionary(ls,&dict),success}));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return nullptr;
|
||||
//Net.Http.CreateWebSocketConnection("wss://example.com/",[],conn, (dict, success)=>{ return true;})
|
||||
}
|
||||
static TObject Net_Http_DownloadToString(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string url;
|
||||
if(GetArgument(args,0,url))
|
||||
return DownloadToStringSimple(url);
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_DownloadToStream(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string url;
|
||||
TStreamHeapObject* strm;
|
||||
if(GetArgument(args,0,url) && GetArgumentHeap(args,1,strm))
|
||||
{
|
||||
DownloadToStreamSimple(url,strm->stream);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject Net_Http_DownloadToFile(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::string url;
|
||||
TVFSHeapObject* vfs;
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
if(GetArgument(args,0,url) && GetArgumentHeap(args,1,vfs) && GetArgumentAsPath(args,2, path))
|
||||
{
|
||||
DownloadToFileSimple(url,vfs->vfs,path);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void TStd::RegisterNet(GC* gc, TRootEnvironment* env)
|
||||
{
|
||||
|
||||
@ -877,6 +995,10 @@ namespace Tesses::CrossLang
|
||||
return nullptr;
|
||||
});
|
||||
http->DeclareFunction(gc, "MakeRequest", "Create an http request", {"url","$extra"}, Net_Http_MakeRequest);
|
||||
http->DeclareFunction(gc, "WebSocketClient", "Create a websocket connection",{"url","headers","conn","$successCB"},Net_Http_WebSocketClient);
|
||||
http->DeclareFunction(gc, "DownloadToString","Return the http file's contents as a string",{"url"},Net_Http_DownloadToString);
|
||||
http->DeclareFunction(gc, "DownloadToStream","Download file to stream",{"url","stream"},Net_Http_DownloadToStream);
|
||||
http->DeclareFunction(gc, "DownloadToFile","Download file to file in vfs",{"url","vfs","path"},Net_Http_DownloadToFile);
|
||||
http->DeclareFunction(gc, "ListenSimpleWithLoop", "Listen (creates application loop)", {"server","port"},Net_Http_ListenSimpleWithLoop);
|
||||
http->DeclareFunction(gc, "ListenOnUnusedPort","Listen on unused localhost port and print Port: theport",{"server"},Net_Http_ListenOnUnusedPort);
|
||||
//FileServer svr()
|
||||
|
||||
@ -628,6 +628,18 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
newTypes->DeclareFunction(gc,"DynamicList","Create a dynamic list",{},[](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
TCallable* callable;
|
||||
if(GetArgumentHeap(args,0,callable))
|
||||
return TDynamicList::Create(ls,callable);
|
||||
return nullptr;
|
||||
});
|
||||
newTypes->DeclareFunction(gc,"DynamicDictionary","Create a dynamic dictionary",{},[](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
TCallable* callable;
|
||||
if(GetArgumentHeap(args,0,callable))
|
||||
return TDynamicDictionary::Create(ls,callable);
|
||||
return nullptr;
|
||||
});
|
||||
newTypes->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray);
|
||||
gc->BarrierBegin();
|
||||
env->DeclareVariable("Version", TDictionary::Create(ls,{
|
||||
|
||||
@ -35,10 +35,10 @@ namespace Tesses::CrossLang {
|
||||
dict->SetValue("Type", "GetField");
|
||||
dict->SetValue("Key", key);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return cb->Call(ls,{dict});
|
||||
return this->cb->Call(ls,{dict});
|
||||
}
|
||||
|
||||
void TDynamicDictionary::SetField(GCList& ls, std::string key, TObject value)
|
||||
TObject TDynamicDictionary::SetField(GCList& ls, std::string key, TObject value)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
@ -46,7 +46,7 @@ namespace Tesses::CrossLang {
|
||||
dict->SetValue("Key", key);
|
||||
dict->SetValue("Value", value);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
cb->Call(ls,{dict});
|
||||
return this->cb->Call(ls,{dict});
|
||||
}
|
||||
|
||||
TObject TDynamicDictionary::CallMethod(GCList& ls, std::string name, std::vector<TObject> args)
|
||||
@ -59,7 +59,7 @@ namespace Tesses::CrossLang {
|
||||
argVal->items = args;
|
||||
dict->SetValue("Arguments", argVal);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return cb->Call(ls,{dict});
|
||||
return this->cb->Call(ls,{dict});
|
||||
}
|
||||
|
||||
TEnumerator* TDynamicDictionary::GetEnumerator(GCList& ls)
|
||||
@ -70,7 +70,7 @@ namespace Tesses::CrossLang {
|
||||
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return TEnumerator::CreateFromObject(ls,cb->Call(ls,{dict}));
|
||||
return TEnumerator::CreateFromObject(ls,this->cb->Call(ls,{dict}));
|
||||
}
|
||||
bool TDictionary::MethodExists(GCList& ls,std::string method)
|
||||
{
|
||||
@ -90,7 +90,7 @@ namespace Tesses::CrossLang {
|
||||
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
auto res = cb->Call(ls,{dict});
|
||||
auto res = this->cb->Call(ls,{dict});
|
||||
bool r2;
|
||||
if(GetObject(res,r2)) return r2;
|
||||
return false;
|
||||
|
||||
@ -38,6 +38,76 @@ namespace Tesses::CrossLang {
|
||||
if(GetObject(res,n)) return n;
|
||||
return 0;
|
||||
}
|
||||
TObject TDynamicList::Add(GCList& ls, TObject v)
|
||||
{
|
||||
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "Add");
|
||||
dict->SetValue("Value",v);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return cb->Call(ls,{dict});
|
||||
|
||||
}
|
||||
TObject TDynamicList::Insert(GCList& ls, int64_t index, TObject v)
|
||||
{
|
||||
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "Insert");
|
||||
dict->SetValue("Index",index);
|
||||
dict->SetValue("Value",v);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return cb->Call(ls,{dict});
|
||||
|
||||
}
|
||||
TObject TDynamicList::Clear(GCList& ls)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "Clear");
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
TObject TDynamicList::Remove(GCList& ls, TObject obj)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "Remove");
|
||||
dict->SetValue("Value", obj);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
TObject TDynamicList::RemoveAllEqual(GCList& ls, TObject obj)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "RemoveAllEqual");
|
||||
dict->SetValue("Value", obj);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
TObject TDynamicList::RemoveAt(GCList& ls, int64_t index)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "RemoveAt");
|
||||
dict->SetValue("Index", index);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
TObject TDynamicList::ToString(GCList& ls)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("Type", "ToString");
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
|
||||
TObject TDynamicList::GetAt(GCList& ls, int64_t index)
|
||||
{
|
||||
@ -50,7 +120,7 @@ namespace Tesses::CrossLang {
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
|
||||
void TDynamicList::SetAt(GCList& ls, int64_t index, TObject val)
|
||||
TObject TDynamicList::SetAt(GCList& ls, int64_t index, TObject val)
|
||||
{
|
||||
auto dict = TDictionary::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
@ -58,7 +128,7 @@ namespace Tesses::CrossLang {
|
||||
dict->SetValue("Index",index);
|
||||
dict->SetValue("Value",val);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
cb->Call(ls,{dict});
|
||||
return cb->Call(ls,{dict});
|
||||
}
|
||||
|
||||
TDynamicList::~TDynamicList()
|
||||
|
||||
184
src/vm/vm.cpp
184
src/vm/vm.cpp
@ -2535,8 +2535,10 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto dynList = dynamic_cast<TDynamicList*>(obj);
|
||||
auto bArray = dynamic_cast<TByteArray*>(obj);
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto ittr = dynamic_cast<TEnumerator*>(obj);
|
||||
auto strm = dynamic_cast<TStreamHeapObject*>(obj);
|
||||
auto vfs = dynamic_cast<TVFSHeapObject*>(obj);
|
||||
@ -3996,6 +3998,139 @@ namespace Tesses::CrossLang {
|
||||
cse.back()->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
else if(dynList != nullptr)
|
||||
{
|
||||
|
||||
if(key == "GetEnumerator")
|
||||
{
|
||||
cse.back()->Push(gc, TDynamicListEnumerator::Create(ls, dynList));
|
||||
return false;
|
||||
}
|
||||
else if(key == "ToString")
|
||||
{
|
||||
cse.back()->Push(gc, dynList->ToString(ls));
|
||||
return false;
|
||||
}
|
||||
else if(key == "Insert")
|
||||
{
|
||||
if(args.size() != 2)
|
||||
{
|
||||
throw VMException("List.Insert must only accept two arguments");
|
||||
}
|
||||
int64_t index;
|
||||
|
||||
if(!GetArgument(args,0,index))
|
||||
{
|
||||
throw VMException("List.Insert first argument must be Long");
|
||||
}
|
||||
|
||||
cse.back()->Push(gc, dynList->Insert(ls,index,args[0]));
|
||||
return false;
|
||||
}
|
||||
if(key == "Add")
|
||||
{
|
||||
if(args.size() != 1)
|
||||
{
|
||||
throw VMException("List.Add must only accept one argument");
|
||||
}
|
||||
|
||||
cse.back()->Push(gc,dynList->Add(ls,args[0]));
|
||||
return false;
|
||||
}
|
||||
if(key == "RemoveAllEqual")
|
||||
{
|
||||
if(args.size() != 1)
|
||||
{
|
||||
throw VMException("List.RemoveAllEqual must only accept one argument");
|
||||
}
|
||||
|
||||
cse.back()->Push(gc,dynList->RemoveAllEqual(ls, args[0]));
|
||||
return false;
|
||||
}
|
||||
if(key == "Remove")
|
||||
{
|
||||
if(args.size() != 1)
|
||||
{
|
||||
throw VMException("List.Remove must only accept one argument");
|
||||
}
|
||||
|
||||
|
||||
|
||||
cse.back()->Push(gc,dynList->Remove(ls, args[0]));
|
||||
return false;
|
||||
}
|
||||
if(key == "RemoveAt")
|
||||
{
|
||||
if(args.size() != 1)
|
||||
{
|
||||
throw VMException("List.RemoveAt must only accept one argument");
|
||||
}
|
||||
|
||||
if(!std::holds_alternative<int64_t>(args[0]))
|
||||
{
|
||||
throw VMException("List.RemoveAt must only accept a long");
|
||||
}
|
||||
cse.back()->Push(gc,dynList->RemoveAt(ls,std::get<int64_t>(args[0])));
|
||||
|
||||
return false;
|
||||
}
|
||||
if(key == "Clear")
|
||||
{
|
||||
|
||||
|
||||
cse.back()->Push(gc, dynList->Clear(ls));
|
||||
return false;
|
||||
}
|
||||
if(key == "GetAt")
|
||||
{
|
||||
if(args.size() != 1)
|
||||
{
|
||||
throw VMException("List.GetAt must only accept one argument");
|
||||
}
|
||||
|
||||
if(!std::holds_alternative<int64_t>(args[0]))
|
||||
{
|
||||
throw VMException("List.GetAt must only accept a long");
|
||||
}
|
||||
|
||||
int64_t index = std::get<int64_t>(args[0]);
|
||||
if(index >= 0)
|
||||
{
|
||||
cse.back()->Push(gc, dynList->GetAt(ls,index));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
if(key == "SetAt")
|
||||
{
|
||||
if(args.size() != 2)
|
||||
{
|
||||
throw VMException("List.SetAt must only accept two arguments");
|
||||
}
|
||||
|
||||
if(!std::holds_alternative<int64_t>(args[0]))
|
||||
{
|
||||
throw VMException("List.SetAt first argument must only accept a long");
|
||||
}
|
||||
|
||||
int64_t index = std::get<int64_t>(args[0]);
|
||||
if(index >= 0)
|
||||
{
|
||||
cse.back()->Push(gc,dynList->SetAt(ls,index,args[1]));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(key == "Count" || key == "Length")
|
||||
{
|
||||
cse.back()->Push(gc, dynList->Count(ls));
|
||||
|
||||
return false;
|
||||
}
|
||||
cse.back()->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
else if(dict != nullptr)
|
||||
{
|
||||
if(key == "ToString" && !dict->MethodExists(ls, key) && args.empty())
|
||||
@ -4010,6 +4145,14 @@ namespace Tesses::CrossLang {
|
||||
|
||||
return InvokeMethod(ls,o,dict,args);
|
||||
}
|
||||
else if(dynDict != nullptr)
|
||||
{
|
||||
|
||||
|
||||
cse.back()->Push(gc,dict->CallMethod(ls, key, args));
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(callable != nullptr)
|
||||
{
|
||||
if(key == "Call")
|
||||
@ -4237,6 +4380,8 @@ namespace Tesses::CrossLang {
|
||||
auto bA = dynamic_cast<TByteArray*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto dynList = dynamic_cast<TDynamicList*>(obj);
|
||||
auto tcallable = dynamic_cast<TCallable*>(obj);
|
||||
auto closure = dynamic_cast<TClosure*>(obj);
|
||||
auto externalMethod = dynamic_cast<TExternalMethod*>(obj);
|
||||
@ -4247,6 +4392,7 @@ namespace Tesses::CrossLang {
|
||||
auto file = dynamic_cast<TFile*>(obj);
|
||||
auto chunk = dynamic_cast<TFileChunk*>(obj);
|
||||
|
||||
|
||||
if(file != nullptr)
|
||||
{
|
||||
if(key == "Version")
|
||||
@ -4538,6 +4684,29 @@ namespace Tesses::CrossLang {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(dynList != nullptr)
|
||||
{
|
||||
if(key == "Count" || key == "Length")
|
||||
{
|
||||
int64_t len = dynList->Count(ls);
|
||||
if(len < 0) len = 0;
|
||||
|
||||
stk->Push(gc, len);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(dynDict != nullptr)
|
||||
{
|
||||
if(dynDict->MethodExists(ls,"get" + key))
|
||||
{
|
||||
cse.back()->Push(gc,dynDict->CallMethod(ls,"get" + key, {}));
|
||||
}
|
||||
else
|
||||
{
|
||||
cse.back()->Push(gc, dynDict->GetField(ls,key));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(dict != nullptr)
|
||||
{
|
||||
@ -4590,6 +4759,8 @@ namespace Tesses::CrossLang {
|
||||
auto vfs = dynamic_cast<TVFSHeapObject*>(obj);
|
||||
auto strm = dynamic_cast<TStreamHeapObject*>(obj);
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
auto tcallable = dynamic_cast<TCallable*>(obj);
|
||||
if(tcallable != nullptr)
|
||||
{
|
||||
@ -4627,6 +4798,19 @@ namespace Tesses::CrossLang {
|
||||
|
||||
}
|
||||
}
|
||||
if(dynDict != nullptr)
|
||||
{
|
||||
if(dynDict->MethodExists(ls,"set" + key))
|
||||
{
|
||||
cse.back()->Push(gc,dynDict->CallMethod(ls,"set" + key, {value}));
|
||||
}
|
||||
else
|
||||
{
|
||||
dynDict->SetField(ls,key,value);
|
||||
cse.back()->Push(gc,value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(dict != nullptr)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
|
||||
Reference in New Issue
Block a user