Class: Gloo::Persist::FileLoader

Inherits:
Object
  • Object
show all
Defined in:
lib/gloo/persist/file_loader.rb

Constant Summary collapse

BEGIN_BLOCK =
'BEGIN'.freeze
END_BLOCK =
'END'.freeze
SPACE_CNT =
2
LIB_DIRECTIVE =

A 'load lib name' (or 'load ext name') statement at the top of a file, before the first object declaration. It makes a core library's object types available to the declarations that follow. Same syntax as the load verb, but the loader runs it before building the object tree instead of a script running it afterward.

/\A(?:load|ld)\s+(?:lib|ext)\s+\S+\s*\z/i.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(engine, pn) ⇒ FileLoader

Set up a file storage for an object.



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/gloo/persist/file_loader.rb', line 28

def initialize( engine, pn )
  @engine = engine
  @mech = @engine.platform.get_file_mech( @engine )
  @pn = pn
  @tabs = 0
  @obj = nil
  @in_multiline = false
  @exiting_multiline = false
  @in_block = false
  @block_value = ''
  @body_started = false
  @debug = false
end

Instance Attribute Details

#objObject (readonly)

Returns the value of attribute obj.



23
24
25
# File 'lib/gloo/persist/file_loader.rb', line 23

def obj
  @obj
end

Instance Method Details

#determine_indent(line) ⇒ Object

Determine the relative indent level for the line.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/gloo/persist/file_loader.rb', line 127

def determine_indent( line )
  tabs = tab_count( line )
  @indent = 0 # same level as prior line
  if tabs > @tabs # indent
    # TODO:  What if indent is more than one more level?
    @tabs = tabs
    @indent = 1
  elsif tabs < @tabs # outdent
    diff = @tabs - tabs
    @tabs -= diff
    @indent -= diff
  end
  puts "tabs: #{@tabs}, indent: #{@indent}, line: #{line}" if @debug
end

#handle_one_line(line) ⇒ Object

Process one one of the file we're loading.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/gloo/persist/file_loader.rb', line 94

def handle_one_line( line )
  if line.strip.end_with? BEGIN_BLOCK
    @in_block = true
    @save_line = line
  elsif @in_block
    if line.strip == END_BLOCK
      @in_block = false
      determine_indent @save_line
      process_line @save_line
    else
      @block_value << line
    end
  else
    determine_indent line
    process_line line
  end
end

#join_continuations(data) ⇒ Object

Join continuation lines.



87
88
89
# File 'lib/gloo/persist/file_loader.rb', line 87

def join_continuations( data )
  return data.gsub( "\\\n", '' )
end

#loadObject

Load the objects from the file.



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
# File 'lib/gloo/persist/file_loader.rb', line 45

def load
  unless @mech.exist?( @pn )
    @engine.err "File '#{@pn}' does not exist."
    return
  end

  @engine.log.debug "Loading file '#{@pn}'"
  @tabs = 0
  @parent_stack = []
  @parent = @engine.heap.root
  @parent_stack.push @parent
  f = @mech.read( @pn )

  f = join_continuations( f )

  f.each_line do |line|
    next if skip_line? line

    if !@body_started && line =~ LIB_DIRECTIVE
      run_lib_directive line
      next
    end
    @body_started = true

    handle_one_line line
  end
end

#process_line(line) ⇒ Object

Process one line and add objects.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/gloo/persist/file_loader.rb', line 145

def process_line( line )
  # reset multiline unless we're actually indented
  if @in_multiline && @multi_indent > @indent
    puts "Done multiline mi: #{@multi_indent}, i: #{@indent}" if @debug
    @in_multiline = false
    @exiting_multiline = true
  end

  if @in_multiline
    @last.add_line line
  else
    setup_process_obj_line
    process_obj_line line
  end
end

#process_obj_line(line) ⇒ Object

Process one line and add objects.



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/gloo/persist/file_loader.rb', line 184

def process_obj_line( line )
  name, type, value = split_line( line )
  unless @block_value == ''
    value = @block_value
    @block_value = ''
  end
  params = { name: name, type: type, value: value, parent: @parent }
  @last = @engine.factory.create( params )

  if value&.empty? && @last&.multiline_value?
    @multi_indent = 0
    @in_multiline = true
    puts "*** Start multiline. multi_indent: #{@multi_indent}" if @debug
  end

  @obj = @last if @obj.nil?
end

#run_lib_directive(line) ⇒ Object

Run a top-of-file 'load lib name' directive. It goes through the same load verb a script would use, so libraries are loaded and their object types registered before the declarations that depend on them are parsed.



79
80
81
82
# File 'lib/gloo/persist/file_loader.rb', line 79

def run_lib_directive( line )
  @engine.log.debug "Loading file directive: #{line.strip}"
  @engine.parser.run line.strip
end

#setup_process_obj_lineObject

Setup and get ready to process an object line.



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/gloo/persist/file_loader.rb', line 164

def setup_process_obj_line
  if @exiting_multiline
    @exiting_multiline = false
    @indent += 1
  end

  if @indent.positive?
    @parent = @last
    @parent_stack.push @parent
  elsif @indent.negative?
    @indent.abs.times do
      @parent_stack.pop
      @parent = @parent_stack.last
    end
  end
end

#skip_line?(line) ⇒ Boolean

Is this line a comment or a blank line? If so we'll skip it.

Returns:

  • (Boolean)


116
117
118
119
120
121
122
# File 'lib/gloo/persist/file_loader.rb', line 116

def skip_line?( line )
  line = line.strip
  return true if line.empty?
  return true if line[ 0 ] == '#'

  return false
end

#split_line(line) ⇒ Object

Split the line into 3 parts.



222
223
224
225
# File 'lib/gloo/persist/file_loader.rb', line 222

def split_line( line )
  o = LineSplitter.new( line, @tabs )
  return o.split
end

#tab_count(line) ⇒ Object

Get the number of leading tabs.



205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/gloo/persist/file_loader.rb', line 205

def tab_count( line )
  i = 0

  if line[ i ] == ' '
    i += 1 while line[ i ] == ' '
    tab_equiv = ( i / SPACE_CNT ).to_i
    puts "Found #{i} spaces => #{tab_equiv}" if @debug
    return tab_equiv
  end

  i += 1 while line[ i ] == "\t"
  return i
end