mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-18 10:37:04 +00:00
Add const variables
This commit is contained in:
@@ -666,7 +666,8 @@ typedef enum {
|
|||||||
PUSHCONTINUE,
|
PUSHCONTINUE,
|
||||||
JMPIFBREAK,
|
JMPIFBREAK,
|
||||||
JMPIFCONTINUE,
|
JMPIFCONTINUE,
|
||||||
JMPIFDEFINED
|
JMPIFDEFINED,
|
||||||
|
DECLARECONSTVARIABLE
|
||||||
} Instruction;
|
} Instruction;
|
||||||
/**
|
/**
|
||||||
* @brief Base type for bytecode instruction
|
* @brief Base type for bytecode instruction
|
||||||
@@ -991,6 +992,12 @@ constexpr std::string_view DictionaryExpression = "dictionaryExpression";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constexpr std::string_view DeclareExpression = "declareExpression";
|
constexpr std::string_view DeclareExpression = "declareExpression";
|
||||||
|
/**
|
||||||
|
* @brief const v = 59;
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
constexpr std::string_view ConstExpression = "constExpression";
|
||||||
/**
|
/**
|
||||||
* @brief Closure expression (a,b)=> a * b
|
* @brief Closure expression (a,b)=> a * b
|
||||||
*
|
*
|
||||||
@@ -1666,10 +1673,10 @@ class GC {
|
|||||||
virtual void Mark();
|
virtual void Mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ThrowConstError(std::string key);
|
||||||
|
|
||||||
class TEnvironment : public THeapObject {
|
class TEnvironment : public THeapObject {
|
||||||
|
std::vector<std::string> consts;
|
||||||
public:
|
public:
|
||||||
std::vector<TCallable*> defers;
|
std::vector<TCallable*> defers;
|
||||||
TObject LoadFile(GC* gc, TFile* f);
|
TObject LoadFile(GC* gc, TFile* f);
|
||||||
@@ -1687,6 +1694,9 @@ class GC {
|
|||||||
virtual void SetVariable(std::string key, TObject value)=0;
|
virtual void SetVariable(std::string key, TObject value)=0;
|
||||||
TDictionary* EnsureDictionary(GC* gc, std::string key);
|
TDictionary* EnsureDictionary(GC* gc, std::string key);
|
||||||
virtual void DeclareVariable(std::string key, TObject value)=0;
|
virtual void DeclareVariable(std::string key, TObject value)=0;
|
||||||
|
void DeclareConstVariable(std::string key, TObject value);
|
||||||
|
bool HasConstForDeclare(std::string key);
|
||||||
|
virtual bool HasConstForSet(std::string key);
|
||||||
void DeclareVariable(GC* gc,std::vector<std::string> key, TObject value);
|
void DeclareVariable(GC* gc,std::vector<std::string> key, TObject value);
|
||||||
virtual TRootEnvironment* GetRootEnvironment()=0;
|
virtual TRootEnvironment* GetRootEnvironment()=0;
|
||||||
virtual TEnvironment* GetParentEnvironment()=0;
|
virtual TEnvironment* GetParentEnvironment()=0;
|
||||||
@@ -1744,6 +1754,8 @@ class GC {
|
|||||||
TObject SetVariable(GCList& ls, std::string key, TObject v);
|
TObject SetVariable(GCList& ls, std::string key, TObject v);
|
||||||
|
|
||||||
void DeclareVariable(std::string key, TObject value);
|
void DeclareVariable(std::string key, TObject value);
|
||||||
|
bool HasConstForSet(std::string key);
|
||||||
|
|
||||||
TRootEnvironment* GetRootEnvironment();
|
TRootEnvironment* GetRootEnvironment();
|
||||||
TEnvironment* GetParentEnvironment();
|
TEnvironment* GetParentEnvironment();
|
||||||
|
|
||||||
@@ -1846,7 +1858,8 @@ class GC {
|
|||||||
bool HasVariable(std::string key);
|
bool HasVariable(std::string key);
|
||||||
bool HasVariableRecurse(std::string key);
|
bool HasVariableRecurse(std::string key);
|
||||||
bool HasVariableOrFieldRecurse(std::string key, bool setting=false);
|
bool HasVariableOrFieldRecurse(std::string key, bool setting=false);
|
||||||
|
bool HasConstForSet(std::string key);
|
||||||
|
|
||||||
TObject GetVariable(std::string key);
|
TObject GetVariable(std::string key);
|
||||||
void SetVariable(std::string key, TObject value);
|
void SetVariable(std::string key, TObject value);
|
||||||
TObject GetVariable(GCList& ls, std::string key);
|
TObject GetVariable(GCList& ls, std::string key);
|
||||||
@@ -2226,6 +2239,7 @@ class GC {
|
|||||||
bool GetArray(GC* gc);
|
bool GetArray(GC* gc);
|
||||||
bool SetArray(GC* gc);
|
bool SetArray(GC* gc);
|
||||||
bool DeclareVariable(GC* gc);
|
bool DeclareVariable(GC* gc);
|
||||||
|
bool DeclareConstVariable(GC* gc);
|
||||||
bool PushLong(GC* gc);
|
bool PushLong(GC* gc);
|
||||||
bool PushDouble(GC* gc);
|
bool PushDouble(GC* gc);
|
||||||
bool PushChar(GC* gc);
|
bool PushChar(GC* gc);
|
||||||
|
|||||||
@@ -451,6 +451,10 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
instrs.push_back(std::make_shared<SimpleChunkInstruction>(DECLAREVARIABLE));
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(DECLAREVARIABLE));
|
||||||
}
|
}
|
||||||
|
else if(name == "declareconstvariable")
|
||||||
|
{
|
||||||
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(DECLARECONSTVARIABLE));
|
||||||
|
}
|
||||||
else if(name == "setfield")
|
else if(name == "setfield")
|
||||||
{
|
{
|
||||||
instrs.push_back(std::make_shared<SimpleChunkInstruction>(SETFIELD));
|
instrs.push_back(std::make_shared<SimpleChunkInstruction>(SETFIELD));
|
||||||
|
|||||||
@@ -459,6 +459,9 @@ namespace Tesses::CrossLang {
|
|||||||
case DECLAREVARIABLE:
|
case DECLAREVARIABLE:
|
||||||
buffer.append("declarevariable");
|
buffer.append("declarevariable");
|
||||||
break;
|
break;
|
||||||
|
case DECLARECONSTVARIABLE:
|
||||||
|
buffer.append("declareconstvariable");
|
||||||
|
break;
|
||||||
case SETFIELD:
|
case SETFIELD:
|
||||||
buffer.append("setfield");
|
buffer.append("setfield");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1257,6 +1257,29 @@ namespace Tesses::CrossLang
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(varNode.nodeName == ConstExpression && varNode.nodes.size() == 1 && std::holds_alternative<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(DECLARECONSTVARIABLE));
|
||||||
|
}
|
||||||
|
else if(varNode.nodeName == ConstExpression && varNode.nodes.size() == 1 && std::holds_alternative<AdvancedSyntaxNode>(varNode.nodes[0]))
|
||||||
|
{
|
||||||
|
auto adv2 = std::get<AdvancedSyntaxNode>(varNode.nodes[0]);
|
||||||
|
|
||||||
|
if(adv2.nodeName == ArrayExpression && adv2.nodes.size() == 1)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto vars= StringifyListOfVars(adv2.nodes[0]);
|
||||||
|
|
||||||
|
auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars});
|
||||||
|
|
||||||
|
this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI);
|
||||||
|
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||||
|
instructions.push_back(new SimpleInstruction(DECLARECONSTVARIABLE));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2)
|
else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2)
|
||||||
{
|
{
|
||||||
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
|
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||||
|
|||||||
@@ -730,6 +730,33 @@ namespace Tesses::CrossLang
|
|||||||
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text});
|
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(IsIdentifier("const"))
|
||||||
|
{
|
||||||
|
if(i >= tokens.size()) throw std::out_of_range("End of file");
|
||||||
|
auto variable = tokens[i];
|
||||||
|
|
||||||
|
i++;
|
||||||
|
if(variable.type == LexTokenType::Symbol && variable.text == ".")
|
||||||
|
{
|
||||||
|
EnsureSymbol("[");
|
||||||
|
node = AdvancedSyntaxNode::Create(ConstExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression ,true,{ParseExpression()})
|
||||||
|
});
|
||||||
|
EnsureSymbol("]");
|
||||||
|
}
|
||||||
|
else if(variable.type == LexTokenType::Symbol && variable.text == "[")
|
||||||
|
{
|
||||||
|
node = AdvancedSyntaxNode::Create(ConstExpression,true,{
|
||||||
|
AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()})
|
||||||
|
});
|
||||||
|
EnsureSymbol("]");
|
||||||
|
}
|
||||||
|
else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\"");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node = AdvancedSyntaxNode::Create(ConstExpression,true,{variable.text});
|
||||||
|
}
|
||||||
|
}
|
||||||
else if(IsIdentifier("comptime"))
|
else if(IsIdentifier("comptime"))
|
||||||
{
|
{
|
||||||
SyntaxNode n = nullptr;
|
SyntaxNode n = nullptr;
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
bool TClassEnvironment::HasConstForSet(std::string key)
|
||||||
|
{
|
||||||
|
if(this->env->HasVariableRecurse(key))
|
||||||
|
{
|
||||||
|
return this->env->HasConstForSet(key);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TClassEnvironment* TClassEnvironment::Create(GCList* gc,TEnvironment* env,TClassObject* obj)
|
TClassEnvironment* TClassEnvironment::Create(GCList* gc,TEnvironment* env,TClassObject* obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -95,6 +102,7 @@ namespace Tesses::CrossLang {
|
|||||||
if(GetObjectHeap(res,call)) return call->Call(ls,{v});
|
if(GetObjectHeap(res,call)) return call->Call(ls,{v});
|
||||||
}
|
}
|
||||||
if(this->clsObj->HasValue(clsName,key)) { this->clsObj->SetValue(clsName,key,v); return v;}
|
if(this->clsObj->HasValue(clsName,key)) { this->clsObj->SetValue(clsName,key,v); return v;}
|
||||||
|
|
||||||
return this->env->SetVariable(ls,key,v);
|
return this->env->SetVariable(ls,key,v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,27 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
void ThrowConstError(std::string key)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Cannot set \"" + key + "\" because it is a const");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TEnvironment::DeclareConstVariable(std::string key, TObject value)
|
||||||
|
{
|
||||||
|
this->DeclareVariable(key,value);
|
||||||
|
this->consts.push_back(key);
|
||||||
|
}
|
||||||
|
bool TEnvironment::HasConstForDeclare(std::string key)
|
||||||
|
{
|
||||||
|
for(auto item : this->consts)
|
||||||
|
if(item == key)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TEnvironment::HasConstForSet(std::string key)
|
||||||
|
{
|
||||||
|
return HasConstForDeclare(key);
|
||||||
|
}
|
||||||
bool TRootEnvironment::TryFindClass(std::vector<std::string>& name, size_t& index)
|
bool TRootEnvironment::TryFindClass(std::vector<std::string>& name, size_t& index)
|
||||||
{
|
{
|
||||||
for(size_t i = 0; i < this->classes.size(); i++)
|
for(size_t i = 0; i < this->classes.size(); i++)
|
||||||
|
|||||||
@@ -50,6 +50,18 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
bool TSubEnvironment::HasConstForSet(std::string key)
|
||||||
|
{
|
||||||
|
if(this->dict->HasValue(key))
|
||||||
|
{
|
||||||
|
return this->HasConstForDeclare(key);
|
||||||
|
}
|
||||||
|
if(this->env->HasVariableRecurse(key))
|
||||||
|
{
|
||||||
|
return this->env->HasConstForSet(key);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
TObject TSubEnvironment::SetVariable(GCList& ls, std::string key, TObject value)
|
TObject TSubEnvironment::SetVariable(GCList& ls, std::string key, TObject value)
|
||||||
{
|
{
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
|
|||||||
265
src/vm/vm.cpp
265
src/vm/vm.cpp
@@ -4390,19 +4390,53 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
if(args.size() > 1 && GetArgument(args,0,key))
|
if(args.size() > 1 && GetArgument(args,0,key))
|
||||||
env->SetVariable(key,args[1]);
|
{
|
||||||
|
if(env->HasConstForSet(key))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
env->SetVariable(key,args[1]);
|
||||||
|
|
||||||
|
}
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
cse.back()->Push(gc,nullptr);
|
cse.back()->Push(gc,nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(key == "DeclareVariable")
|
if(key == "DeclareVariable")
|
||||||
{
|
{
|
||||||
std::string key;
|
std::string key;
|
||||||
|
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
if(args.size() > 1 && GetArgument(args,0,key))
|
if(args.size() > 1 && GetArgument(args,0,key))
|
||||||
env->DeclareVariable(key,args[1]);
|
{
|
||||||
|
if(env->HasConstForDeclare(key))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(key);
|
||||||
|
}
|
||||||
|
env->DeclareVariable(key,args[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc,nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(key == "DeclareConstVariable")
|
||||||
|
{
|
||||||
|
std::string key;
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
if(args.size() > 1 && GetArgument(args,0,key))
|
||||||
|
{
|
||||||
|
if(env->HasConstForDeclare(key))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(key);
|
||||||
|
}
|
||||||
|
env->DeclareConstVariable(key,args[1]);
|
||||||
|
}
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
cse.back()->Push(gc,nullptr);
|
cse.back()->Push(gc,nullptr);
|
||||||
return false;
|
return false;
|
||||||
@@ -6048,6 +6082,12 @@ namespace Tesses::CrossLang {
|
|||||||
if(std::holds_alternative<std::string>(key))
|
if(std::holds_alternative<std::string>(key))
|
||||||
{
|
{
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|
||||||
|
if(stk->env->HasConstForSet(std::get<std::string>(key)))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(std::get<std::string>(key));
|
||||||
|
}
|
||||||
stk->Push(gc,stk->env->SetVariable(ls,std::get<std::string>(key),value));
|
stk->Push(gc,stk->env->SetVariable(ls,std::get<std::string>(key),value));
|
||||||
|
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
@@ -6072,6 +6112,12 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
auto val = valueLs->Get(i);
|
auto val = valueLs->Get(i);
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
|
||||||
|
if(stk->env->HasConstForSet(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->SetVariable(ls,mkey,val);
|
stk->env->SetVariable(ls,mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6093,6 +6139,12 @@ namespace Tesses::CrossLang {
|
|||||||
auto val = valueDynList->GetAt(ls,i);
|
auto val = valueDynList->GetAt(ls,i);
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
|
||||||
|
if(stk->env->HasConstForSet(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->SetVariable(ls,mkey,val);
|
stk->env->SetVariable(ls,mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6111,6 +6163,12 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
auto val = valueDict->GetValue(mkey);
|
auto val = valueDict->GetValue(mkey);
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
|
||||||
|
if(stk->env->HasConstForSet(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->SetVariable(ls,mkey,val);
|
stk->env->SetVariable(ls,mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6131,6 +6189,12 @@ namespace Tesses::CrossLang {
|
|||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
|
||||||
|
if(stk->env->HasConstForSet(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->SetVariable(ls,mkey,val);
|
stk->env->SetVariable(ls,mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6144,6 +6208,12 @@ namespace Tesses::CrossLang {
|
|||||||
auto item = mls->Get(i);
|
auto item = mls->Get(i);
|
||||||
if(GetObject(item,mkey))
|
if(GetObject(item,mkey))
|
||||||
{
|
{
|
||||||
|
if(stk->env->HasConstForSet(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
|
|
||||||
stk->env->SetVariable(ls,mkey, value);
|
stk->env->SetVariable(ls,mkey, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6174,6 +6244,11 @@ namespace Tesses::CrossLang {
|
|||||||
if(std::holds_alternative<std::string>(key))
|
if(std::holds_alternative<std::string>(key))
|
||||||
{
|
{
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
if(stk->env->HasConstForDeclare(std::get<std::string>(key)))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(std::get<std::string>(key));
|
||||||
|
}
|
||||||
stk->env->DeclareVariable(std::get<std::string>(key),value);
|
stk->env->DeclareVariable(std::get<std::string>(key),value);
|
||||||
stk->Push(gc, value);
|
stk->Push(gc, value);
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
@@ -6198,6 +6273,11 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
auto val = valueLs->Get(i);
|
auto val = valueLs->Get(i);
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->DeclareVariable(mkey,val);
|
stk->env->DeclareVariable(mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6219,6 +6299,11 @@ namespace Tesses::CrossLang {
|
|||||||
auto val = valueDynList->GetAt(ls,i);
|
auto val = valueDynList->GetAt(ls,i);
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->DeclareVariable(mkey,val);
|
stk->env->DeclareVariable(mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6237,6 +6322,11 @@ namespace Tesses::CrossLang {
|
|||||||
{
|
{
|
||||||
auto val = valueDict->GetValue(mkey);
|
auto val = valueDict->GetValue(mkey);
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->DeclareVariable(mkey,val);
|
stk->env->DeclareVariable(mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6257,6 +6347,11 @@ namespace Tesses::CrossLang {
|
|||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|
||||||
result->SetValue(mkey, val);
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->DeclareVariable(mkey,val);
|
stk->env->DeclareVariable(mkey,val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6270,6 +6365,11 @@ namespace Tesses::CrossLang {
|
|||||||
auto item = mls->Get(i);
|
auto item = mls->Get(i);
|
||||||
if(GetObject(item,mkey))
|
if(GetObject(item,mkey))
|
||||||
{
|
{
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
stk->env->DeclareVariable(mkey, value);
|
stk->env->DeclareVariable(mkey, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6287,6 +6387,165 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool InterperterThread::DeclareConstVariable(GC* gc)
|
||||||
|
{
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
if(!cse.empty())
|
||||||
|
{
|
||||||
|
auto stk = cse.back();
|
||||||
|
GCList ls(gc);
|
||||||
|
|
||||||
|
auto value = stk->Pop(ls);
|
||||||
|
auto key = stk->Pop(ls);
|
||||||
|
|
||||||
|
TList* mls;
|
||||||
|
|
||||||
|
if(std::holds_alternative<std::string>(key))
|
||||||
|
{
|
||||||
|
gc->BarrierBegin();
|
||||||
|
if(stk->env->HasConstForDeclare(std::get<std::string>(key)))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(std::get<std::string>(key));
|
||||||
|
}
|
||||||
|
stk->env->DeclareConstVariable(std::get<std::string>(key),value);
|
||||||
|
stk->Push(gc, value);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
}
|
||||||
|
else if(GetObjectHeap(key,mls))
|
||||||
|
{
|
||||||
|
gc->BarrierBegin();
|
||||||
|
|
||||||
|
TList* valueLs;
|
||||||
|
TDynamicList* valueDynList;
|
||||||
|
TDictionary* valueDict;
|
||||||
|
TDynamicDictionary* valueDynDict;
|
||||||
|
if(GetObjectHeap(value, valueLs))
|
||||||
|
{
|
||||||
|
TDictionary* result = TDictionary::Create(ls);
|
||||||
|
int64_t len = std::min(valueLs->Count(), mls->Count());
|
||||||
|
for(int64_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
std::string mkey;
|
||||||
|
auto item = mls->Get(i);
|
||||||
|
if(GetObject(item,mkey))
|
||||||
|
{
|
||||||
|
auto val = valueLs->Get(i);
|
||||||
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
|
stk->env->DeclareConstVariable(mkey,val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stk->Push(gc,result);
|
||||||
|
}
|
||||||
|
else if(GetObjectHeap(value, valueDynList))
|
||||||
|
{
|
||||||
|
TDictionary* result = TDictionary::Create(ls);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
int64_t len = std::min(valueDynList->Count(ls), mls->Count());
|
||||||
|
gc->BarrierBegin();
|
||||||
|
for(int64_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
std::string mkey;
|
||||||
|
auto item = mls->Get(i);
|
||||||
|
if(GetObject(item,mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
auto val = valueDynList->GetAt(ls,i);
|
||||||
|
gc->BarrierBegin();
|
||||||
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
|
stk->env->DeclareConstVariable(mkey,val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stk->Push(gc,result);
|
||||||
|
}
|
||||||
|
else if(GetObjectHeap(value, valueDict))
|
||||||
|
{
|
||||||
|
|
||||||
|
TDictionary* result = TDictionary::Create(ls);
|
||||||
|
int64_t len = mls->Count();
|
||||||
|
for(int64_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
std::string mkey;
|
||||||
|
auto item = mls->Get(i);
|
||||||
|
if(GetObject(item,mkey))
|
||||||
|
{
|
||||||
|
auto val = valueDict->GetValue(mkey);
|
||||||
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
|
stk->env->DeclareConstVariable(mkey,val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stk->Push(gc,result);
|
||||||
|
}
|
||||||
|
else if(GetObjectHeap(value, valueDynDict))
|
||||||
|
{
|
||||||
|
TDictionary* result = TDictionary::Create(ls);
|
||||||
|
int64_t len =mls->Count();
|
||||||
|
for(int64_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
std::string mkey;
|
||||||
|
auto item = mls->Get(i);
|
||||||
|
if(GetObject(item,mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
auto val = valueDynDict->GetField(ls,mkey);
|
||||||
|
gc->BarrierBegin();
|
||||||
|
|
||||||
|
result->SetValue(mkey, val);
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
|
stk->env->DeclareConstVariable(mkey,val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stk->Push(gc,result);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int64_t len =mls->Count();
|
||||||
|
for(int64_t i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
std::string mkey;
|
||||||
|
auto item = mls->Get(i);
|
||||||
|
if(GetObject(item,mkey))
|
||||||
|
{
|
||||||
|
if(stk->env->HasConstForDeclare(mkey))
|
||||||
|
{
|
||||||
|
gc->BarrierEnd();
|
||||||
|
ThrowConstError(mkey);
|
||||||
|
}
|
||||||
|
stk->env->DeclareConstVariable(mkey, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stk->Push(gc, value);
|
||||||
|
}
|
||||||
|
gc->BarrierEnd();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
throw VMException("[DECLARECONSTVARIABLE] Can't pop string, got type " + GetObjectTypeString(key) + " = " + ToString(gc,key) + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InterperterThread::PushResource(GC* gc)
|
bool InterperterThread::PushResource(GC* gc)
|
||||||
{
|
{
|
||||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ static opcode opcodes[256]={
|
|||||||
&InterperterThread::JumpIfBreak,
|
&InterperterThread::JumpIfBreak,
|
||||||
&InterperterThread::JumpIfContinue,
|
&InterperterThread::JumpIfContinue,
|
||||||
&InterperterThread::JumpIfDefined,
|
&InterperterThread::JumpIfDefined,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::DeclareConstVariable,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
&InterperterThread::Illegal,
|
&InterperterThread::Illegal,
|
||||||
|
|||||||
Reference in New Issue
Block a user