riml 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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