Class: Ree::ObjectCompiler

Inherits:
Object show all
Defined in:
lib/ree/object_compiler.rb

Instance Method Summary collapse

Constructor Details

#initialize(packages_facade) ⇒ ObjectCompiler

Returns a new instance of ObjectCompiler.



4
5
6
7
# File 'lib/ree/object_compiler.rb', line 4

def initialize(packages_facade)
  @packages_facade = packages_facade
  @link_validator = Ree::LinkValidator.new(packages_facade)
end

Instance Method Details

#call(package_name, object_name) ⇒ Ree::Object

Parameters:

  • package_name (Symbol)
  • object_name (Symbol)

Returns:



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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ree/object_compiler.rb', line 12

def call(package_name, object_name)
  @packages_facade.get_loaded_package(package_name)
  object = @packages_facade.load_package_object(package_name, object_name)

  object.set_as_compiled(true)
  Ree.logger.debug("compile_object(:#{package_name}, :#{object_name}), object_id=#{object.object_id}")

  klass = object.klass
  links = object.links

  links.each do |_|
    @link_validator.call(object, _)
    pckg = @packages_facade.get_loaded_package(_.package_name)
    obj = pckg.get_object(_.object_name)
    @packages_facade.load_package_object(pckg.name, obj.name)
  end

  eval_list = []

  eval_list.push("\n# #{object.klass}")
  indent = ""

  if object.with_caller?
    eval_list.push("def get_caller = @caller")
    eval_list.push("\n")
    eval_list.push("def set_caller(c)")
    indent = inc_indent(indent)
    eval_list.push("@caller = c")
    eval_list.push("self")
    indent = dec_indent(indent)
    eval_list.push("end")
  end

  class_links = []
  object_links = []

  links.each do |_|
    pckg = @packages_facade.get_loaded_package(_.package_name)
    obj = pckg.get_object(_.object_name)

    if [:class, :both].include?(_.target || obj.target)
      class_links << _
    end

    if [:object, :both].include?(_.target || obj.target)
      object_links << _
    end
  end

  if !class_links.empty?
    class_links.each do |_|
      pckg = @packages_facade.get_loaded_package(_.package_name)
      obj = pckg.get_object(_.object_name)

      if !obj.with_caller?
        eval_list.push(indent + "@#{_.as} = #{obj.klass}.new")
      end
    end

    eval_list.push("\n")
  end

  eval_list.push("\n")

  if object.singleton
    eval_list.push(indent + "if !const_defined?(:SEMAPHORE)")
    eval_list.push(indent + "  SEMAPHORE = Mutex.new")
    eval_list.push(indent + "  private_constant :SEMAPHORE")
    eval_list.push(indent + "end")
    eval_list.push("\n")
  end

  if object.factory || object.singleton
    eval_list.push(indent + "def self.new")

    if object.singleton
      eval_list.push(indent + "  SEMAPHORE.synchronize do")
      eval_list.push(indent + "    @__instance ||= begin")

      if object.factory
        eval_list.push(indent + "      super.#{object.factory}")
      else
        eval_list.push(indent + "      super")
      end

      eval_list.push(indent + "    end")
      eval_list.push(indent + "  end")
    else
      eval_list.push(indent + "  super.#{object.factory}")
    end

    eval_list.push(indent + "end")
  end

  eval_list.push("\n")
  eval_list.push(indent + "def initialize")

  indent = inc_indent(indent)

  links.each do |_|
    @link_validator.call(object, _)
    pckg = @packages_facade.get_loaded_package(_.package_name)
    obj = pckg.get_object(_.object_name)

    @packages_facade.load_package_object(pckg.name, obj.name)

    eval_list.push(indent + "@#{_.as} = #{obj.klass}.new")
  end

  if object.after_init?
    eval_list.push(indent + "#{object.after_init}")
  end

  if object.freeze?
    eval_list.push(indent + 'freeze')
  end

  indent = dec_indent(indent)

  eval_list.push(indent + 'end')

  if !class_links.empty?
    eval_list.push("\n")
    eval_list.push("class << self")
    indent = inc_indent(indent)

    class_links.each do |_|
      pckg = @packages_facade.get_loaded_package(_.package_name)
      obj = pckg.get_object(_.object_name)
      mount_fn(eval_list, obj, indent, _)
    end

    indent = dec_indent(indent)
    eval_list.push("end")
    eval_list.push("\n")
  end

  object_links.each do |_|
    pckg = @packages_facade.get_loaded_package(_.package_name)
    obj = pckg.get_object(_.object_name)
    mount_fn(eval_list, obj, indent, _)
  end

  indent = dec_indent(indent)

  str = eval_list.join("\n")

  klass.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
    #{str}
  ruby_eval

  # compile all linked objects
  links.each do |link|
    pckg = @packages_facade.get_loaded_package(link.package_name)
    obj = pckg.get_object(link.object_name)

    if !obj.compiled?
      self.call(obj.package_name, obj.name)
    end
  end

  object
end