Class: Emfrp::Top

Inherits:
Syntax
  • Object
show all
Defined in:
lib/emfrp/syntax.rb,
lib/emfrp/compile/c/syntax_codegen.rb

Constant Summary collapse

ATTRS =
[
  :inputs,
  :outputs,
  :uses,
  :datas,
  :funcs,
  :nodes,
  :types,
  :infixes,
  :ptypes,
  :pfuncs,
  :itypes,
  :ifuncs,
  :commands,
  :newnodes,
]

Instance Method Summary collapse

Methods inherited from Syntax

#[], #deep_copy, #traverse_all_syntax

Constructor Details

#initialize(*tops) ⇒ Top

Returns a new instance of Top.



116
117
118
119
120
121
122
123
124
# File 'lib/emfrp/syntax.rb', line 116

def initialize(*tops)
  ATTRS.each do |a|
    self[a] = []
    tops.each do |h|
      self[a] += h[a] if h[a]
    end
  end
  self[:module_name] = tops.map{|x| x[:module_name]}.find{|x| x}
end

Instance Method Details

#add(d) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/emfrp/syntax.rb', line 126

def add(d)
  case d
  when DataDef then self[:datas] << d
  when FuncDef then self[:funcs] << d
  when TypeDef then self[:types] << d
  else raise "assertion error: unsupported Def-type"
  end
end

#codegen(ct, ar) ⇒ 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
# File 'lib/emfrp/compile/c/syntax_codegen.rb', line 6

def codegen(ct, ar)
  self[:dict][:itype_space].each do |k, v|
    v.get.struct_gen(ct)
    v.get.constructor_gen(ct)
    v.get.marker_gen(ct)
  end
  self[:inputs].each do |i|
    if i[:init_exp]
      i.init_func_gen(ct)
      ct.define_init_stmt "#{i.node_var_name(ct)}[last_side] = #{i.init_func_name(ct)}();"
    end
    i.node_var_gen(ct)
  end
  self[:dict][:sorted_nodes].each_with_index do |n, i|
    node = n.get
    node.func_gen(ct)
    node.node_var_gen(ct)
    if node[:init_exp]
      node.init_func_gen(ct)
      ct.define_init_stmt "#{node.node_var_name(ct)}[last_side] = #{node.init_func_name(ct)}();"
      t = ct.tdef(node)
      if t.is_a?(TypeDef) && !t.enum?(ct)
        ct.define_init_stmt "#{t.marker_func_name(ct)}(#{node.node_var_name(ct)}[last_side], #{ar.ref_pos_last(node) + 1});"
      end
    end
  end
  self[:dict][:ifunc_space].each do |k, v|
    v.get.codegen(ct)
  end
  self[:dict][:used_pfuncs].each do |v|
    v.get.codegen(ct)
  end
  self[:dict][:sorted_datas].reverse.each do |v|
    v.get.codegen(ct)
  end
  memory_gen(ct, ar)
  main_gen(ct, ar)
  io_proto_gen(ct)
end

#io_proto_gen(ct) ⇒ Object



110
111
112
113
# File 'lib/emfrp/compile/c/syntax_codegen.rb', line 110

def io_proto_gen(ct)
  ct.define_proto("void", "Input", self[:inputs].map{|x| ct.tref(x) + "*"}, :extern)
  ct.define_proto("void", "Output", self[:outputs].map{|x| ct.tref(x) + "*"}, :extern)
end

#main_gen(ct, ar) ⇒ Object



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/compile/c/syntax_codegen.rb', line 71

def main_gen(ct, ar)
  ct.define_func("void", "Activate" + self[:module_name][:desc], [], :none) do |x|
    x << "int current_side = 0, last_side = 1;"
    ct.define_init_stmt "Counter = NodeSize + 1;"
    ct.define_init_stmt "refreshMark();"
    ct.init_stmts.each do |i|
      x << i
    end
    stmts = []
    stmts << "Counter = 1;"
    inputs = self[:inputs].map{|x| "&#{x.node_var_name(ct)}[current_side]"}.join(", ")
    stmts << "Input(#{inputs});"
    self[:dict][:sorted_nodes].each do |n|
      node = n.get
      args = node[:params].map do |x|
        pn = self[:dict][:node_space][x[:name][:desc]].get
        "#{pn.node_var_name(ct)}[#{x[:last] ? "last_side" : "current_side"}]"
      end
      output_arg = "&#{node.node_var_name(ct)}[current_side]"
      stmts << "#{node.node_func_name(ct)}(#{[*args, output_arg].join(", ")});"
      t = ct.tdef(node)
      if t.is_a?(TypeDef) && !t.enum?(ct)
        mark_val = "Counter + #{ar.life_point(node)}"
        stmts << "#{t.marker_func_name(ct)}(#{node.node_var_name(ct)}[current_side], #{mark_val});"
      end
      stmts << "Counter++;"
    end
    outputs = self[:outputs].map do |x|
      node = self[:dict][:node_space][x[:name][:desc]].get
      "&#{node.node_var_name(ct)}[current_side]"
    end
    stmts << "Output(#{outputs.join(", ")});"
    stmts << "refreshMark();"
    stmts << "current_side ^= 1;"
    stmts << "last_side ^= 1;"
    x << ct.make_block("while (1) {", stmts, "}")
  end
end

#memory_gen(ct, ar) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/emfrp/compile/c/syntax_codegen.rb', line 46

def memory_gen(ct, ar)
  max_memory = ar.requirement()
  max_memory.each do |t, i|
    t = t.get
    next if t[:static] || t.enum?(ct)
    ct.define_global_var("struct #{t.struct_name(ct)}", "#{t.memory_name(ct)}[#{i}]")
    ct.define_global_var("int", "#{t.memory_size_name(ct)}", "#{i}")
    ct.define_global_var("int", "#{t.memory_counter_name(ct)}", "0")
  end
  ct.define_global_var("int", "Counter", "1")
  ct.define_global_var("int", "NodeSize", "#{self[:dict][:sorted_nodes].size}")
  ct.define_func("void", "refreshMark", []) do |x|
    x << "int i;"
    max_memory.each do |t, i|
      t = t.get
      next if t[:static] || t.enum?(ct)
      mn = "#{t.memory_name(ct)}[i].mark"
      stmts = []
      stmts << "if (#{mn} < Counter) #{mn} = 0;"
      stmts << "else #{mn} -= Counter - 1;"
      x << ct.make_block("for (i = 0; i < #{t.memory_size_name(ct)}; i++) {", stmts, "}")
    end
  end
end