riml 0.3.1 → 0.3.2

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/Gemfile.lock CHANGED
@@ -3,12 +3,13 @@ GEM
3
3
  specs:
4
4
  minitest (2.5.1)
5
5
  racc (1.4.9)
6
- rake (10.0.4)
6
+ rake (10.1.0)
7
7
 
8
8
  PLATFORMS
9
9
  ruby
10
10
 
11
11
  DEPENDENCIES
12
+ bundler (~> 1.3)
12
13
  minitest (~> 2.5.1)
13
14
  racc
14
- rake
15
+ rake (~> 10.1.0)
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  require File.expand_path('../lib/environment', __FILE__)
2
2
  require 'rake/testtask'
3
+ require 'bundler/setup'
4
+ require 'bundler/gem_tasks'
3
5
 
4
6
  task :default => :test
5
7
  task :test => [:parser]
data/bin/riml CHANGED
@@ -20,7 +20,8 @@ module Riml
20
20
  options.check_syntax_files = []
21
21
  options.repl = false
22
22
  options.vi_readline = false
23
- options.output_dir = nil
23
+ options.readable = DEFAULT_COMPILE_OPTIONS[:readable]
24
+ options.output_dir = DEFAULT_COMPILE_FILES_OPTIONS[:output_dir]
24
25
 
25
26
  OptionParser.new do |opts|
26
27
  opts.banner = "Usage: riml [options] [file1][,file2]..."
@@ -59,6 +60,10 @@ module Riml
59
60
  options.output_dir = dir
60
61
  end
61
62
 
63
+ opts.on("-d", "--condensed", "Compiled VimL contains no extraneous newlines") do
64
+ options.readable = false
65
+ end
66
+
62
67
  opts.on("-i", "--interactive", "Start an interactive riml session (REPL).") do
63
68
  options.repl = true
64
69
  end
@@ -101,11 +106,16 @@ module Riml
101
106
  class << self
102
107
  def start
103
108
  options = Options.parse(ARGV)
104
-
109
+ compile_options = {
110
+ :readable => options.readable
111
+ }
112
+ compile_files_options = compile_options.merge(
113
+ :output_dir => options.output_dir
114
+ )
105
115
  if options.stdio
106
- puts Riml.compile($stdin.read)
116
+ puts Riml.compile($stdin.read, compile_options)
107
117
  elsif options.compile_files.any?
108
- Riml.compile_files(*options.compile_files, :output_dir => options.output_dir)
118
+ Riml.compile_files(*options.compile_files, compile_files_options)
109
119
  elsif options.check_syntax_files.any?
110
120
  files = options.check_syntax_files
111
121
  Riml.check_syntax_files(*files)
@@ -114,7 +124,7 @@ module Riml
114
124
  puts "ok (#{size} file#{'s' if size > 1})"
115
125
  elsif options.repl
116
126
  require 'repl'
117
- Riml::Repl.new(options.vi_readline).run
127
+ Riml::Repl.new(options.vi_readline, compile_options).run
118
128
  else
119
129
  ARGV.replace ['--help']
120
130
  start
@@ -0,0 +1,14 @@
1
+ module Riml
2
+ class BacktraceFilter
3
+ attr_reader :error
4
+
5
+ def initialize(error)
6
+ @error = error
7
+ end
8
+
9
+ def filter!
10
+ error.backtrace.clear
11
+ end
12
+
13
+ end
14
+ end
data/lib/compiler.rb CHANGED
@@ -3,7 +3,22 @@ require File.expand_path('../nodes', __FILE__)
3
3
  # visits AST nodes and translates them into VimL
4
4
  module Riml
5
5
  class Compiler
6
- attr_accessor :parser, :output_dir
6
+ attr_accessor :parser
7
+ attr_writer :options
8
+
9
+ # compiler options
10
+
11
+ def options
12
+ @options ||= {}
13
+ end
14
+
15
+ def output_dir
16
+ options[:output_dir]
17
+ end
18
+
19
+ def readable
20
+ options.has_key?(:readable) and options[:readable]
21
+ end
7
22
 
8
23
  # Base abstract visitor
9
24
  class Visitor
@@ -19,6 +34,8 @@ module Riml
19
34
  propagate_up_tree(node, output)
20
35
  end
21
36
 
37
+ protected
38
+
22
39
  def propagate_up_tree(node, output)
23
40
  node.parent_node.compiled_output << output.to_s unless @propagate_up_tree == false || node.parent_node.nil?
