rltk 2.2.1 → 3.0.0

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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +12 -12
  3. data/README.md +458 -285
  4. data/Rakefile +99 -92
  5. data/lib/rltk/ast.rb +221 -126
  6. data/lib/rltk/cfg.rb +218 -239
  7. data/lib/rltk/cg/basic_block.rb +1 -1
  8. data/lib/rltk/cg/bindings.rb +9 -26
  9. data/lib/rltk/cg/builder.rb +40 -8
  10. data/lib/rltk/cg/context.rb +1 -1
  11. data/lib/rltk/cg/contractor.rb +51 -0
  12. data/lib/rltk/cg/execution_engine.rb +45 -8
  13. data/lib/rltk/cg/function.rb +12 -2
  14. data/lib/rltk/cg/generated_bindings.rb +2541 -575
  15. data/lib/rltk/cg/generic_value.rb +2 -2
  16. data/lib/rltk/cg/instruction.rb +104 -83
  17. data/lib/rltk/cg/llvm.rb +44 -3
  18. data/lib/rltk/cg/memory_buffer.rb +22 -5
  19. data/lib/rltk/cg/module.rb +85 -36
  20. data/lib/rltk/cg/old_generated_bindings.rb +6152 -0
  21. data/lib/rltk/cg/pass_manager.rb +87 -43
  22. data/lib/rltk/cg/support.rb +2 -4
  23. data/lib/rltk/cg/target.rb +158 -28
  24. data/lib/rltk/cg/triple.rb +8 -8
  25. data/lib/rltk/cg/type.rb +69 -25
  26. data/lib/rltk/cg/value.rb +107 -66
  27. data/lib/rltk/cg.rb +16 -17
  28. data/lib/rltk/lexer.rb +21 -11
  29. data/lib/rltk/lexers/calculator.rb +1 -1
  30. data/lib/rltk/lexers/ebnf.rb +8 -7
  31. data/lib/rltk/parser.rb +300 -247
  32. data/lib/rltk/parsers/infix_calc.rb +1 -1
  33. data/lib/rltk/parsers/postfix_calc.rb +2 -2
  34. data/lib/rltk/parsers/prefix_calc.rb +2 -2
  35. data/lib/rltk/token.rb +1 -2
  36. data/lib/rltk/version.rb +3 -3
  37. data/lib/rltk.rb +6 -6
  38. data/test/cg/tc_basic_block.rb +83 -0
  39. data/test/cg/tc_control_flow.rb +191 -0
  40. data/test/cg/tc_function.rb +54 -0
  41. data/test/cg/tc_generic_value.rb +33 -0
  42. data/test/cg/tc_instruction.rb +256 -0
  43. data/test/cg/tc_llvm.rb +25 -0
  44. data/test/cg/tc_math.rb +88 -0
  45. data/test/cg/tc_module.rb +89 -0
  46. data/test/cg/tc_transforms.rb +68 -0
  47. data/test/cg/tc_type.rb +69 -0
  48. data/test/cg/tc_value.rb +151 -0
  49. data/test/cg/ts_cg.rb +23 -0
  50. data/test/tc_ast.rb +105 -8
  51. data/test/tc_cfg.rb +63 -48
  52. data/test/tc_lexer.rb +84 -96
  53. data/test/tc_parser.rb +224 -52
  54. data/test/tc_token.rb +6 -6
  55. data/test/ts_rltk.rb +12 -15
  56. metadata +149 -75
  57. data/lib/rltk/cg/generated_extended_bindings.rb +0 -287
  58. data/lib/rltk/util/abstract_class.rb +0 -25
  59. data/lib/rltk/util/monkeys.rb +0 -129
data/test/tc_cfg.rb CHANGED
@@ -7,8 +7,8 @@
7
7
  # Requires #
8
8
  ############
9
9
 
10
- # Standard Library
11
- require 'test/unit'
10
+ # Gems
11
+ require 'minitest/autorun'
12
12
 
13
13
  # Ruby Language Toolkit
14
14
  require 'rltk/cfg'
@@ -17,7 +17,7 @@ require 'rltk/cfg'
17
17
  # Classes and Modules #
18
18
  #######################
19
19
 
20
- class CFGTester < Test::Unit::TestCase
20
+ class CFGTester < Minitest::Test
21
21
  def setup
22
22
  @grammar = RLTK::CFG.new
23
23
 
