埃菲尔铁塔(Eiffel):一种评估“ eval”之类的STRING表达式的方法

时间:2018-10-10 12:31:21

标签: eval eiffel

有没有一种方法可以评估Eiffel中的STRING表达式? (我知道一个大的错误源,但是机制很强大!)

寻找一种对数据库字段和类进行通用设置的方法,我正在尝试执行类似的操作。

fields_mapping: HASH_TABLE [ANY, STRING]
    do
        create Result.make (10)
        Result.put (name, "name")
        Result.put (surname, "surname")
        ...
    end

set_fields
    do
        across
            fields_mapping as field
        loop
            eval("set_" + field.key + "(" + field.item + ")")
        end
    end

我知道我可以使用代理来做到这一点,但对我来说似乎不太通用,因为我必须两次定义每个函数

  • fields_mapping
  • 在另一个我要进行JSON转换的fields_mapping

1 个答案:

答案 0 :(得分:1)

Eiffel的现有实现是编译而不是解释。因此,不支持对任意表达式的求值。使用反射类仍然可以使用给定值更新任意对象字段:

update_object (field_values: HASH_TABLE [ANY, STRING]; target: ANY)
        -- Update fields of object `target` with values from `field_values`.
    local
        object: REFLECTED_REFERENCE_OBJECT
        fields: like field_properties
        position: like {REFLECTED_OBJECT}.field_count
    do
        create object.make (target)
        fields := field_properties (object.dynamic_type)
        across
            field_values as v
        loop
            if attached fields [v.key] as f then
                position := f.position
                if {REFLECTOR}.field_conforms_to (v.item.generating_type.type_id, f.type_id) then
                    inspect object.field_type (position)
                    when {REFLECTOR_CONSTANTS}.integer_32_type then
                        object.set_integer_32_field (position, {INTEGER_32} / v.item)
                    when ... then
                        -- Other basic types.
                    when {REFLECTOR_CONSTANTS}.reference_type then
                        object.set_reference_field (position, v.item)
                    else
                        print ("Unhandled field type%N")
                    end
                else
                    print ("Field type mismatch%N")
                end
            end
        end
    end

上面的代码有点简化,因为它不处理类型SPECIALTUPLE以及用户定义的扩展类型。该代码依赖于记录类型信息的帮助程序功能,因此下次不应从头开始重新计算它:

field_properties (type_id: like {TYPE [ANY]}.type_id):
    HASH_TABLE [TUPLE [position: INTEGER; type_id: INTEGER], STRING]
        -- Positions and types of fields indexed by their name
        -- for a specified type ID `type_id`.
    local
        i: like {REFLECTOR}.field_count_of_type
    do
        Result := field_positions_table [type_id]
        if not attached Result then
            from
                i := {REFLECTOR}.field_count_of_type (type_id)
                create Result.make (i)
                field_positions_table.force (Result, type_id)
            until
                i <= 0
            loop
                Result [{REFLECTOR}.field_name_of_type (i, type_id)] :=
                    [i, {REFLECTOR}.field_static_type_of_type (i, type_id)]
                i := i - 1
            end
        end
    end

field_positions_table: HASH_TABLE [HASH_TABLE
    [TUPLE [position: INTEGER; type_id: INTEGER], STRING], INTEGER]
    once
        create Result.make (1)
    end

使用特征update_object并假定对象x分别具有类型foobar的字段INTEGER_32detachable STRING_8,以下代码

        field_values: HASH_TABLE [ANY, STRING]
    do
        create field_values.make (10)
        field_values ["foo"] := {INTEGER_32} 5
        field_values ["bar"] := " bottles"
        update_object (field_values, x)
        print (x.foo)
        print (x.bar)

将打印5 bottles,而不管对象x的先前状态如何。