loxxy 0.4.09 → 0.4.10
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +32 -304
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +1 -1
- data/lib/loxxy/ast/ast_builder.rb +1 -1
- data/lib/loxxy/back_end/engine.rb +2 -0
- data/lib/loxxy/back_end/environment.rb +1 -1
- data/lib/loxxy/front_end/scanner.rb +9 -9
- data/lib/loxxy/interpreter.rb +3 -3
- data/lib/loxxy/version.rb +1 -1
- data/loxxy.gemspec +8 -7
- data/spec/back_end/engine_spec.rb +21 -19
- data/spec/back_end/environment_spec.rb +20 -19
- data/spec/back_end/symbol_table_spec.rb +67 -67
- data/spec/back_end/variable_spec.rb +14 -13
- data/spec/datatype/boolean_spec.rb +9 -8
- data/spec/datatype/lx_string_spec.rb +16 -15
- data/spec/datatype/nil_spec.rb +5 -5
- data/spec/datatype/number_spec.rb +18 -17
- data/spec/front_end/parser_spec.rb +110 -110
- data/spec/front_end/raw_parser_spec.rb +25 -25
- data/spec/front_end/scanner_spec.rb +77 -76
- data/spec/interpreter_spec.rb +114 -118
- data/spec/loxxy_spec.rb +1 -1
- metadata +33 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21a1cbd9499c50fc448238c4b46fabf32add037e813d073df2e88126682076cb
|
4
|
+
data.tar.gz: 54b00da85e3b48be9506ad9f5c52e4844c26491dcf3007a360af2c5a925296d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a35a3aefa589ba7d2d5d0c3e2f9b21b837855ea46e93817e890649d5a0a8fc7f0d02b3fd2fdf0072c0f2b7ccdd4ad6c77e4c585f7dd08fe6394ee5f08dca23af
|
7
|
+
data.tar.gz: e5d91111f82398021791ef5e6c3f0625e3b16527aec81948dc730381b6da882a86ec7c6a11fd25273c2b8e06efb781421ee2de9b586833f0eb234cbbfcc67982
|
data/.rubocop.yml
CHANGED
@@ -2,10 +2,18 @@ AllCops:
|
|
2
2
|
Exclude:
|
3
3
|
- 'exp/**/*'
|
4
4
|
- 'demo/**/*'
|
5
|
+
NewCops: enable
|
6
|
+
SuggestExtensions: false
|
5
7
|
|
6
8
|
Gemspec/DeprecatedAttributeAssignment:
|
7
9
|
Enabled: true
|
8
10
|
|
11
|
+
Gemspec/DevelopmentDependencies:
|
12
|
+
EnforcedStyle: gemspec
|
13
|
+
|
14
|
+
Gemspec/RequireMFA: # new in 1.23
|
15
|
+
Enabled: true
|
16
|
+
|
9
17
|
Layout/ArgumentAlignment:
|
10
18
|
Enabled: false
|
11
19
|
|
@@ -60,117 +68,12 @@ Layout/MultilineMethodCallBraceLayout:
|
|
60
68
|
Enabled: true
|
61
69
|
EnforcedStyle: same_line
|
62
70
|
|
63
|
-
Layout/SpaceAroundOperators:
|
64
|
-
Enabled: true
|
65
|
-
|
66
|
-
Layout/SpaceBeforeBrackets:
|
67
|
-
Enabled: true
|
68
|
-
|
69
|
-
Layout/SpaceInsideParens:
|
70
|
-
Enabled: true
|
71
|
-
|
72
|
-
Layout/IndentationStyle:
|
73
|
-
Enabled: true
|
74
|
-
|
75
|
-
Layout/SpaceAroundMethodCallOperator:
|
76
|
-
Enabled: true
|
77
|
-
|
78
|
-
Layout/TrailingEmptyLines:
|
79
|
-
Enabled: true
|
80
|
-
|
81
|
-
Layout/TrailingWhitespace:
|
82
|
-
Enabled: true
|
83
|
-
|
84
|
-
Lint/AmbiguousAssignment:
|
85
|
-
Enabled: true
|
86
|
-
|
87
71
|
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
88
72
|
Enabled: true
|
89
73
|
|
90
|
-
Lint/AmbiguousRange:
|
91
|
-
Enabled: true
|
92
|
-
|
93
|
-
Lint/DeprecatedConstants:
|
94
|
-
Enabled: true
|
95
|
-
|
96
|
-
Lint/DuplicateBranch:
|
97
|
-
Enabled: true
|
98
|
-
|
99
|
-
Lint/DuplicateRegexpCharacterClassElement:
|
100
|
-
Enabled: true
|
101
|
-
|
102
|
-
Lint/EmptyBlock:
|
103
|
-
Enabled: true
|
104
|
-
|
105
74
|
Lint/EmptyClass:
|
106
75
|
Enabled: false
|
107
76
|
|
108
|
-
Lint/EmptyInPattern:
|
109
|
-
Enabled: true
|
110
|
-
|
111
|
-
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
112
|
-
Enabled: true
|
113
|
-
|
114
|
-
Lint/LambdaWithoutLiteralBlock:
|
115
|
-
Enabled: true
|
116
|
-
|
117
|
-
Lint/Loop:
|
118
|
-
Enabled: true
|
119
|
-
|
120
|
-
Lint/NoReturnInBeginEndBlocks:
|
121
|
-
Enabled: true
|
122
|
-
|
123
|
-
Lint/NumberedParameterAssignment:
|
124
|
-
Enabled: true
|
125
|
-
|
126
|
-
Lint/OrAssignmentToConstant:
|
127
|
-
Enabled: true
|
128
|
-
|
129
|
-
Lint/RaiseException:
|
130
|
-
Enabled: true
|
131
|
-
|
132
|
-
Lint/RedundantDirGlobSort:
|
133
|
-
Enabled: true
|
134
|
-
|
135
|
-
Lint/RequireRelativeSelfPath: # new in 1.22
|
136
|
-
Enabled: true
|
137
|
-
|
138
|
-
Lint/RescueException:
|
139
|
-
Enabled: true
|
140
|
-
|
141
|
-
Lint/StructNewOverride:
|
142
|
-
Enabled: true
|
143
|
-
|
144
|
-
Lint/SymbolConversion:
|
145
|
-
Enabled: true
|
146
|
-
|
147
|
-
Lint/ToEnumArguments:
|
148
|
-
Enabled: true
|
149
|
-
|
150
|
-
Lint/TripleQuotes:
|
151
|
-
Enabled: true
|
152
|
-
|
153
|
-
Lint/UnexpectedBlockArity:
|
154
|
-
Enabled: true
|
155
|
-
|
156
|
-
Lint/UnmodifiedReduceAccumulator:
|
157
|
-
Enabled: true
|
158
|
-
|
159
|
-
Lint/UnusedMethodArgument:
|
160
|
-
Enabled: true
|
161
|
-
|
162
|
-
Lint/UselessAccessModifier:
|
163
|
-
Enabled: true
|
164
|
-
|
165
|
-
Lint/UselessRuby2Keywords: # new in 1.23
|
166
|
-
Enabled: true
|
167
|
-
|
168
|
-
Lint/Void:
|
169
|
-
Enabled: false
|
170
|
-
|
171
|
-
Lint/UselessAssignment:
|
172
|
-
Enabled: true
|
173
|
-
|
174
77
|
Metrics/AbcSize:
|
175
78
|
Enabled: false
|
176
79
|
|
@@ -204,21 +107,12 @@ Metrics/ModuleLength:
|
|
204
107
|
Metrics/PerceivedComplexity:
|
205
108
|
Enabled: false
|
206
109
|
|
207
|
-
Naming/BlockForwarding: # new in 1.24
|
208
|
-
Enabled: true
|
209
|
-
|
210
110
|
Naming/ConstantName:
|
211
111
|
Enabled: false
|
212
112
|
|
213
113
|
Naming/ClassAndModuleCamelCase:
|
214
114
|
Enabled: false
|
215
115
|
|
216
|
-
Naming/BlockParameterName:
|
217
|
-
Enabled: true
|
218
|
-
|
219
|
-
Naming/InclusiveLanguage:
|
220
|
-
Enabled: true
|
221
|
-
|
222
116
|
Naming/MethodParameterName:
|
223
117
|
Enabled: false
|
224
118
|
|
@@ -228,15 +122,6 @@ Naming/MethodName:
|
|
228
122
|
Naming/VariableName:
|
229
123
|
Enabled: false
|
230
124
|
|
231
|
-
Security/IoMethods: # new in 1.22
|
232
|
-
Enabled: true
|
233
|
-
|
234
|
-
Style/Alias:
|
235
|
-
Enabled: true
|
236
|
-
|
237
|
-
Style/ArgumentsForwarding:
|
238
|
-
Enabled: true
|
239
|
-
|
240
125
|
Style/AsciiComments:
|
241
126
|
Enabled: false
|
242
127
|
|
@@ -255,9 +140,6 @@ Style/ClassCheck:
|
|
255
140
|
Style/ClassVars:
|
256
141
|
Enabled: false
|
257
142
|
|
258
|
-
Style/CollectionCompact:
|
259
|
-
Enabled: true
|
260
|
-
|
261
143
|
Style/ColonMethodCall:
|
262
144
|
Enabled: false
|
263
145
|
|
@@ -270,223 +152,69 @@ Style/CommentedKeyword:
|
|
270
152
|
Style/ConditionalAssignment:
|
271
153
|
Enabled: false
|
272
154
|
|
273
|
-
Style/DefWithParentheses:
|
274
|
-
Enabled: true
|
275
|
-
|
276
155
|
Style/Documentation:
|
277
156
|
Enabled: false
|
278
157
|
|
279
|
-
Style/DocumentDynamicEvalDefinition:
|
280
|
-
Enabled: true
|
281
|
-
|
282
158
|
Style/ExpandPathArguments:
|
283
159
|
Enabled: false
|
284
160
|
|
285
|
-
Style/ExponentialNotation:
|
286
|
-
Enabled: true
|
287
|
-
|
288
161
|
Style/GuardClause:
|
289
162
|
Enabled: false
|
290
163
|
|
291
|
-
Style/HashEachMethods:
|
292
|
-
Enabled: true
|
293
|
-
|
294
|
-
Style/HashExcept:
|
295
|
-
Enabled: true
|
296
|
-
|
297
|
-
Style/HashTransformKeys:
|
298
|
-
Enabled: true
|
299
|
-
|
300
|
-
Style/HashTransformValues:
|
301
|
-
Enabled: true
|
302
|
-
|
303
164
|
Style/IfUnlessModifier:
|
304
165
|
Enabled: false
|
305
166
|
|
306
|
-
Style/InPatternThen:
|
307
|
-
Enabled: true
|
308
|
-
|
309
167
|
Style/InverseMethods:
|
310
168
|
Enabled: false
|
311
169
|
|
312
170
|
Style/MissingRespondToMissing:
|
313
171
|
Enabled: false
|
314
172
|
|
315
|
-
Style/MultilineInPatternThen:
|
316
|
-
Enabled: true
|
317
|
-
|
318
|
-
Style/NegatedIfElseCondition:
|
319
|
-
Enabled: true
|
320
|
-
|
321
173
|
Style/Next:
|
322
174
|
Enabled: false
|
323
175
|
|
324
|
-
Style/NilLambda:
|
325
|
-
Enabled: true
|
326
|
-
|
327
|
-
Style/NumberedParameters: # new in 1.22
|
328
|
-
Enabled: true
|
329
|
-
|
330
|
-
Style/NumberedParametersLimit: # new in 1.22
|
331
|
-
Enabled: true
|
332
|
-
|
333
176
|
Style/NumericLiterals:
|
334
177
|
Enabled: false
|
335
178
|
|
336
|
-
Style/QuotedSymbols:
|
337
|
-
Enabled: true
|
338
|
-
|
339
|
-
Style/RaiseArgs:
|
340
|
-
Enabled: true
|
341
|
-
|
342
|
-
Style/RedundantArgument:
|
343
|
-
Enabled: true
|
344
|
-
|
345
179
|
Style/RedundantReturn:
|
346
180
|
Enabled: false
|
347
181
|
|
348
|
-
Style/RedundantSelf:
|
349
|
-
Enabled: true
|
350
|
-
|
351
|
-
Style/RedundantSelfAssignmentBranch:
|
352
|
-
Enabled: true
|
353
|
-
|
354
182
|
Style/RegexpLiteral:
|
355
183
|
Enabled: false
|
356
184
|
|
357
185
|
Style/PercentLiteralDelimiters:
|
358
186
|
Enabled: false
|
359
187
|
|
360
|
-
Style/SelectByRegexp: # new in 1.22
|
361
|
-
Enabled: true
|
362
|
-
|
363
188
|
Style/StderrPuts:
|
364
189
|
Enabled: false
|
365
190
|
|
366
|
-
Style/StringLiterals:
|
367
|
-
Enabled: true
|
368
|
-
|
369
|
-
Style/SwapValues:
|
370
|
-
Enabled: true
|
371
|
-
|
372
191
|
Style/TernaryParentheses:
|
373
192
|
Enabled: false
|
374
193
|
|
375
194
|
Style/UnlessElse:
|
376
195
|
Enabled: false
|
377
196
|
|
378
|
-
|
379
|
-
|
380
|
-
Enabled:
|
381
|
-
|
382
|
-
|
383
|
-
Enabled:
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
Enabled:
|
393
|
-
|
394
|
-
|
395
|
-
Enabled:
|
396
|
-
|
397
|
-
|
398
|
-
Enabled:
|
399
|
-
|
400
|
-
|
401
|
-
Enabled:
|
402
|
-
|
403
|
-
Lint/MixedRegexpCaptureTypes:
|
404
|
-
Enabled: true
|
405
|
-
|
406
|
-
Lint/OutOfRangeRegexpRef:
|
407
|
-
Enabled: true
|
408
|
-
|
409
|
-
Lint/SelfAssignment:
|
410
|
-
Enabled: true
|
411
|
-
|
412
|
-
Lint/TopLevelReturnWithArgument:
|
413
|
-
Enabled: true
|
414
|
-
|
415
|
-
Lint/UnreachableLoop:
|
416
|
-
Enabled: true
|
417
|
-
|
418
|
-
Style/AccessorGrouping:
|
419
|
-
Enabled: true
|
420
|
-
|
421
|
-
Style/ArrayCoercion:
|
422
|
-
Enabled: true
|
423
|
-
|
424
|
-
Style/BisectedAttrAccessor:
|
425
|
-
Enabled: true
|
426
|
-
|
427
|
-
Style/CaseLikeIf:
|
428
|
-
Enabled: true
|
429
|
-
|
430
|
-
Style/EndlessMethod:
|
431
|
-
Enabled: true
|
432
|
-
|
433
|
-
Style/ExplicitBlockArgument:
|
434
|
-
Enabled: true
|
435
|
-
|
436
|
-
Style/FileRead: # new in 1.24
|
437
|
-
Enabled: true
|
438
|
-
|
439
|
-
Style/FileWrite: # new in 1.24
|
440
|
-
Enabled: true
|
441
|
-
|
442
|
-
Style/GlobalStdStream:
|
443
|
-
Enabled: true
|
444
|
-
|
445
|
-
Style/HashAsLastArrayItem:
|
446
|
-
Enabled: true
|
447
|
-
|
448
|
-
Style/HashConversion:
|
449
|
-
Enabled: true
|
450
|
-
|
451
|
-
Style/HashLikeCase:
|
452
|
-
Enabled: true
|
453
|
-
|
454
|
-
Style/IfWithBooleanLiteralBranches:
|
455
|
-
Enabled: true
|
456
|
-
|
457
|
-
Style/MapToHash: # new in 1.24
|
458
|
-
Enabled: true
|
459
|
-
|
460
|
-
Style/OpenStructUse: # new in 1.23
|
461
|
-
Enabled: true
|
462
|
-
|
463
|
-
Style/OptionalBooleanParameter:
|
464
|
-
Enabled: true
|
465
|
-
|
466
|
-
|
467
|
-
Style/RedundantAssignment:
|
468
|
-
Enabled: true
|
469
|
-
|
470
|
-
Style/RedundantFetchBlock:
|
471
|
-
Enabled: true
|
472
|
-
|
473
|
-
Style/RedundantFileExtensionInRequire:
|
474
|
-
Enabled: true
|
475
|
-
|
476
|
-
Style/RedundantRegexpCharacterClass:
|
477
|
-
Enabled: true
|
478
|
-
|
479
|
-
Style/RedundantRegexpEscape:
|
480
|
-
Enabled: true
|
481
|
-
|
482
|
-
Style/SingleArgumentDig:
|
483
|
-
Enabled: true
|
484
|
-
|
485
|
-
Style/SlicingWithRange:
|
486
|
-
Enabled: true
|
487
|
-
|
488
|
-
Style/StringChars:
|
489
|
-
Enabled: true
|
490
|
-
|
491
|
-
Style/StringConcatenation:
|
492
|
-
Enabled: true
|
197
|
+
## Optional rubocop-rspec plugin rule checking
|
198
|
+
#RSpec/ContextWording:
|
199
|
+
# Enabled: false
|
200
|
+
#
|
201
|
+
#RSpec/DescribeClass:
|
202
|
+
# Enabled: false
|
203
|
+
#
|
204
|
+
#RSpec/ExampleLength:
|
205
|
+
# Max: 40
|
206
|
+
#
|
207
|
+
#RSpec/MultipleExpectations:
|
208
|
+
# Max: 25
|
209
|
+
#
|
210
|
+
#RSpec/NoExpectationExample:
|
211
|
+
# Enabled: false
|
212
|
+
#
|
213
|
+
#RSpec/RepeatedDescription:
|
214
|
+
# Enabled: false
|
215
|
+
#
|
216
|
+
#RSpec/RepeatedExample:
|
217
|
+
# Enabled: false
|
218
|
+
#
|
219
|
+
#RSpec/RepeatedExampleGroupDescription:
|
220
|
+
# Enabled: false
|
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
CHANGED
@@ -446,6 +446,7 @@ module Loxxy
|
|
446
446
|
add_native_fun('print_error', native_print_error)
|
447
447
|
end
|
448
448
|
|
449
|
+
# rubocop: disable Lint/UselessConstantScoping
|
449
450
|
NativeFunction = Struct.new(:callable, :interp) do
|
450
451
|
def accept(_visitor)
|
451
452
|
interp.expr_stack.push self
|
@@ -459,6 +460,7 @@ module Loxxy
|
|
459
460
|
'<native fn>'
|
460
461
|
end
|
461
462
|
end
|
463
|
+
# rubocop: enable Lint/UselessConstantScoping
|
462
464
|
|
463
465
|
def add_native_fun(aName, aProc)
|
464
466
|
native_fun = Variable.new(aName, NativeFunction.new(aProc, self))
|
@@ -20,14 +20,14 @@ module Loxxy
|
|
20
20
|
# Delimiters: e.g. parentheses '(', ')'
|
21
21
|
# Separators: e.g. comma
|
22
22
|
class Scanner
|
23
|
-
PATT_BLOCK_COMMENT_BEGIN =
|
24
|
-
PATT_BLOCK_COMMENT_END =
|
25
|
-
PATT_COMPARISON = /[!=><]
|
26
|
-
PATT_IDENTIFIER = /[a-zA-Z_][a-zA-Z_0-9]
|
27
|
-
PATT_LINE_COMMENT = /\/\/[^\r\n]
|
28
|
-
PATT_NEWLINE = /(?:\r\n)|\r|\n
|
29
|
-
PATT_NUMBER = /\d+(?:\.\d+)
|
30
|
-
PATT_WHITESPACE = /[ \t\f]
|
23
|
+
PATT_BLOCK_COMMENT_BEGIN = /\/\*/
|
24
|
+
PATT_BLOCK_COMMENT_END = /\*\//
|
25
|
+
PATT_COMPARISON = /[!=><]=?/
|
26
|
+
PATT_IDENTIFIER = /[a-zA-Z_][a-zA-Z_0-9]*/
|
27
|
+
PATT_LINE_COMMENT = /\/\/[^\r\n]*/
|
28
|
+
PATT_NEWLINE = /(?:\r\n)|\r|\n/
|
29
|
+
PATT_NUMBER = /\d+(?:\.\d+)?/
|
30
|
+
PATT_WHITESPACE = /[ \t\f]+/
|
31
31
|
|
32
32
|
# @return [StringScanner] Low-level input scanner
|
33
33
|
attr_reader(:scanner)
|
@@ -148,7 +148,7 @@ module Loxxy
|
|
148
148
|
elsif (lexeme = scanner.scan(PATT_COMPARISON))
|
149
149
|
# One or two special character tokens
|
150
150
|
build_token(Lexeme2name[lexeme], lexeme)
|
151
|
-
elsif scanner.scan(
|
151
|
+
elsif scanner.scan('"') # Start of string detected...
|
152
152
|
build_string_token
|
153
153
|
elsif (lexeme = scanner.scan(PATT_NUMBER))
|
154
154
|
build_token('NUMBER', lexeme)
|
data/lib/loxxy/interpreter.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative '
|
5
|
-
require_relative '
|
3
|
+
require_relative 'front_end/parser'
|
4
|
+
require_relative 'ast/ast_visitor'
|
5
|
+
require_relative 'back_end/engine'
|
6
6
|
|
7
7
|
module Loxxy
|
8
8
|
# A Lox tree-walking interpreter.
|
data/lib/loxxy/version.rb
CHANGED
data/loxxy.gemspec
CHANGED
@@ -42,11 +42,13 @@ Gem::Specification.new do |spec|
|
|
42
42
|
spec.description = <<-DESCR_END
|
43
43
|
A Ruby implementation of the Lox programming language. Lox is a dynamically typed,
|
44
44
|
object-oriented programming language that features first-class functions, closures,
|
45
|
-
classes, and inheritance.
|
45
|
+
classes, and inheritance. The interpreter passes all unit tests from the original Java implementation.
|
46
|
+
It is also able to run `LoxLox` a Lox interpreter written in Lox itself.
|
46
47
|
DESCR_END
|
47
48
|
spec.homepage = 'https://github.com/famished-tiger/loxxy'
|
48
49
|
spec.license = 'MIT'
|
49
|
-
spec.required_ruby_version = '>=
|
50
|
+
spec.required_ruby_version = '>= 3.1'
|
51
|
+
spec.metadata = { 'rubygems_mfa_required' => 'true' }
|
50
52
|
|
51
53
|
spec.bindir = 'bin'
|
52
54
|
spec.executables = ['loxxy']
|
@@ -56,11 +58,10 @@ Gem::Specification.new do |spec|
|
|
56
58
|
PkgExtending.pkg_documentation(spec)
|
57
59
|
|
58
60
|
# Runtime dependencies
|
59
|
-
spec.add_dependency 'rley', '~> 0.
|
61
|
+
spec.add_dependency 'rley', '~> 0.9', '>= 0.9.02'
|
60
62
|
|
61
63
|
# Development dependencies
|
62
|
-
spec.add_development_dependency 'bundler', '~> 2.
|
63
|
-
spec.add_development_dependency 'rake', '~> 13
|
64
|
-
spec.add_development_dependency 'rspec', '~> 3.
|
65
|
-
spec.add_development_dependency 'yard', '~> 0.9.34'
|
64
|
+
spec.add_development_dependency 'bundler', '~> 2.4', '>= 2.4.1'
|
65
|
+
spec.add_development_dependency 'rake', '~> 13'
|
66
|
+
spec.add_development_dependency 'rspec', '~> 3', '>= 3.10.0'
|
66
67
|
end
|
@@ -12,50 +12,52 @@ module Loxxy
|
|
12
12
|
let(:sample_options) do
|
13
13
|
{ ostream: StringIO.new }
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
|
+
subject(:engine) { described_class.new(sample_options) }
|
16
17
|
|
17
18
|
context 'Initialization:' do
|
18
|
-
it '
|
19
|
-
expect {
|
19
|
+
it 'accepts an option Hash at initialization' do
|
20
|
+
expect { described_class.new(sample_options) }.not_to raise_error
|
20
21
|
end
|
21
22
|
|
22
|
-
it '
|
23
|
-
expect(
|
23
|
+
it 'knows its config options' do
|
24
|
+
expect(engine.config).to eq(sample_options)
|
24
25
|
end
|
25
26
|
|
26
|
-
it '
|
27
|
-
expect(
|
27
|
+
it 'has an empty stack' do
|
28
|
+
expect(engine.stack).to be_empty
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
31
32
|
context 'Listening to visitor events:' do
|
32
33
|
let(:greeting) { Datatype::LXString.new('Hello, world') }
|
33
|
-
let(:sample_pos) { double('fake-position') }
|
34
|
+
# let(:sample_pos) { double('fake-position') }
|
35
|
+
let(:sample_pos) { instance_double(Rley::Lexical::Position) }
|
34
36
|
let(:var_decl) { Ast::LoxVarStmt.new(sample_pos, 'greeting', greeting) }
|
35
37
|
let(:lit_expr) { Ast::LoxLiteralExpr.new(sample_pos, greeting) }
|
36
38
|
|
37
|
-
it "
|
39
|
+
it "reacts to 'after_var_stmt' event" do
|
38
40
|
# Precondition: value to assign is on top of expr stack
|
39
|
-
|
41
|
+
engine.expr_stack.push(greeting)
|
40
42
|
|
41
|
-
expect {
|
42
|
-
current_env =
|
43
|
-
expect(current_env.defns['greeting']).to
|
43
|
+
expect { engine.after_var_stmt(var_decl) }.not_to raise_error
|
44
|
+
current_env = engine.symbol_table.current_env
|
45
|
+
expect(current_env.defns['greeting']).to be_a(Variable)
|
44
46
|
expect(current_env.defns['greeting'].value).to eq(greeting)
|
45
47
|
end
|
46
48
|
|
47
|
-
it "
|
48
|
-
expect {
|
49
|
-
expect(
|
49
|
+
it "reacts to 'before_literal_expr' event" do
|
50
|
+
expect { engine.before_literal_expr(lit_expr) }.not_to raise_error
|
51
|
+
expect(engine.expr_stack.pop).to eq(greeting)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
55
|
context 'Built-in functions:' do
|
54
|
-
it '
|
55
|
-
symb_table =
|
56
|
+
it 'provides built-in functions' do
|
57
|
+
symb_table = engine.symbol_table
|
56
58
|
%w[clock getc chr exit print_error].each do |name|
|
57
59
|
fun_var = symb_table.current_env.defns[name]
|
58
|
-
expect(fun_var.value).to
|
60
|
+
expect(fun_var.value).to be_a(BackEnd::Engine::NativeFunction)
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|