@@ -35,59 +35,74 @@ class CFGTester < Test::Unit::TestCase
35
35
  def test_callback
36
36
  grammar = RLTK::CFG.new
37
37
 
38
- first = true
39
- grammar.callback do |p, type, num|
40
- assert_not_nil(p)
41
- assert_equal(type, :'?')
38
+ call_count = 0
39
+ grammar.callback do |type, which, p|
40
+ refute_nil(p)
41
+ assert_equal(type, :optional)
42
42
 
43
- if first
44
- assert_equal(num, :first)
45
- first = false
46
- else
47
- assert_equal(num, :second)
43
+ case call_count
44
+ when 0 then assert_equal(:empty, which)
45
+ when 1 then assert_equal(:nonempty, which)
48
46
  end
47
+
48
+ call_count += 1
49
49
  end
50
50
 
51
51
  grammar.production(:a, 'A?') { |a| a }
52
+ assert_equal(2, call_count)
52
53
 
53
- first = true
54
- grammar.callback do |p, type, num|
55
- assert_not_nil(p)
56
- assert_equal(type, :*)
54
+ call_count = 0
55
+ grammar.callback do |type, which, p|
56
+ refute_nil(p)
57
57
 
58
- if first
59
- assert_equal(num, :first)
60
- first = false
61
- else
62
- assert_equal(num, :second)
58
+ case call_count
59
+ when 0
60
+ assert_equal(:elp, type)
61
+ assert_equal(:empty, which)
62
+
63
+ when 1
64
+ assert_equal(:elp, type)
65
+ assert_equal(:nonempty, which)
66
+
67
+ when 2
68
+ assert_equal(:nelp, type)
69
+ assert_equal(:single, which)
70
+
71
+ when 3
72
+ assert_equal(:nelp, type)
73
+ assert_equal(:multiple, which)
63
74
  end
75
+
76
+ call_count += 1
64
77
  end
65
78
 
66
79
  grammar.production(:a, 'A*') { |a| a }
80
+ assert_equal(4, call_count)
67
81
 
68
- first = true
69
- grammar.callback do |p, type, num|
70
- assert_not_nil(p)
71
- assert_equal(type, :+)
82
+ call_count = 0
83
+ grammar.callback do |type, which, p|
84
+ refute_nil(p)
85
+ assert_equal(type, :nelp)
72
86
 
73
- if first
74
- assert_equal(num, :first)
75
- first = false
76
- else
77
- assert_equal(num, :second)
87
+ case call_count
88
+ when 0 then assert_equal(:single, which)
89
+ when 1 then assert_equal(:multiple, which)
78
90
  end
91
+
92
+ call_count += 1
79
93
  end
80
94
 
81
95
  grammar.production(:a, 'A+') { |a| a }
96
+ assert_equal(2, call_count)
82
97
  end
83
98
 
84
99
  def test_first_set
85
100
  @grammar.first_set(:s).each do |sym|
86
- assert([:A, :B].include?(sym))
101
+ assert_includes([:A, :B], sym)
87
102
  end
88
103
 
89
- assert_equal(@grammar.first_set(:b), [:G])
90
- assert_equal(@grammar.first_set(:a), [:G])
104
+ assert_equal([:G], @grammar.first_set(:b))
105
+ assert_equal([:G], @grammar.first_set(:a))
91
106
  end
92
107
 
93
108
  def test_follow_set
@@ -103,13 +118,13 @@ class CFGTester < Test::Unit::TestCase
103
118
  end
104
119
 
105
120
  def test_is_nonterminal
106
- assert_equal(RLTK::CFG::is_nonterminal?(:lowercase), true)
107
- assert_equal(RLTK::CFG::is_nonterminal?(:UPERCASE), false)
121
+ assert(RLTK::CFG::is_nonterminal?(:lowercase))
122
+ assert(!RLTK::CFG::is_nonterminal?(:UPERCASE))
108
123
  end
109
124
 
110
125
  def test_is_terminal
111
- assert_equal(RLTK::CFG::is_terminal?(:lowercase), false)
112
- assert_equal(RLTK::CFG::is_terminal?(:UPERCASE), true)
126
+ assert(!RLTK::CFG::is_terminal?(:lowercase))
127
+ assert(RLTK::CFG::is_terminal?(:UPERCASE))
113
128
  end
114
129
 
115
130
  def test_item
@@ -117,25 +132,25 @@ class CFGTester < Test::Unit::TestCase
117
132
  i1 = i0.copy
