Module: Emfrp::Interpreter::Evaluater

Extended by:
Evaluater
Included in:
Evaluater
Defined in:
lib/emfrp/interpreter/evaluater.rb

Instance Method Summary collapse

Instance Method Details

#eval_exp(top, exp, env = {}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 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) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 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) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# 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) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
# 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 = , vars = {}) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# 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) ⇒ Object



137
138
139
140
141
142
143
# 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