class Emfrp::Monofy

Constants

IFunc
IType

Public Class Methods

monofy(top) click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 21
def self.monofy(top)
  m = new(top)
  m.monofy()
  m.sort_nodes()
end
new(top) click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 27
def initialize(top)
  @top = top
  @datas = []
  @itypes = []
  @ifuncs = []
  @update = false
end

Public Instance Methods

copy_def(x, mapping={}, tbl={}) click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 162
def copy_def(x, mapping={}, tbl={})
  case x
  when Syntax
    new_x = x.dup
    mapping[x] = new_x
    x.keys.each do |k|
      new_x[k] = copy_def(x[k], mapping, tbl)
    end
    if new_x.has_key?(:typing)
      new_x[:typing] = x[:typing].clone_utype(tbl)
    end
    if new_x.has_key?(:binder) && mapping[new_x[:binder].get]
      new_x[:binder] = Link.new(mapping[new_x[:binder].get])
    end
    if new_x.has_key?(:type_def) && mapping[new_x[:type_def].get]
      new_x[:type_def] = Link.new(mapping[new_x[:type_def].get])
    end
    return new_x
  when Array
    return x.map{|a| copy_def(a, mapping, tbl)}
  else
    return x
  end
end
monofy() click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 71
def monofy
  visited = {}
  @top[:outputs].each do |x|
    monofy_node(@top[:dict][:node_space][x[:name][:desc]].get, visited)
  end
  while @update
    @update = false
    @datas.each do |d|
      key = Link.new(d)
      unless @top[:dict][:sorted_datas].find{|x| x == key}
        monofy_exp(d[:exp])
        @top[:dict][:sorted_datas] << key
      end
    end
    @ifuncs.each do |ifunc|
      key = ifunc.typing_name_array + [ifunc.func_def[:name][:desc]]
      unless @top[:dict][:ifunc_space][key]
        new_f = copy_def(ifunc.func_def)
        xs = ([new_f] + new_f[:params]).map{|x| x[:typing]}
        ys = [ifunc.typing] + ifunc.param_typings
        xs.zip(ys).each{|x, y| x.unify(y)}
        @top[:dict][:ifunc_space][key] = Link.new(new_f)
        monofy_exp(new_f[:exp])
      end
    end
    @itypes.each do |itype|
      key = itype.typing.to_uniq_str
      unless @top[:dict][:itype_space][key]
        new_t = copy_def(itype.type_def)
        new_t[:tvalues].each{|x| x[:typing].unify(itype.typing)}
        @top[:dict][:itype_space][key] = Link.new(new_t)
      end
    end
  end
  @top[:dict][:sorted_datas] = @datas.map{|x| Link.new(x)}
end
monofy_exp(exp, visited={}) click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 120
def monofy_exp(exp, visited={})
  if exp.is_a?(Syntax) && exp.has_key?(:typing)
    case type_def = @top[:dict][:type_space][exp[:typing].typename].get
    when TypeDef
      itype = IType.new(exp[:typing], type_def)
      unless @itypes.find{|x| x == itype}
        @itypes << itype
        @update = true
      end
    when PrimTypeDef
      # do nothing
    else
      raise
    end
  end
  case exp
  when FuncCall
    case f = @top[:dict][:func_space][exp[:name][:desc]].get
    when FuncDef
      ifunc = IFunc.new(exp[:typing], exp[:args].map{|x| x[:typing]}, f)
      unless @ifuncs.find{|x| x == ifunc}
        @ifuncs << ifunc
        @update = true
      end
    when PrimFuncDef
      @top[:dict][:used_pfuncs] << Link.new(f)
      @top[:dict][:used_pfuncs].uniq!
    end
    monofy_exp(exp[:args])
  when VarRef
    d = exp[:binder].get
    if d.is_a?(DataDef) && !@datas.find{|x| x[:name] == d[:name]}
      @datas << d
      @update = true
    end
  when Syntax
    monofy_exp(exp.values)
  when Array
    exp.each{|x| monofy_exp(x)}
  end
end
monofy_node(node, visited) click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 108
def monofy_node(node, visited)
  return if visited[node]
  visited[node] = true
  monofy_exp(node[:init_exp]) if node[:init_exp]
  if node.is_a?(NodeDef)
    monofy_exp(node[:exp])
    node[:params].each do |param|
      monofy_node(@top[:dict][:node_space][param[:name][:desc]].get, visited)
    end
  end
end
sort_nodes() click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 54
def sort_nodes
  evaluated = Hash[@top[:inputs].map{|x| [x[:name], true]}]
  nodes = used_nodes()
  que = nodes.select{|n| n[:params].all?{|p| p[:last] || evaluated[p[:name]]}}
  res = []
  until que.empty?
    node = que.shift
    next if evaluated[node[:name]]
    evaluated[node[:name]] = true
    que += nodes.select do |n|
      n[:params].all?{|p| p[:last] || evaluated[p[:name]]}
    end
    res << node
  end
  @top[:dict][:sorted_nodes] = res.map{|x| Link.new(x)}
end
used_nodes() click to toggle source
# File lib/emfrp/compile/c/monofy.rb, line 35
def used_nodes
  used = []
  visited = Set.new
  f = proc do |n|
    used << n
    visited << n[:name]
    n[:params].each do |p|
      pn = @top[:dict][:node_space][p[:name][:desc]].get
      if pn.is_a?(NodeDef)
        if !visited.include?(p[:name])
          f.call(pn)
        end
      end
    end
  end
  @top[:outputs].each{|x| f.call(@top[:dict][:node_space][x[:name][:desc]].get)}
  return used.uniq
end