riml 0.3.7 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/riml.rb +44 -19
- data/lib/riml/ast_rewriter.rb +1 -2
- data/lib/riml/backtrace_filter.rb +3 -1
- data/lib/riml/class_dependency_graph.rb +13 -18
- data/lib/riml/compiler.rb +1 -1
- data/version.rb +2 -2
- metadata +3 -3
data/lib/riml.rb
CHANGED
@@ -32,6 +32,9 @@ module Riml
|
|
32
32
|
EXTRACT_COMPILE_OPTIONS = lambda { |k,_| DEFAULT_COMPILE_OPTIONS.keys.include?(k.to_sym) }
|
33
33
|
EXTRACT_COMPILE_FILES_OPTIONS = lambda { |k,_| DEFAULT_COMPILE_FILES_OPTIONS.keys.include?(k.to_sym) }
|
34
34
|
|
35
|
+
FILENAME_OPTION_KEYS = [:commandline_filename, :sourced_filename]
|
36
|
+
EXTRACT_FILENAME_OPTIONS = lambda { |k,_| FILENAME_OPTION_KEYS.include?(k.to_sym) }
|
37
|
+
|
35
38
|
# lex code (String) into tokens (Array)
|
36
39
|
def self.lex(code)
|
37
40
|
Lexer.new(code).tokenize
|
@@ -53,13 +56,14 @@ module Riml
|
|
53
56
|
parser.options = DEFAULT_PARSE_OPTIONS.merge(parse_options)
|
54
57
|
compiler = Compiler.new
|
55
58
|
compiler.options = DEFAULT_COMPILE_OPTIONS.merge(compile_options)
|
56
|
-
|
59
|
+
filename_options = Hash[options.select(&EXTRACT_FILENAME_OPTIONS)]
|
60
|
+
do_compile(input, parser, compiler, filename_options)
|
57
61
|
end
|
58
62
|
|
59
63
|
# compile AST (Nodes), tokens (Array), code (String) or object that returns
|
60
64
|
# String from :read to output code (String). Writes file(s) if `input` is a
|
61
65
|
# File.
|
62
|
-
def self.do_compile(input, parser = Parser.new, compiler = Compiler.new)
|
66
|
+
def self.do_compile(input, parser = Parser.new, compiler = Compiler.new, filename_options = {})
|
63
67
|
if input.is_a?(Nodes)
|
64
68
|
nodes = input
|
65
69
|
elsif input.is_a?(String) || input.is_a?(Array)
|
@@ -73,17 +77,26 @@ module Riml
|
|
73
77
|
"code (String) or respond_to?(:read), is #{input.inspect}"
|
74
78
|
end
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
80
|
+
compiler.parser = parser
|
81
|
+
|
82
|
+
# This is to avoid cases where the file we're compiling from the
|
83
|
+
# commandline gets recompiled but put in a different location because
|
84
|
+
# it's also sourced, and `Riml.source_path` is set to a non-default value.
|
85
|
+
if input.is_a?(File)
|
86
|
+
pathname = Pathname.new(input.path)
|
87
|
+
full_path =
|
88
|
+
if pathname.absolute?
|
89
|
+
pathname.to_s
|
90
|
+
else
|
91
|
+
File.expand_path(input.path, compiler.output_dir || Dir.getwd)
|
92
|
+
end
|
93
|
+
compiler.sourced_files_compiled << full_path
|
81
94
|
end
|
82
95
|
|
83
96
|
output = compiler.compile(nodes)
|
84
97
|
|
85
98
|
if input.is_a?(File)
|
86
|
-
write_file(compiler, output, input.path,
|
99
|
+
write_file(compiler, output, input.path, filename_options)
|
87
100
|
else
|
88
101
|
output
|
89
102
|
end
|
@@ -125,7 +138,7 @@ module Riml
|
|
125
138
|
threads << Thread.new do
|
126
139
|
f = File.open(fname)
|
127
140
|
# `do_compile` will close file handle
|
128
|
-
do_compile(f, _parser, _compiler)
|
141
|
+
do_compile(f, _parser, _compiler, :commandline_filename => fname)
|
129
142
|
end
|
130
143
|
end
|
131
144
|
threads.each(&:join)
|
@@ -136,7 +149,7 @@ module Riml
|
|
136
149
|
fname = filenames.first
|
137
150
|
f = File.open(fname)
|
138
151
|
# `do_compile` will close file handle
|
139
|
-
with_file_rollback { do_compile(f, parser, compiler) }
|
152
|
+
with_file_rollback { do_compile(f, parser, compiler, :commandline_filename => fname) }
|
140
153
|
else
|
141
154
|
raise ArgumentError, "need filenames to compile"
|
142
155
|
end
|
@@ -268,10 +281,11 @@ module Riml
|
|
268
281
|
|
269
282
|
# This is for when another file is sourced within a file we're compiling.
|
270
283
|
def self.process_compile_queue!(compiler)
|
271
|
-
while
|
284
|
+
while paths = compiler.compile_queue.shift
|
285
|
+
basename, full_path = *paths
|
272
286
|
unless compiler.sourced_files_compiled.include?(full_path)
|
273
287
|
compiler.sourced_files_compiled << full_path
|
274
|
-
do_compile(File.open(full_path), compiler.parser, compiler)
|
288
|
+
do_compile(File.open(full_path), compiler.parser, compiler, :sourced_filename => basename)
|
275
289
|
end
|
276
290
|
end
|
277
291
|
end
|
@@ -280,19 +294,30 @@ module Riml
|
|
280
294
|
INCLUDE_COMMENT_FMT = File.read(File.expand_path("../riml/included.vim", __FILE__))
|
281
295
|
GET_SID_FUNCTION_SRC = File.read(File.expand_path("../riml/get_sid_function.vim", __FILE__))
|
282
296
|
|
283
|
-
|
297
|
+
# Files are written following these rules:
|
298
|
+
# If a filename is given from the commandline,
|
299
|
+
# 1) if the filename is absolute, output it to the directory in which the file resides
|
300
|
+
# 2) if there's an `output_dir` given, output the file to that directory
|
301
|
+
# 3) otherwise, output it into pwd
|
302
|
+
# If a filename is sourced,
|
303
|
+
# 1) if the filename is absolute, output it to the directory in which the file resides
|
304
|
+
# 2) otherwise, output it to the directory in which the `riml` file is found, checking `Riml.source_path`
|
305
|
+
def self.write_file(compiler, output, full_path, filename_options = {})
|
306
|
+
fname = filename_options[:commandline_filename] || filename_options[:sourced_filename]
|
307
|
+
fname or raise ArgumentError, "must pass correct filename_options"
|
284
308
|
# writing out a file that's compiled from cmdline, output into output_dir
|
285
|
-
output_dir = if
|
309
|
+
output_dir = if filename_options[:commandline_filename]
|
286
310
|
compiler.output_dir || Dir.getwd
|
287
311
|
# writing out a riml_source'd file
|
288
312
|
else
|
289
|
-
# absolute path for filename sent from
|
313
|
+
# absolute path for filename sent from riml_sourced files,
|
290
314
|
# output to that same directory if no --output-dir option is set
|
291
|
-
if
|
292
|
-
Pathname.new(
|
293
|
-
# relative path
|
315
|
+
if full_path[0, 1] == File::SEPARATOR && !compiler.output_dir
|
316
|
+
Pathname.new(full_path).parent.to_s
|
317
|
+
# relative path, join it with output_dir
|
294
318
|
else
|
295
|
-
|
319
|
+
rel_dir = Pathname.new(full_path).parent.to_s
|
320
|
+
File.join(compiler.output_dir || Dir.getwd, rel_dir)
|
296
321
|
end
|
297
322
|
end
|
298
323
|
basename_without_riml_ext = File.basename(fname).sub(/\.riml\Z/i, '')
|
data/lib/riml/ast_rewriter.rb
CHANGED
@@ -25,7 +25,6 @@ module Riml
|
|
25
25
|
# "lib1.riml" => [], "lib2.riml" => [] }
|
26
26
|
@included_and_sourced_file_refs = Hash.new { |h, k| h[k] = [] }
|
27
27
|
@class_dependency_graph = class_dependency_graph || ClassDependencyGraph.new
|
28
|
-
@class_dependency_graph.classes = @classes
|
29
28
|
@resolving_class_dependencies = nil
|
30
29
|
end
|
31
30
|
|
@@ -187,7 +186,7 @@ module Riml
|
|
187
186
|
|
188
187
|
def class_name_full_name(class_name)
|
189
188
|
return nil if class_name.nil?
|
190
|
-
if class_name[1
|
189
|
+
if class_name[1, 1] == ':'
|
191
190
|
class_name
|
192
191
|
else
|
193
192
|
ClassDefinitionNode::DEFAULT_SCOPE_MODIFIER + class_name
|
@@ -20,7 +20,9 @@ module Riml
|
|
20
20
|
raise ArgumentError, "first index must come before (or be equal to) last index"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
# check if `responds_to?(:debug)` because we don't want to have to require 'riml.rb'
|
24
|
+
# just for this
|
25
|
+
unless Riml.respond_to?(:debug) && Riml.debug
|
24
26
|
add_to_head = @error.backtrace[0...first_i] || []
|
25
27
|
add_to_tail = @error.backtrace[last_i...-1] || []
|
26
28
|
backtrace = @error.backtrace[first_i..last_i] || []
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# topological sorting module from stdlib
|
2
|
-
# uses Tarjan's algorithm for strongly connected components
|
3
2
|
require 'tsort'
|
4
3
|
|
5
4
|
module Riml
|
@@ -8,14 +7,12 @@ module Riml
|
|
8
7
|
include TSort
|
9
8
|
|
10
9
|
attr_reader :definition_graph, :encountered_graph
|
11
|
-
# for checking imported classes
|
12
|
-
attr_accessor :classes
|
13
10
|
|
14
11
|
# definition_graph: { "faster_car.riml" => { "s:FasterCar" => "s:Car" }, "car.riml" => { "s:Car" => nil } }
|
15
12
|
# encountered_graph: { "faster_car.riml" => ["s:FasterCar", "s:Car"], "car.riml" => ["s:Car"] }
|
16
|
-
def initialize
|
17
|
-
@definition_graph =
|
18
|
-
@encountered_graph =
|
13
|
+
def initialize
|
14
|
+
@definition_graph = {}
|
15
|
+
@encountered_graph = {}
|
19
16
|
@filename_graph = nil
|
20
17
|
end
|
21
18
|
|
@@ -48,19 +45,17 @@ module Riml
|
|
48
45
|
def prepare_filename_graph!
|
49
46
|
@filename_graph = {}
|
50
47
|
@encountered_graph.each do |filename, encountered_classes|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
@
|
48
|
+
dependent_class_names =
|
49
|
+
if @definition_graph[filename].nil?
|
50
|
+
encountered_classes
|
51
|
+
else
|
52
|
+
class_names_defined_in_file = @definition_graph[filename].keys
|
53
|
+
# all superclass names that this file depends on
|
54
|
+
class_names_dependent_by_superclass = @definition_graph[filename].values.compact - class_names_defined_in_file
|
55
|
+
class_names_dependent_by_use = encountered_classes - class_names_defined_in_file
|
56
|
+
class_names_dependent_by_superclass + class_names_dependent_by_use
|
56
57
|
end
|
57
|
-
|
58
|
-
end
|
59
|
-
defined_in_filename = @definition_graph[filename].keys
|
60
|
-
dependent_by_superclass = @definition_graph[filename].values.compact - defined_in_filename
|
61
|
-
dependent_by_use = encountered_classes - (defined_in_filename + dependent_by_superclass)
|
62
|
-
dependents = dependent_by_superclass + dependent_by_use
|
63
|
-
dependents.each do |dep|
|
58
|
+
dependent_class_names.each do |dep|
|
64
59
|
dependent_definition_fname = @definition_graph.detect { |fname, hash| hash.has_key?(dep) }.first rescue nil
|
65
60
|
if dependent_definition_fname
|
66
61
|
@filename_graph[filename] ||= []
|
data/lib/riml/compiler.rb
CHANGED
@@ -603,7 +603,7 @@ module Riml
|
|
603
603
|
if node.name == 'riml_source'
|
604
604
|
node.name = 'source'
|
605
605
|
node.each_existing_file! do |basename, full_path|
|
606
|
-
current_compiler(node).compile_queue << full_path
|
606
|
+
current_compiler(node).compile_queue << [basename, full_path]
|
607
607
|
end
|
608
608
|
elsif node.name == 'riml_include'
|
609
609
|
# riml_include has to be top-level
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: riml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: racc
|
@@ -153,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
153
153
|
version: '0'
|
154
154
|
segments:
|
155
155
|
- 0
|
156
|
-
hash:
|
156
|
+
hash: 4386632180611596538
|
157
157
|
requirements: []
|
158
158
|
rubyforge_project:
|
159
159
|
rubygems_version: 1.8.25
|