0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

定义数据类型

汽车电子技术 来源:程序猿搬砖 作者:坏人 2023-03-03 10:10 次阅读

上一节我们从模型上重建了AST节点,将antlr生成的表达式AST抽象成可直接运算的AST节点。

在运算之前我们必须首先定义出数据类型,定义出脚本支持的数据类型,这是运算的基础。

这一小节我们将定义出数据类型,在这里我们暂时定义四个数据类型:

enum Type { String, Number, Bool, Object, None };

完整的数据类型定义如下:

/// .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; }
        /// 获取数据的字符串描述
        const string getText();
        template

这里我们使用了any来包装我们具体的数据,所以我们的C++编译器需要设置成C++ 17

String类型我们使用的是std::string来实现。

Number类型则是上面提到的使用double来实现的。

Bool类型则是使用bool实现。

Object类型是单独定义的一个C++类型或者本身就是一个SemaASTNodeObject,后面单独说明。

通过std::any中的type()函数获取放置的数据信息来判断放置的数据的类型:

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;
    }
}

解包的时候判断再转换成具体的数据类即可,它的实现如下:

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

为里需要特别说明一下Object这个类型中的另外一个自定义数据类型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;
        }
    };
};

这个类定义了栈帧执行时的变量上下文环境,由于特殊的使用场景,还多定义了一个注入的Json对象,这个Json对象在使用模板一开始的时候就注入了。

栈运行过程中产生的临时变量放入variable容器中,目前执行环境都是单独的一个表达式树,在没有对象与函数实现之前,这个执行环境比较单纯,这里只是提前考虑到执行环境这个问题,后期加入类与函数实现的时候可以更方便改造。

后面我们在消解变量的时候就需要从当前这个环境中查找对应的数据,找到后打包成一个SemaASTNodeObject对象,他的具体执行逻辑是这样的:

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;
        }

首先从临时变量中查找,如果找到了就直接返回,如果没找到就从注入的Json对象就查找。

到此,我们的类型系统就实现完成了, 我们还实现了栈帧执行的环境上下文。

下一节我们将在此基础上实现简最单纯的栈帧

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 运算
    +关注

    关注

    0

    文章

    130

    浏览量

    25777
  • 数据类型
    +关注

    关注

    0

    文章

    236

    浏览量

    13608
  • 定义
    +关注

    关注

    0

    文章

    10

    浏览量

    14335
收藏 人收藏

    评论

    相关推荐

    一个定时器设计的脉冲发生器?

    定义数据类型为布尔型的输入变量start作为脉冲发生器的启动输入,置位有效。定义数据类型为时间类型的输入变量onTime作为脉冲发生器的接通
    的头像 发表于 02-07 10:45 2408次阅读
    一个定时器设计的脉冲发生器?

    EDA技术:预定义数据类型(1)#EDA技术

    edaEDA技术
    jf_49750429
    发布于 :2023年04月11日 23:40:51

    EDA技术:预定义数据类型(2)#EDA技术

    edaEDA技术
    jf_49750429
    发布于 :2023年04月11日 23:41:25

    单片机中宏定义与重新定义数据类型(typedef)区别

    单片机中宏定义与重新定义数据类型(typedef)区别,并且各自的优势(初学单片机)eg:#define SKY unsigned chartypedef unsigned char SKY
    发表于 08-27 20:21

    求助,插补判别F 怎样定义数据类型

    插补程序,x1 y1 x2 y2分别为起终点坐标;Xe Ye是起终点之间的横纵坐标差;N为插补步数F是判别结果,默认为0关于F,Xe,Ye,N;该怎么定义数据类型尤其是F,我试了char int
    发表于 02-25 18:25

    LabVIEW自定义数据类型

    一直只知道自定义控件,不知道自定义数据类型,直到有一天看到别人的后面板某控件左上角有个黑色小三角形,像这样,才知道有自定义数据类型,类似于C
    发表于 03-24 17:24

    请问如何自定义128位数据类型

    编程中有项目需要经常用到一百个左右的二级制数移位比较等操作,KEIL中数据类型最多的也就是32位或64位吧,能不能自己定义数据类型呢?比如定义一个 XXlong关键字,使用此关键字
    发表于 08-20 21:58

    嵌入式ARM开发之自定义数据类型相关资料推荐

    定义数据类型变量集合常量集合重命名struct(结构体)元素地址连续排列union(共用体)元素共用起始地址enum(枚举)被命名的整型常数集合typedef(声明类型)声明一个新的类型
    发表于 12-14 07:19

    C++程序设计教程之自定义数据类型的详细资料说明

    本文档详细介绍的是C++程序设计教程之自定义数据类型的详细资料说明主要内容包括了:1. 结构体类型,2. 共用体,3. 枚举类型,4. 用typedef声明
    发表于 03-14 16:04 1次下载
    C++程序设计教程之自<b class='flag-5'>定义</b><b class='flag-5'>数据类型</b>的详细资料说明

    SystemVerilog为工程师定义新的数据类型提供了一种机制

    为了使源代码更易于阅读和维护,typedef名称应该使用一种命名约定,使名称明显代表用户自定义类型。两种常见的命名约定是在用户自定义类型名称中添加“_t”后缀或“t_”前缀。本文系列文
    的头像 发表于 06-09 09:45 921次阅读

    用户定义数据类型的结构

    用户定义数据类型(UDTs)是你自己创建的特殊数据结构。因用户数据类型指派了名字,他们可以用很多次。一旦他们被定义,就可在CPU程序的任意点
    的头像 发表于 08-19 10:06 1424次阅读

    KUKA ENUM定义计数类型简析

    在 $CONFIG.DAT 中不允许使用用关键词 GLOBAL 在数据列表中定义数据类型
    的头像 发表于 01-16 10:28 1421次阅读
    KUKA ENUM<b class='flag-5'>定义</b>计数<b class='flag-5'>类型</b>简析

    用户自定义类型

    SystemVerilog还为工程师定义新的数据类型提供了一种机制。用户定义数据类型允许从现有数据类型创建新的
    的头像 发表于 02-09 14:53 1030次阅读
    用户自<b class='flag-5'>定义</b><b class='flag-5'>类型</b>

    博途PLC1200/1500PLC用户自定义数据类型(UDT)

    用户自定义数据类型可以包含基本数据类型(例如,INT bool string),以及 数组 ,结构体,以及PLC的专有数据类型等,而且用户自定义
    发表于 04-20 09:46 5次下载
    博途PLC1200/1500PLC用户自<b class='flag-5'>定义</b><b class='flag-5'>数据类型</b>(UDT)

    浅谈PLC定义数据类型的应用

    PLC定义数据类型以下用一个例子介绍PLC定义数据类型的应用,以便进一步理解PLC定义数据类型
    的头像 发表于 07-24 16:07 1287次阅读
    浅谈PLC<b class='flag-5'>定义</b><b class='flag-5'>数据类型</b>的应用