118
133
 
119
134
  assert_equal(i0, i1)
120
- assert_equal(i0.at_end?, false)
121
- assert_equal(i0.next_symbol, :b)
135
+ assert(!i0.at_end?)
136
+ assert_equal(:b, i0.next_symbol)
122
137
 
123
138
  i0.advance
124
139
 
125
- assert_not_equal(i0, i1)
126
- assert_equal(i0.at_end?, false)
127
- assert_equal(i0.next_symbol, :C)
140
+ refute_equal(i0, i1)
141
+ assert(!i0.at_end?)
142
+ assert_equal(:C, i0.next_symbol)
128
143
 
129
144
  i0.advance
130
- assert_equal(i0.at_end?, false)
131
- assert_equal(i0.next_symbol, :D)
145
+ assert(!i0.at_end?)
146
+ assert_equal(:D, i0.next_symbol)
132
147
 
133
148
  i0.advance
134
- assert_equal(i0.at_end?, false)
135
- assert_equal(i0.next_symbol, :e)
149
+ assert(!i0.at_end?)
150
+ assert_equal(:e, i0.next_symbol)
136
151
 
137
152
  i0.advance
138
- assert_equal(i0.at_end?, true)
153
+ assert(i0.at_end?)
139
154
  assert_nil(i0.next_symbol)
140
155
  end
141
156
 
@@ -144,6 +159,6 @@ class CFGTester < Test::Unit::TestCase
144
159
  p1 = p0.copy
145
160
 
146
161
  assert_equal(p0, p1)
147
- assert_equal(p0.last_terminal, :D)
162
+ assert_equal(:D, p0.last_terminal)
148
163
  end
149
164
  end
data/test/tc_lexer.rb CHANGED
@@ -7,8 +7,8 @@
7
7
  # Requires #
8
8
  ############
9
9
 
10
- # Standard Library
11
- require 'test/unit'
10
+ # Gems
11
+ require 'minitest/autorun'
12
12
 
13
13
  # Ruby Language Toolkit
14
14
  require 'rltk/token'
@@ -20,21 +20,21 @@ require 'rltk/lexers/ebnf'
20
20
  # Classes and Modules #
21
21
  #######################
22
22
 
23
- class LexerTester < Test::Unit::TestCase
23
+ class LexerTester < Minitest::Test
24
24
  class ABLongest < RLTK::Lexer
25
- rule(/a+/) { :APLUS }
26
- rule(/b+/) { :BPLUS }
25
+ rule(/a+/) { :APLUS }
26
+ rule(/b+/) { :BPLUS }
27
27
 
28
- rule(/a+b+/) { :APLUSBPLUS }
28
+ rule(/a+b+/) { :APLUSBPLUS }
29
29
  end
30
30
 
31
31
  class ABFirst < RLTK::Lexer
32
32
  match_first
33
33
 
34
- rule(/a+/) { :APLUS }
35
- rule(/b+/) { :BPLUS }
34
+ rule(/a+/) { :APLUS }
35
+ rule(/b+/) { :BPLUS }
36
36
 
37
- rule(/a+b+/) { :APLUSBPLUS }
37
+ rule(/a+b+/) { :APLUSBPLUS }
38
38
  end
39
39
 
40
40
  class ENVLexer < RLTK::Lexer
@@ -53,21 +53,21 @@ class LexerTester < Test::Unit::TestCase
53
53
  end
54
54
 
55
55
  class FlagLexer < RLTK::Lexer
56
- rule(/a/) { set_flag(:a); :A }
56
+ rule(/a/) { set_flag(:a); :A }
57
57
  rule(/\s/)
58
58
 
59
- rule(/b/, :default, [:a]) { set_flag(:b); :B }
60
- rule(/c/, :default, [:a, :b]) { :C }
59
+ rule(/b/, :default, [:a]) { set_flag(:b); :B }
60
+ rule(/c/, :default, [:a, :b]) { :C }
61
61
  end
62
62
 
63
63
  class StateLexer < RLTK::Lexer
64
- rule(/a/) { :A }
64
+ rule(/a/) { :A }
65
65
  rule(/\s/)
66
66
 
