Module: Emfrp::AlphaConvert

Extended by:
AlphaConvert
Included in:
AlphaConvert
Defined in:
lib/emfrp/pre_convert/alpha_convert.rb

Instance Method Summary collapse

Instance Method Details

#alpha_convert(top, syntax, tbl = nil) ⇒ Object



5
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/emfrp/pre_convert/alpha_convert.rb', line 5

def alpha_convert(top, syntax, tbl=nil)
  tbl ||= Hash.new{|h,k| h[k] = []}
  case syntax
  when InputDef
    alpha_convert(top, syntax[:init_exp], tbl) if syntax[:init_exp]
  when NodeDef
    alpha_convert(top, syntax[:init_exp], tbl) if syntax[:init_exp]
    if syntax[:params]
      check_duplicate_name(syntax[:params].map{|x| x[:name]})
      vars = syntax[:params].map{|x| x[:as]}
      check_duplicate_name(vars)
      vars.each do |v|
        tbl[v].push(syntax)
      end
      alpha_convert(top, syntax[:exp], tbl)
      vars.each do |v|
        tbl[v].pop
      end
    else
      syntax[:params] = []
      vars = (top[:nodes] + top[:inputs]).map{|x|
        [x[:name], SSymbol.new(:desc => x[:name][:desc] + "@last")]
      }.flatten
      vars.each do |v|
        tbl[v].push(syntax)
      end
      alpha_convert(top, syntax[:exp], tbl)
      vars.each do |v|
        tbl[v].pop
      end
    end
  when FuncDef
    vars = syntax[:params].map{|x| x[:name]}
    check_duplicate_name(vars)
    vars.each do |v|
      tbl[v].push(syntax)
    end
    alpha_convert(top, syntax[:exp], tbl)
    vars.each do |v|
      tbl[v].pop
    end
  when DataDef
    alpha_convert(top, syntax[:exp], tbl)
  when Case
    vars = syntax[:pattern].find_refs()
    check_duplicate_name(vars)
    vars.each do |v|
      tbl[v].push(syntax)
    end
    alpha_convert(top, syntax[:exp], tbl)
    vars.each do |v|
      tbl[v].pop
    end
  when VarRef
    if tbl[syntax[:name]].size == 0
      if top[:dict][:data_space][syntax[:name][:desc]]
        syntax[:binder] = top[:dict][:data_space][syntax[:name][:desc]]
      else
        PreConvert.err(:unbound, "Unbound variable `#{syntax[:name][:desc]}':\n", syntax)
      end
    else
      binder = tbl[syntax[:name]].last
      if binder.is_a?(NodeDef) && !binder[:params].find{|x| x[:as] == syntax[:name]}
        if syntax[:name][:desc] =~ /^(.+)@last$/
          name = SSymbol.new(:desc => $1)
          last = true
        else
          name = syntax[:name]
          last = false
        end
        binder[:params] << NodeRef.new(:as => syntax[:name], :name => name, :last => last)
      end
      syntax[:binder] = Link.new(binder)
    end
  when ValueConst, ValuePattern
    name = syntax[:name][:desc]
    if tvalue_link = top[:dict][:const_space][name]
      tvalue = tvalue_link.get
      if syntax[:args].size != tvalue[:params].size
        s = "#{syntax[:args].size} for #{tvalue[:params].size}"
        PreConvert.err(:arg_num, "Wrong number of arguments (#{s}) for `#{name}':\n", syntax)
      end
    else
      PreConvert.err(:undef, "Undefined value-constructor `#{name}':\n", syntax)
    end
    alpha_convert(top, syntax.values, tbl)
  when FuncCall
    name = syntax[:name][:desc]
    if func_link = top[:dict][:func_space][name]
      f = func_link.get
      if syntax[:args].size != f[:params].size
        s = "#{syntax[:args].size} for #{f[:params].size}"
        PreConvert.err(:arg_num, "Wrong number of arguments (#{s}) for `#{name}':\n", syntax)
      end
    else
      PreConvert.err(:undef, "Undefined function `#{name}':\n", syntax)
    end
    alpha_convert(top, syntax.values, tbl)
  when Syntax
    alpha_convert(top, syntax.values, tbl)
  when Array
    syntax.each{|e| alpha_convert(top, e, tbl)}
  end
end

#check_duplicate_name(names) ⇒ Object



110
111
112
113
114
115
116
117
# File 'lib/emfrp/pre_convert/alpha_convert.rb', line 110

def check_duplicate_name(names)
  names.each do |name|
    dups = names.select{|x| x == name}
    if dups.size > 1
      PreConvert.err(:dup, "Duplicate variable names `#{name[:desc]}':\n", *dups)
    end
  end
end