#yaml #interpreter #variables #evaluate #dynamically #attributes #cross-language

nightly yamlate

一个跨语言的解释器库,可以动态评估给定的变量绑定下的YAML属性

2个版本

使用旧的Rust 2015

0.1.1 2016年6月10日
0.1.0 2015年12月26日

#1664编码

MIT 协议

95KB
2K SLoC

Rust 2K SLoC // 0.1% comments Python 275 SLoC // 0.2% comments

yamlate

一个跨语言的解释器库,可以动态评估给定的变量绑定下的YAML属性

Build Status

它做什么

给定一个变量到值的映射,它可以动态评估以特殊语言编写的YAML属性。它还可以更新映射中的变量,以便它可以改变其“状态”。

YAML中的语言功能以 '~>' 为前缀,以便解释器知道要评估它们。

假设用例

假设你想收集关于数千种昆虫的数据。每种昆虫都有不同的行为。有些根据季节改变翅膀颜色,有些在附近有其他昆虫时改变翅膀颜色。一旦昆虫改变翅膀颜色以靠近其他昆虫,其他昆虫就会离开,就没有其他昆虫靠近了。

一种建模方法是使用类似于策略模式的硬编码的昆虫行为。你可以为所有昆虫创建一千个不同的代码文件。

这种方法的一个问题是,为每个昆虫编写代码将数据绑定到代码,这使得非开发人员难以理解核心逻辑,并将数据绑定到特定语言(Java、Python等)。

另一种方法是使用像XML这样的标记语言或像YAML这样的数据序列化格式,以便将数据从代码中抽象出来。

这种方法的一个问题是,有很多复杂的逻辑,数据正在被转换(其他昆虫离开改变了环境),所以像YAML这样的东西将不足以应对。

使用Yamlate,你可以做类似的事情

cricket:
  wing_span: 3.5
  wing_color:
    - if:
      - '~> current_season == "spring"'
      - do:
        - 'red'
        else:
        - 'blue'
        
beetle:
  wing_span: 2.9
  wing_color:
    - if:
      - '~> another_beetle_nearby == 1'
      - do:
        - '~> another_beetle_nearby = 0'
        - 'blue'
        else:
        - 'red'

# etc... for all of the bugs

这使你能够拥有YAML的优势,同时能够模拟更复杂的逻辑。

你还可以用你喜欢的语言(目前只有python :P)编写程序来检索数据

lib = ctypes.cdll.LoadLibrary("../target/release/libyamlate.dylib")
yamlate = Yamlate(lib)

with yamlate.new_environment() as environment:
    environment.set_integer('another_beetle_nearby', 1)
    environment.set_string('current_season', 'spring')
        
    with open('../examples/bug.yaml', 'r') as yaml_file:
        data = yaml_file.read()
            
        with yamlate.new_yaml_from_str(data) as root_yaml:
            with root_yaml.hash_get('cricket') as cricket_yaml:
                with cricket_yaml.hash_get('wing_color') as wing_yaml:
                    with wing_yaml.evaluate(environment) as cricket_wing_result:
                        # should print 'red'
                        print cricket_wing_result.get_string()
                                        
            with root_yaml.hash_get('beetle') as beetle_yaml:
                with beetle_yaml.hash_get('wing_color') as wing_yaml:
                    with wing_yaml.evaluate(environment) as beetle_wing_result:
                        # should print 'blue'
                        print beetle_wing_result.get_string()
                        
                        # should print '0'
                        print environment.get_integer('another_beetle_nearby')

注意:python包装器相当冗长,希望我能将其重构得更好

完整的示例请参阅python/python_example_bug.py中的python文件和examples/bug.yaml中的YAML文件

为什么选择Rust?

  • 公开C接口,以便所有具有C FFI支持的(基本上是所有现代语言)语言都可以调用库
  • 性能特征类似于C和C++
  • 默认安全(防止不仅内存问题,还有其他一系列问题)
  • 开箱即用,易于测试(无需像C/C++那样进行令人困惑的链接或设置问题)

构建

您必须使用cargo将项目构建成动态库。

cargo build --release

生成的库在 ./target/release/libyamlate.dylib

贡献

欢迎贡献!请确保所有现有测试用例都通过(从cargo test运行)并且如果您正在添加功能,请添加额外的测试用例。

请确保您没有从clippy收到任何警告。

如果您收到clippy警告,警告之后的行将类似于以下内容

help: for further information visit https://github.com/Manishearth/rust-clippy/wiki#<clippy_warning_here>

您还应该确保您的代码使用了rustfmt进行格式化。

依赖项

~740KB
~16K SLoC