67
- rule(/\(\*/) { push_state(:comment) }
67
+ rule(/\(\*/) { push_state(:comment) }
68
68
 
69
- rule(/\(\*/, :comment) { push_state(:comment) }
70
- rule(/\*\)/, :comment) { pop_state }
69
+ rule(/\(\*/, :comment) { push_state(:comment) }
70
+ rule(/\*\)/, :comment) { pop_state }
71
71
  rule(/./, :comment)
72
72
  end
73
73
 
@@ -76,19 +76,18 @@ class LexerTester < Test::Unit::TestCase
76
76
  end
77
77
 
78
78
  def test_calc
79
- expected =
80
- [
81
- RLTK::Token.new(:NUM, 1),
82
-
83
- RLTK::Token.new(:PLS),
84
- RLTK::Token.new(:SUB),
85
- RLTK::Token.new(:MUL),
86
- RLTK::Token.new(:DIV),
87
-
88
- RLTK::Token.new(:LPAREN),
89
- RLTK::Token.new(:RPAREN),
90
- RLTK::Token.new(:EOS)
91
- ]
79
+ expected = [
80
+ RLTK::Token.new(:NUM, 1),
81
+
82
+ RLTK::Token.new(:PLS),
83
+ RLTK::Token.new(:SUB),
84
+ RLTK::Token.new(:MUL),
85
+ RLTK::Token.new(:DIV),
86
+
87
+ RLTK::Token.new(:LPAREN),
88
+ RLTK::Token.new(:RPAREN),
89
+ RLTK::Token.new(:EOS)
90
+ ]
92
91
 
93
92
  actual = RLTK::Lexers::Calculator.lex('1 + - * / ( )')
94
93
 
@@ -96,16 +95,15 @@ class LexerTester < Test::Unit::TestCase
96
95
  end
97
96
 
98
97
  def test_ebnf
99
- expected =
100
- [
101
- RLTK::Token.new(:NONTERM, :aaa),
102
- RLTK::Token.new(:TERM, :BBB),
103
-
104
- RLTK::Token.new(:*),
105
- RLTK::Token.new(:+),
106
- RLTK::Token.new(:'?'),
107
- RLTK::Token.new(:EOS)
108
- ]
98
+ expected = [
99
+ RLTK::Token.new(:NONTERM, :aaa),
100
+ RLTK::Token.new(:TERM, :BBB),
101
+
102
+ RLTK::Token.new(:STAR),
103
+ RLTK::Token.new(:PLUS),
104
+ RLTK::Token.new(:QUESTION),
105
+ RLTK::Token.new(:EOS)
106
+ ]
109
107
 
110
108
  actual = RLTK::Lexers::EBNF.lex('aaa BBB * + ?')
111
109
 
@@ -113,13 +111,12 @@ class LexerTester < Test::Unit::TestCase
113
111
  end
114
112
 
115
113
  def test_environment
116
- expected =
117
- [
118
- RLTK::Token.new(:A, 0),
119
- RLTK::Token.new(:A, 1),
120
- RLTK::Token.new(:A, 2),
121
- RLTK::Token.new(:EOS)
122
- ]
114
+ expected = [
115
+ RLTK::Token.new(:A, 0),
116
+ RLTK::Token.new(:A, 1),
117
+ RLTK::Token.new(:A, 2),
118
+ RLTK::Token.new(:EOS)
119
+ ]
123
120
 
124
121
  actual = ENVLexer.lex('aaa')
125
122
 
@@ -129,24 +126,22 @@ class LexerTester < Test::Unit::TestCase
129
126
 
130
127
  assert_equal(expected, lexer.lex('aaa'))
131
128
 
132
- expected =
133
- [
134
- RLTK::Token.new(:A, 3),
135
- RLTK::Token.new(:A, 4),
136
- RLTK::Token.new(:A, 5),
137
- RLTK::Token.new(:EOS)
138
- ]
129
+ expected = [
130
+ RLTK::Token.new(:A, 3),
131
+ RLTK::Token.new(:A, 4),
132
+ RLTK::Token.new(:A, 5),
133
+ RLTK::Token.new(:EOS)
134
+ ]
139
135
 
140
136
  assert_equal(expected, lexer.lex('aaa'))
141
137
  end
142
138
 
143
139
  def test_first_match
144
- expected =
145
- [
146
- RLTK::Token.new(:APLUS),
147
- RLTK::Token.new(:BPLUS),
148
- RLTK::Token.new(:EOS)
149
- ]
140
+ expected = [
141
+ RLTK::Token.new(:APLUS),
142
+ RLTK::Token.new(:BPLUS),
143
+ RLTK::Token.new(:EOS)
144
+ ]
150
145
 
151
146
  actual = ABFirst.lex('aaabbb')
152
147
 
@@ -155,49 +150,43 @@ class LexerTester < Test::Unit::TestCase
155
150
 
156
151
  def test_flags
157
152
 
158
- assert_raise(RLTK::LexingError) { FlagLexer.lex('b') }
159
- assert_raise(RLTK::LexingError) { FlagLexer.lex('ac') }
153
+ assert_raises(RLTK::LexingError) { FlagLexer.lex('b') }
154
+ assert_raises(RLTK::LexingError) { FlagLexer.lex('ac') }
160
155
 
161
- expected =
162
- [
163
- RLTK::Token.new(:A),
164
- RLTK::Token.new(:B),
165
- RLTK::Token.new(:C),
166
- RLTK::Token.new(:EOS)
167
- ]
156
+ expected = [
157
+ RLTK::Token.new(:A),
158
+ RLTK::Token.new(:B),
159
+ RLTK::Token.new(:C),
160
+ RLTK::Token.new(:EOS)
161
+ ]
168
162
 
169
163
  actual = FlagLexer.lex('abc')
170
164
  assert_equal(expected, actual)
171
165
 
172
- expected =
173
- [
174
- RLTK::Token.new(:A),
175
- RLTK::Token.new(:B),
176
- RLTK::Token.new(:C),
177
- RLTK::Token.new(:A),
178
- RLTK::Token.new(:B),
179
- RLTK::Token.new(:C),
180
- RLTK::Token.new(:EOS)
181
- ]
166
+ expected = [
167
+ RLTK::Token.new(:A),
168
+ RLTK::Token.new(:B),
169
+ RLTK::Token.new(:C),
170
+ RLTK::Token.new(:A),
171
+ RLTK::Token.new(:B),
172
+ RLTK::Token.new(:C),
173
+ RLTK::Token.new(:EOS)
174
+ ]
182
175
 
183
176
  actual = FlagLexer.lex('abcabc')
184
177
  assert_equal(expected, actual)
185
178
  end
186
179
 
187
180
  def test_lex
188
- assert_raise(RLTK::LexingError) { ABFirst.lex('aaabbbCCC') }
189
- assert_raise(RLTK::LexingError) { ABLongest.lex('aaabbbCCC') }
190
-
191
- assert_nothing_raised(RLTK::LexingError) { ABFirst.lex('aaabbb') }
192
- assert_nothing_raised(RLTK::LexingError) { ABLongest.lex('aaabbb') }
181
+ assert_raises(RLTK::LexingError) { ABFirst.lex('aaabbbCCC') }
182
+ assert_raises(RLTK::LexingError) { ABLongest.lex('aaabbbCCC') }
193
183
  end
194
184
 
195
185
  def test_longest_match
196
- expected =
197
- [
198
- RLTK::Token.new(:APLUSBPLUS),
199
- RLTK::Token.new(:EOS)
200
- ]
186
+ expected = [
187
+ RLTK::Token.new(:APLUSBPLUS),
188
+ RLTK::Token.new(:EOS)
189
+ ]
201
190
 
202
191
  actual = ABLongest.lex('aaabbb')
203
192
 
@@ -205,19 +194,18 @@ class LexerTester < Test::Unit::TestCase
205
194
  end
206
195
 
207
196
  def test_match_data
208
- expected = [RLTK::Token.new(:FOO, ['', 'ccc']), RLTK::Token.new(:EOS)]
209
- actual = MatchDataLexer.lex('accc')
197
+ expected = [RLTK::Token.new(:FOO, ['', 'ccc']), RLTK::Token.new(:EOS)]
198
+ actual = MatchDataLexer.lex('accc')
210
199
 
211
200
  assert_equal(expected, actual)
212
201
  end
213
202
 
214
203
  def test_state
215
- expected =
216
- [
217
- RLTK::Token.new(:A),
218
- RLTK::Token.new(:A),
219
- RLTK::Token.new(:EOS)
220
- ]
204
+ expected = [
205
+ RLTK::Token.new(:A),
206
+ RLTK::Token.new(:A),
207
+ RLTK::Token.new(:EOS)
208
+ ]
221
209
 
222
210
  actual = StateLexer.lex('a (* bbb *) a')
223
211
  assert_equal(expected, actual)