24
41
  end
@@ -26,6 +43,17 @@ module Riml
26
43
  def visitor_for_node(node, params={})
27
44
  Compiler.const_get("#{node.class.name.split('::').last}Visitor").new(params)
28
45
  end
46
+
47
+ def root_node(node)
48
+ @root_node ||= begin
49
+ node = node.parent until node.parent.nil?
50
+ node
51
+ end
52
+ end
53
+
54
+ def current_compiler(node)
55
+ root_node(node).current_compiler
56
+ end
29
57
  end
30
58
 
31
59
  class IfNodeVisitor < Visitor
@@ -452,6 +480,11 @@ module Riml
452
480
  end
453
481
  end
454
482
  node.compiled_output = declaration << body << "endfunction\n"
483
+ if current_compiler(node).readable
484
+ node.compiled_output << "\n"
485
+ else
486
+ node.compiled_output
487
+ end
455
488
  end
456
489
 
457
490
  private
@@ -565,7 +598,7 @@ module Riml
565
598
  if node.name == 'riml_source'
566
599
  node.name = 'source'
567
600
  node.each_existing_file! do |basename, full_path|
568
- root_node(node).current_compiler.compile_queue << full_path
601
+ current_compiler(node).compile_queue << full_path
569
602
  end
570
603
  elsif node.name == 'riml_include'
571
604
  # riml_include has to be top-level
@@ -575,7 +608,7 @@ module Riml
575
608
  end
576
609
  node.each_existing_file! do |basename, full_path|
577
610
  riml_src = File.read(full_path)
578
- node.compiled_output << root_node(node).current_compiler.compile_include(riml_src, basename)
611
+ node.compiled_output << current_compiler(node).compile_include(riml_src, basename)
579
612
  end
580
613
  return node.compiled_output
581
614
  end
@@ -585,13 +618,6 @@ module Riml
585
618
  node.compiled_output.sub!('.riml', '.vim')
586
619
  node.compiled_output
587
620
  end
588
-
589
- def root_node(node)
590
- @root_node ||= begin
591
- node = node.parent until node.parent.nil?
592
- node
593
- end
594
- end
595
621
  end
596
622
 
597
623
  class ForNodeVisitor < Visitor
data/lib/nodes.rb CHANGED
@@ -45,15 +45,19 @@ module Riml
45
45
  alias walk each
46
46
 
47
47
  def previous
48
- idx = index
49
- return unless idx
50
- parent.children.fetch(idx - 1)
48
+ idx = index_by_member
49
+ if idx && parent.members[idx - 1]
50
+ attr = parent.members[idx - 1]
51
+ return send(attr)
52
+ else
53
+ idx = index_by_children
54
+ return unless idx
55
+ parent.children.fetch(idx - 1)
56
+ end
51
57
  end
52
58
 
53
59
  def child_previous_to(node)
54
- idx = children.find_index(node)
55
- return unless idx
56
- children.fetch(idx - 1)
60
+ node.previous
57
61
  end
58
62
 
59
63
  def insert_before(node, new_node)
@@ -63,15 +67,19 @@ module Riml
63
67
  end
64
68
 
65
69
  def next
66
- idx = index
67
- return unless idx
68
- parent.children.fetch(idx + 1)
70
+ idx = index_by_member
71
+ if idx && parent.members[idx + 1]
72
+ attr = parent.members[idx + 1]
73
+ return parent.send(attr)
74
+ else
75
+ idx = index_by_children
76
+ return unless idx
77
+ parent.children.fetch(idx + 1)
78
+ end
69
79
  end
70
80
 
71
81
  def child_after(node)
72
- idx = children.find_index(node)
73
- return unless idx
74
- children.fetch(idx + 1)
82
+ node.next
75
83
  end
76
84
 
77
85
  def insert_after(node, new_node)
@@ -80,21 +88,44 @@ module Riml
80
88
  children.insert(idx + 1, new_node)
81
89
  end
82
90
 
83
- def index
91
+ def index_by_member
92
+ attrs = parent.members
93
+ attrs.each_with_index do |attr, i|
94
+ if parent.send(attr) == self
95
+ return i
96
+ end
97
+ end
98
+ nil
99
+ end
100
+
101
+ def index_by_children
84
102
  parent.children.find_index(self)
85
103
  end
86
104
 
87
105
  def remove
