module Emfrp::Interpreter::Evaluater
Public Instance Methods
eval_exp(top, exp, env={})
click to toggle source
# File lib/emfrp/interpreter/evaluater.rb, line 6 def eval_exp(top, exp, env={}) case exp when FuncCall case f = top[:dict][:func_space][exp[:name][:desc]].get when PrimFuncDef if ruby_exp = f[:foreigns].find{|x| x[:language][:desc] == "ruby"} proc_str = "proc{|#{f[:params].map{|x| x[:name][:desc]}.join(",")}| #{ruby_exp[:desc]}}" return eval(proc_str).call(*exp[:args].map{|e| eval_exp(top, e, env)}) else raise "Primitive Function `#{f[:name][:desc]}` is not defined for ruby" end when FuncDef f[:params].map{|param| [param[:name], Link.new(f)]}.zip(exp[:args]).each do |key, arg| env[key] = eval_exp(top, arg, env) end return eval_exp(top, f[:exp], env) end when ValueConst return [exp[:name][:desc].to_sym] + exp[:args].map{|e| eval_exp(top, e, env)} when LiteralIntegral return exp[:entity][:desc].to_i when LiteralChar return exp[:entity].ord when LiteralFloating return exp[:entity][:desc].to_f when VarRef key = [exp[:name], exp[:binder]] unless env[key] if exp[:binder].get.is_a?(DataDef) env[key] = eval_exp(top, exp[:binder].get[:exp], env) else raise "Assertion error: #{key} is unbound" end end return env[key] when ParenthExp return eval_exp(top, exp[:exp], env) when MatchExp left_val = eval_exp(top, exp[:exp], env) exp[:cases].each do |c| if match_result = pattern_match(c, left_val) return eval_exp(top, c[:exp], env.merge(match_result)) end end raise "pattern match fail" when SkipExp throw :skip, :skip else raise "Unexpected expression type #{exp.class} (bug)" end end
eval_module(top, input_exps, current_state, last_state, replacement)
click to toggle source
# File lib/emfrp/interpreter/evaluater.rb, line 71 def eval_module(top, input_exps, current_state, last_state, replacement) top[:inputs].zip(input_exps).each do |i, e| current_state[i] = eval_exp(top, e) end unless last_state last_state = {} (top[:inputs] + top[:nodes]).each do |d| last_state[d] = eval_exp(top, d[:init_exp]) if d[:init_exp] end end (top[:inputs] + top[:nodes]).each do |d| eval_node(top, d, current_state, last_state, replacement) end return top[:outputs].map do |x| eval_node(top, top[:dict][:node_space][x[:name][:desc]].get, current_state, last_state, replacement) end end
eval_node(top, node_def, current_state, last_state, replacement)
click to toggle source
# File lib/emfrp/interpreter/evaluater.rb, line 89 def eval_node(top, node_def, current_state, last_state, replacement) if replacement[node_def[:name][:desc]] rep_node = replacement[node_def[:name][:desc]] return eval_node(top, rep_node, current_state, last_state, replacement) end return current_state[node_def] if current_state[node_def] env = {} node_def[:params].each do |param| key = [param[:as], Link.new(node_def)] pn = top[:dict][:node_space][param[:name][:desc]].get if param[:last] raise "Assertion error" unless last_state[pn] if rep_node = replacement[param[:name][:desc]] env[key] = last_state[rep_node] else env[key] = last_state[pn] end else env[key] = eval_node(top, pn, current_state, last_state, replacement) end end res = catch(:skip){ eval_exp(top, node_def[:exp], env) } return current_state[node_def] = res == :skip ? last_state[node_def] : res end
eval_node_as_func(top, node_def, exps)
click to toggle source
# File lib/emfrp/interpreter/evaluater.rb, line 58 def eval_node_as_func(top, node_def, exps) env = {} if node_def[:params].size != exps.size raise "Assertion error: invalid length of args" end node_def[:params].map{|param| [param[:as], Link.new(node_def)]}.zip(exps).each do |key, arg| env[key] = eval_exp(top, arg, env) end return catch(:skip) do return eval_exp(top, node_def[:exp], env) end end
pattern_match(c, v, pattern=c[:pattern], vars={})
click to toggle source
# File lib/emfrp/interpreter/evaluater.rb, line 114 def pattern_match(c, v, pattern=c[:pattern], vars={}) if pattern[:ref] key = [pattern[:ref], Link.new(c)] vars[key] = v end case pattern when ValuePattern if v.is_a?(Array) && pattern[:name][:desc].to_sym == v[0] res = v.drop(1).zip(pattern[:args]).all? do |ch_v, ch_p| pattern_match(c, ch_v, ch_p, vars) end return vars if res end when IntegralPattern if v.is_a?(Integer) && pattern[:val][:entity][:desc].to_i == v return vars end when AnyPattern return vars end return nil end
value_to_s(val)
click to toggle source
# File lib/emfrp/interpreter/evaluater.rb, line 137 def value_to_s(val) if val.is_a?(Array) && val.first.is_a?(Symbol) "#{val.first}" + (val.size > 1 ? "(#{val.drop(1).map{|x| value_to_s(x)}.join(", ")})" : "") else val.to_s end end