LoginSignup
11
10

More than 5 years have passed since last update.

orelangをrubyで

Posted at

@mattn氏の方じゃなくてこっちのやつ。
http://qiita.com/shuetsu@github/items/ac21e597265d6bb906dc

IExpression は lambda に押し込んで極力手を抜いていくスタイル。

エラー処理?
そんなものはない。

orelang.rb
#!/usr/bin/env ruby

module Orelang
  module Operator
    extend self
    attr_reader :op

    @op = {}

    @op["+"] = -> (e, args) {
      args.reduce(0) { |a, n| a + e.eval(n) }
    }
    @op["*"] = -> (e, args) {
      args.reduce(1) { |a, n| a * e.eval(n) }
    }
    @op["="] = -> (e, args) {
      e.eval(args[0]) === e.eval(args[1])
    }
    @op["set"] = -> (e, args) {
      e.vars[e.eval(args[0])] = e.eval(args[1])
    }
    @op["get"] = -> (e, args) {
      e.vars[e.eval(args[0])]
    }
    @op["until"] = -> (e, args) {
      e.eval(args[1]) while ! e.eval(args[0])
    }
    @op["step"] = -> (e, args) {
      args.reduce(0) { |r, n|
        r = e.eval(n)
      }
    }
  end

  class Engine
    attr_accessor :vars

    def initialize
      @vars = {}
    end

    def eval(expr)
      if expr.instance_of?(Array)
        op = Operator::op[expr[0]]
        args = expr[1..-1]
        -> {
          op.call(self, args)
        }
      else
        -> {
          expr
        }
      end.call
    end
  end
end
test_orelang.rb
#!/usr/bin/env ruby

require 'test/unit'
require "json"
require './orelang'

class TestOrelang < Test::Unit::TestCase
  def test_expr1
    engine = Orelang::Engine.new
    result = engine.eval(JSON.parse('["+", 1, 2, ["*", 3, 4]]'))
    assert_equal 15, result
  end

  def test_expr2
    str = <<-EOD
["step",
  ["set", "i", 10],
  ["set", "sum", 0],
  ["until", ["=", ["get", "i"], 0], [
    "step",
    ["set", "sum", ["+", ["get", "sum"], ["get", "i"]]],
    ["set", "i", ["+", ["get", "i"], -1]]
  ]],
  ["get", "sum"]
]
    EOD
    engine = Orelang::Engine.new
    result = engine.eval(JSON.parse(str))
    assert_equal 55, result
  end
end
11
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10