88
- idx = index
89
- parent.children.slice!(idx) if idx
106
+ idx = index_by_member
107
+ if idx
108
+ attr = parent.members[idx]
109
+ parent.send("#{attr}=", nil)
110
+ else
111
+ idx = index_by_children
112
+ parent.children.slice!(idx) if idx
113
+ end
90
114
  end
91
115
 
92
116
  def replace_with(new_node)
93
- idx = index
94
- return unless idx
95
- parent.children.insert(idx, new_node)
96
- parent.children.slice!(idx + 1)
97
- new_node
117
+ idx = index_by_member
118
+ if idx
119
+ attr = parent.members[idx]
120
+ new_node.parent = parent
121
+ parent.send("#{attr}=", new_node)
122
+ else
123
+ idx = index_by_children
124
+ return unless idx
125
+ new_node.parent = parent
126
+ parent.children.insert(idx, new_node)
127
+ parent.children.slice!(idx + 1)
128
+ end
98
129
  end
99
130
  end
100
131
 
@@ -539,9 +570,13 @@ module Riml
539
570
  end
540
571
 
541
572
  def children
542
- return [] unless interpolated?
543
- return value if nested?
544
- [value]
573
+ if !interpolated?
574
+ []
575
+ elsif nested?
576
+ value
577
+ else
578
+ [value]
579
+ end
545
580
  end
546
581
  end
547
582
 
@@ -740,7 +775,7 @@ module Riml
740
775
  end
741
776
  class WhileNode < ControlStructure; end
742
777
 
743
- class UnlessNode < ControlStructure
778
+ class UnlessNode < IfNode
744
779
  def initialize(*)
745
780
  super
746
781
  wrap_condition_in_parens!
data/lib/repl.rb CHANGED
@@ -9,7 +9,7 @@ require_relative 'riml'
9
9
  module Riml
10
10
  class Repl
11
11
  attr_reader :line
12
- attr_reader :parser, :compiler
12
+ attr_reader :parser, :compiler, :compiler_options
13
13
  private :parser, :compiler
14
14
 
15
15
  COMPILE_ON = %w(compile c)
@@ -22,9 +22,10 @@ clear previous class definitions: #{RELOAD_ON.join(', ')}
22
22
  exit repl: #{EXIT_ON.join(', ')}
23
23
  msg
24
24
 
25
- def initialize(vi_readline = false)
25
+ def initialize(vi_readline = false, compile_options = {})
26
26
  @indent_amount = 0
27
27
  @line = nil
28
+ @compiler_options = DEFAULT_COMPILE_OPTIONS.merge(compile_options)
28
29
  prepare_new_context
29
30
  Readline.vi_editing_mode if vi_readline
30
31
  trap(:INT) { reset!; puts }
@@ -55,6 +56,7 @@ msg
55
56
 
56
57
  def prepare_new_context
57
58
  @compiler = Compiler.new
59
+ @compiler.options = compiler_options
58
60
  @parser = Parser.new
59
61
  end
60
62
  alias reload! prepare_new_context
@@ -76,7 +78,7 @@ msg
76
78
  end
77
79
 
78
80
  def compile_unit!
79
- viml = Riml.compile(current_compilation_unit.join("\n"), parser, compiler).chomp
81
+ viml = Riml.do_compile(current_compilation_unit.join("\n"), parser, compiler).chomp
80
82
  puts viml, "\n"
81
83
  rescue => e
82
84
  print_error(e)
data/lib/riml.rb CHANGED
@@ -7,8 +7,15 @@ require 'lexer'
7
7
  require 'parser'
8
8
  require 'compiler'
9
9
  require 'warning_buffer'
10
+ require 'backtrace_filter'
10
11
 
11
12
  module Riml
13
+
14
+ DEFAULT_COMPILE_OPTIONS = { :readable => true }
15
+ DEFAULT_COMPILE_FILES_OPTIONS = DEFAULT_COMPILE_OPTIONS.merge(
16
+ :output_dir => nil
17
+ )
18
+
12
19
  # lex code (String) into tokens (Array)
13
20
  def self.lex(code)
14
21
  Lexer.new(code).tokenize
@@ -23,10 +30,17 @@ module Riml
23
30
  Parser.new.parse(input, ast_rewriter, filename)
24
31
  end
25
32
 
