上一節(jié)我們從模型上重建了AST節(jié)點(diǎn),將antlr生成的表達(dá)式AST抽象成可直接運(yùn)算的AST節(jié)點(diǎn)。
在運(yùn)算之前我們必須首先定義出數(shù)據(jù)類(lèi)型,定義出腳本支持的數(shù)據(jù)類(lèi)型,這是運(yùn)算的基礎(chǔ)。
這一小節(jié)我們將定義出數(shù)據(jù)類(lèi)型,在這里我們暫時(shí)定義四個(gè)數(shù)據(jù)類(lèi)型:
enum Type { String, Number, Bool, Object, None };
完整的數(shù)據(jù)類(lèi)型定義如下:
/// .h
typedef double number;
namespace DynamicDSL {
enum Type { String, Number, Bool, Object, None };
struct SemaASTNodeObject {
private:
any value;
public:
SemaASTNodeObject() {}
SemaASTNodeObject(any value) {
this->value = value;
}
~SemaASTNodeObject() { }
public:
const Type getType();
const string getTypeText();
const any getRawValue() { return this->value; }
void setValue(any v) { this->value = v; }
/// 獲取數(shù)據(jù)的字符串描述
const string getText();
template
這里我們使用了any來(lái)包裝我們具體的數(shù)據(jù),所以我們的C++編譯器需要設(shè)置成C++ 17
String類(lèi)型我們使用的是std::string來(lái)實(shí)現(xiàn)。
Number類(lèi)型則是上面提到的使用double來(lái)實(shí)現(xiàn)的。
Bool類(lèi)型則是使用bool實(shí)現(xiàn)。
Object類(lèi)型是單獨(dú)定義的一個(gè)C++類(lèi)型或者本身就是一個(gè)SemaASTNodeObject,后面單獨(dú)說(shuō)明。
通過(guò)std::any中的type()函數(shù)獲取放置的數(shù)據(jù)信息來(lái)判斷放置的數(shù)據(jù)的類(lèi)型:
const DynamicDSL::Type DynamicDSL::SemaASTNodeObject::getType() {
string clsName = this->value.type().name();
if(clsName == "i" || clsName == "d") return Number;
else if(clsName.find("string") != string::npos) return String;
else if(clsName == "b") return Bool;
else if(clsName.find("SemaASTNodeObject") != string::npos ||
clsName.find("SemaContext") != string::npos)
return Object;
else if(clsName == "v") return None;
else {
return None;
}
}
解包的時(shí)候判斷再轉(zhuǎn)換成具體的數(shù)據(jù)類(lèi)即可,它的實(shí)現(xiàn)如下:
const string DynamicDSL::SemaASTNodeObject::getText() {
if(this->value.has_value()) {
if(getType() == String) {
return any_cast<string>(this->value);
} else if(getType() == Number) {
ostringstream oss;
oss << any_cast<double>(this->value);
return oss.str();
} else if(getType() == Bool) {
if(any_cast<bool>(this->value)) return "true";
else return "false";
} else if(getType() == Object) {
string clsName = this->value.type().name();
if(clsName.find("SemaASTNodeObject") != string::npos) {
return getValue
為里需要特別說(shuō)明一下Object這個(gè)類(lèi)型中的另外一個(gè)自定義數(shù)據(jù)類(lèi)型SemaContext。
它的完整定義如下:
namespace DynamicDSL {
enum JSONType {
JSONType_String,
JSONType_Number,
JSONType_Bool,
JSONType_Object,
JSONType_None
};
}
namespace DynamicDSL {
class SemaContext {
private:
/// 本地變量
map<string, SemaASTNodeObject> variable;
/// JSON注入
Json json;
public:
SemaContext(Json json) {
this->json = json;
}
SemaContext(Json json, map<string, SemaASTNodeObject> variable) {
this->json = json;
this->variable = variable;
}
static SemaContext *copy(SemaContext *context) {
return new SemaContext(context->getJSON(), context->getVariable());
}
public:
map<string, SemaASTNodeObject> getVariable() { return variable; }
Json getJSON() { return json; }
void putVariable(string key, SemaASTNodeObject val) {
variable[key] = val;
}
SemaASTNodeObject getVariableValue(string key) {
if(variable.count(key) > 0) return variable[key];
DynamicDSL::SemaASTNodeObject object;
if(!json[key].is_null()) {
Json jsonValue = json[key];
JSONType type = SemaContext::getValueType(jsonValue);
if(type == DynamicDSL::JSONType_Bool) {
object.setValue(jsonValue.bool_value());
} else if(type == DynamicDSL::JSONType_Number) {
object.setValue(jsonValue.number_value());
} else if(type == DynamicDSL::JSONType_String) {
object.setValue(jsonValue.string_value());
} else if(type == DynamicDSL::JSONType_Object) {
auto context = SemaContext(jsonValue);
object.setValue(context);
}
}
return object;
}
static JSONType getValueType(Json jsonObject) {
if(jsonObject.is_string()) return DynamicDSL::JSONType_String;
else if(jsonObject.is_number()) return DynamicDSL::JSONType_Number;
else if(jsonObject.is_bool()) return DynamicDSL::JSONType_Bool;
else if(jsonObject.is_object()) return DynamicDSL::JSONType_Object;
return DynamicDSL::JSONType_None;
}
};
};
這個(gè)類(lèi)定義了棧幀執(zhí)行時(shí)的變量上下文環(huán)境,由于特殊的使用場(chǎng)景,還多定義了一個(gè)注入的Json對(duì)象,這個(gè)Json對(duì)象在使用模板一開(kāi)始的時(shí)候就注入了。
棧運(yùn)行過(guò)程中產(chǎn)生的臨時(shí)變量放入variable容器中,目前執(zhí)行環(huán)境都是單獨(dú)的一個(gè)表達(dá)式樹(shù),在沒(méi)有對(duì)象與函數(shù)實(shí)現(xiàn)之前,這個(gè)執(zhí)行環(huán)境比較單純,這里只是提前考慮到執(zhí)行環(huán)境這個(gè)問(wèn)題,后期加入類(lèi)與函數(shù)實(shí)現(xiàn)的時(shí)候可以更方便改造。
后面我們?cè)谙庾兞康臅r(shí)候就需要從當(dāng)前這個(gè)環(huán)境中查找對(duì)應(yīng)的數(shù)據(jù),找到后打包成一個(gè)SemaASTNodeObject對(duì)象,他的具體執(zhí)行邏輯是這樣的:
SemaASTNodeObject getVariableValue(string key) {
if(variable.count(key) > 0) return variable[key];
DynamicDSL::SemaASTNodeObject object;
if(!json[key].is_null()) {
Json jsonValue = json[key];
JSONType type = SemaContext::getValueType(jsonValue);
if(type == DynamicDSL::JSONType_Bool) {
object.setValue(jsonValue.bool_value());
} else if(type == DynamicDSL::JSONType_Number) {
object.setValue(jsonValue.number_value());
} else if(type == DynamicDSL::JSONType_String) {
object.setValue(jsonValue.string_value());
} else if(type == DynamicDSL::JSONType_Object) {
auto context = SemaContext(jsonValue);
object.setValue(context);
}
}
return object;
}
首先從臨時(shí)變量中查找,如果找到了就直接返回,如果沒(méi)找到就從注入的Json對(duì)象就查找。
到此,我們的類(lèi)型系統(tǒng)就實(shí)現(xiàn)完成了, 我們還實(shí)現(xiàn)了棧幀執(zhí)行的環(huán)境上下文。
下一節(jié)我們將在此基礎(chǔ)上實(shí)現(xiàn)簡(jiǎn)最單純的棧幀
-
運(yùn)算
+關(guān)注
關(guān)注
0文章
132瀏覽量
26144 -
數(shù)據(jù)類(lèi)型
+關(guān)注
關(guān)注
0文章
237瀏覽量
13853 -
定義
+關(guān)注
關(guān)注
0文章
10瀏覽量
14434
發(fā)布評(píng)論請(qǐng)先 登錄
一個(gè)定時(shí)器設(shè)計(jì)的脈沖發(fā)生器?


EDA技術(shù):預(yù)定義數(shù)據(jù)類(lèi)型(1)#EDA技術(shù)

EDA技術(shù):預(yù)定義數(shù)據(jù)類(lèi)型(2)#EDA技術(shù)
單片機(jī)中宏定義與重新定義數(shù)據(jù)類(lèi)型(typedef)區(qū)別
求助,插補(bǔ)判別F 怎樣定義數(shù)據(jù)類(lèi)型?
LabVIEW自定義數(shù)據(jù)類(lèi)型
請(qǐng)問(wèn)如何自定義128位數(shù)據(jù)類(lèi)型
嵌入式ARM開(kāi)發(fā)之自定義數(shù)據(jù)類(lèi)型相關(guān)資料推薦
C++程序設(shè)計(jì)教程之自定義數(shù)據(jù)類(lèi)型的詳細(xì)資料說(shuō)明

SystemVerilog為工程師定義新的數(shù)據(jù)類(lèi)型提供了一種機(jī)制
用戶(hù)定義數(shù)據(jù)類(lèi)型的結(jié)構(gòu)
KUKA ENUM定義計(jì)數(shù)類(lèi)型簡(jiǎn)析

用戶(hù)自定義類(lèi)型

博途PLC1200/1500PLC用戶(hù)自定義數(shù)據(jù)類(lèi)型(UDT)

淺談PLC定義數(shù)據(jù)類(lèi)型的應(yīng)用

評(píng)論