33
+ def self.compile(input, options = {})
34
+ parser = Parser.new
35
+ compiler = Compiler.new
36
+ compiler.options = DEFAULT_COMPILE_OPTIONS.merge(options)
37
+ do_compile(input, parser, compiler)
38
+ end
39
+
26
40
  # compile AST (Nodes), tokens (Array), code (String) or object that returns
27
41
  # String from :read to output code (String). Writes file(s) if `input` is a
28
42
  # File.
29
- def self.compile(input, parser = Parser.new, compiler = Compiler.new)
43
+ def self.do_compile(input, parser = Parser.new, compiler = Compiler.new)
30
44
  if input.is_a?(Nodes)
31
45
  nodes = input
32
46
  elsif input.is_a?(String) || input.is_a?(Array)
@@ -59,16 +73,15 @@ module Riml
59
73
  process_compile_queue!(compiler)
60
74
  end
61
75
 
62
- # expects `filenames` (String) arguments, to be readable files. Optional options (Hash) as
63
- # last argument.
76
+ # expects `filenames` (String) arguments, to be readable files.
77
+ # Optional options (Hash) as last argument.
64
78
  def self.compile_files(*filenames)
65
79
  parser, compiler = Parser.new, Compiler.new
66
80
 
67
81
  if filenames.last.is_a?(Hash)
68
- opts = filenames.pop
69
- if dir = opts[:output_dir]
70
- compiler.output_dir = dir
71
- end
82
+ compiler.options = DEFAULT_COMPILE_FILES_OPTIONS.merge(filenames.pop)
83
+ else
84
+ compiler.options = DEFAULT_COMPILE_FILES_OPTIONS.dup
72
85
  end
73
86
 
74
87
  if filenames.size > 1
@@ -78,22 +91,26 @@ module Riml
78
91
  _parser, _compiler = parser, compiler
79
92
  else
80
93
  _parser, _compiler = Parser.new, Compiler.new
81
- _compiler.output_dir = compiler.output_dir
94
+ _compiler.options = compiler.options
82
95
  end
83
96
  threads << Thread.new do
84
97
  f = File.open(fname)
85
- compile(f, _parser, _compiler)
98
+ # `do_compile` will close file handle
99
+ do_compile(f, _parser, _compiler)
86
100
  end
87
101
  end
88
102
  threads.each {|t| t.join}
89
103
  elsif filenames.size == 1
90
104
  fname = filenames.first
91
105
  f = File.open(fname)
92
- # `compile` will close file handle
93
- compile(f, parser, compiler)
106
+ # `do_compile` will close file handle
107
+ do_compile(f, parser, compiler)
94
108
  else
95
109
  raise ArgumentError, "need filenames to compile"
96
110
  end
111
+ rescue Riml::ParseError => pe
112
+ BacktraceFilter.new(pe).filter!
113
+ raise
97
114
  ensure
98
115
  flush_warnings
99
116
  end
@@ -183,7 +200,7 @@ module Riml
183
200
  while full_path = compiler.compile_queue.shift
184
201
  unless compiler.sourced_files_compiled.include?(full_path)
185
202
  compiler.sourced_files_compiled << full_path
186
- compile(File.open(full_path), compiler.parser, compiler)
203
+ do_compile(File.open(full_path), compiler.parser, compiler)
187
204
  end
188
205
  end
189
206
  end
@@ -210,6 +227,9 @@ module Riml
210
227
  basename_without_riml_ext = File.basename(fname).sub(/\.riml\Z/i, '')
211
228
  FileUtils.mkdir_p(output_dir) unless File.directory?(output_dir)
212
229
  full_path = File.join(output_dir, "#{basename_without_riml_ext}.vim")
230
+ if output[-2..-1] == "\n\n"
231
+ output.chomp!
232
+ end
213
233
  File.open(full_path, 'w') do |f|
214
234
  f.write FILE_HEADER + output
215
235
  end
data/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Riml
2
- # last changed: Sept. 14, 2013
3
- VERSION = [0,3,1]
2
+ # last changed: Sept. 22, 2013
3
+ VERSION = [0,3,2]
4
4
  end
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.1
4
+ version: 0.3.2
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-09-14 00:00:00.000000000 Z
12
+ date: 2013-09-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: racc
@@ -64,6 +64,7 @@ files:
64
64
  - lib/included.vim
65
65
  - lib/constants.rb
66
66
  - lib/parser.output
67
+ - lib/backtrace_filter.rb
67
68
  - lib/lexer.rb
68
69
  - lib/grammar.y
69
70
  - lib/compiler.rb