loxxy 0.2.00 → 0.2.05
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +47 -11
- data/CHANGELOG.md +81 -0
- data/README.md +188 -90
- data/bin/loxxy +54 -6
- data/lib/loxxy.rb +1 -0
- data/lib/loxxy/ast/all_lox_nodes.rb +0 -1
- data/lib/loxxy/ast/ast_builder.rb +27 -4
- data/lib/loxxy/ast/ast_visitee.rb +53 -0
- data/lib/loxxy/ast/ast_visitor.rb +2 -10
- data/lib/loxxy/ast/lox_assign_expr.rb +1 -5
- data/lib/loxxy/ast/lox_binary_expr.rb +1 -6
- data/lib/loxxy/ast/lox_block_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_call_expr.rb +1 -5
- data/lib/loxxy/ast/lox_class_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_fun_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_get_expr.rb +1 -6
- data/lib/loxxy/ast/lox_grouping_expr.rb +1 -5
- data/lib/loxxy/ast/lox_if_stmt.rb +2 -6
- data/lib/loxxy/ast/lox_literal_expr.rb +1 -5
- data/lib/loxxy/ast/lox_logical_expr.rb +1 -6
- data/lib/loxxy/ast/lox_node.rb +9 -1
- data/lib/loxxy/ast/lox_print_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_return_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_seq_decl.rb +1 -5
- data/lib/loxxy/ast/lox_set_expr.rb +1 -5
- data/lib/loxxy/ast/lox_super_expr.rb +2 -6
- data/lib/loxxy/ast/lox_this_expr.rb +1 -5
- data/lib/loxxy/ast/lox_unary_expr.rb +1 -6
- data/lib/loxxy/ast/lox_var_stmt.rb +1 -5
- data/lib/loxxy/ast/lox_variable_expr.rb +1 -5
- data/lib/loxxy/ast/lox_while_stmt.rb +2 -6
- data/lib/loxxy/back_end/engine.rb +13 -22
- data/lib/loxxy/back_end/lox_instance.rb +1 -1
- data/lib/loxxy/back_end/resolver.rb +1 -12
- data/lib/loxxy/cli_parser.rb +68 -0
- data/lib/loxxy/error.rb +3 -0
- data/lib/loxxy/front_end/parser.rb +1 -1
- data/lib/loxxy/front_end/scanner.rb +37 -12
- data/lib/loxxy/version.rb +1 -1
- data/loxxy.gemspec +5 -1
- data/spec/front_end/scanner_spec.rb +41 -0
- data/spec/interpreter_spec.rb +23 -0
- metadata +8 -4
- data/lib/loxxy/ast/lox_for_stmt.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce7eeb0247e67176d1dc4c67066eff4398ffaa8b75755b289eb3e53932d3006b
|
4
|
+
data.tar.gz: 84f7c781c10b0f6f07cfb5bab98d2ab9d78340cf5b20426822226cbe5c266a94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad3cce2c2f3bcf8c0c3ae30b1dc050764c654e276a2d482934c2efd7ad6120b0db7e415003bd8d2f887ed118f723eee7c882f231ceadea773236d1d01e478db9
|
7
|
+
data.tar.gz: d5e25c250ac629d76e01468fbb59a2fcb287b2a112fda9f2432e83df48a889581ecbe38723ab7371ba6ae3cdd94367051249907994caa78bfa852e7b328a0811
|
data/.rubocop.yml
CHANGED
@@ -3,6 +3,9 @@ AllCops:
|
|
3
3
|
- 'exp/**/*'
|
4
4
|
- 'demo/**/*'
|
5
5
|
|
6
|
+
Gemspec/DateAssignment:
|
7
|
+
Enabled: true
|
8
|
+
|
6
9
|
Layout/ArgumentAlignment:
|
7
10
|
Enabled: false
|
8
11
|
|
@@ -34,7 +37,7 @@ Layout/EndOfLine:
|
|
34
37
|
|
35
38
|
Layout/FirstArgumentIndentation:
|
36
39
|
Enabled: false
|
37
|
-
|
40
|
+
|
38
41
|
Layout/HashAlignment:
|
39
42
|
Enabled: false
|
40
43
|
|
@@ -56,7 +59,7 @@ Layout/MultilineMethodCallBraceLayout:
|
|
56
59
|
|
57
60
|
Layout/SpaceAroundOperators:
|
58
61
|
Enabled: true
|
59
|
-
|
62
|
+
|
60
63
|
Layout/SpaceBeforeBrackets:
|
61
64
|
Enabled: true
|
62
65
|
|
@@ -74,10 +77,13 @@ Layout/TrailingEmptyLines:
|
|
74
77
|
|
75
78
|
Layout/TrailingWhitespace:
|
76
79
|
Enabled: true
|
77
|
-
|
80
|
+
|
78
81
|
Lint/AmbiguousAssignment:
|
79
82
|
Enabled: true
|
80
83
|
|
84
|
+
Lint/DeprecatedConstants:
|
85
|
+
Enabled: true
|
86
|
+
|
81
87
|
Lint/DuplicateBranch:
|
82
88
|
Enabled: true
|
83
89
|
|
@@ -90,24 +96,42 @@ Lint/EmptyBlock:
|
|
90
96
|
Lint/EmptyClass:
|
91
97
|
Enabled: false
|
92
98
|
|
99
|
+
Lint/LambdaWithoutLiteralBlock:
|
100
|
+
Enabled: true
|
101
|
+
|
93
102
|
Lint/Loop:
|
94
103
|
Enabled: true
|
95
104
|
|
96
105
|
Lint/NoReturnInBeginEndBlocks:
|
97
106
|
Enabled: true
|
98
107
|
|
108
|
+
Lint/NumberedParameterAssignment:
|
109
|
+
Enabled: true
|
110
|
+
|
111
|
+
Lint/OrAssignmentToConstant:
|
112
|
+
Enabled: true
|
113
|
+
|
99
114
|
Lint/RaiseException:
|
100
115
|
Enabled: true
|
101
116
|
|
117
|
+
Lint/RedundantDirGlobSort:
|
118
|
+
Enabled: true
|
119
|
+
|
102
120
|
Lint/RescueException:
|
103
121
|
Enabled: true
|
104
122
|
|
105
123
|
Lint/StructNewOverride:
|
106
124
|
Enabled: true
|
107
125
|
|
126
|
+
Lint/SymbolConversion:
|
127
|
+
Enabled: true
|
128
|
+
|
108
129
|
Lint/ToEnumArguments:
|
109
130
|
Enabled: true
|
110
131
|
|
132
|
+
Lint/TripleQuotes:
|
133
|
+
Enabled: true
|
134
|
+
|
111
135
|
Lint/UnexpectedBlockArity:
|
112
136
|
Enabled: true
|
113
137
|
|
@@ -170,7 +194,7 @@ Naming/BlockParameterName:
|
|
170
194
|
|
171
195
|
Naming/MethodParameterName:
|
172
196
|
Enabled: false
|
173
|
-
|
197
|
+
|
174
198
|
Naming/MethodName:
|
175
199
|
Enabled: false
|
176
200
|
|
@@ -200,7 +224,7 @@ Style/ClassCheck:
|
|
200
224
|
|
201
225
|
Style/ClassVars:
|
202
226
|
Enabled: false
|
203
|
-
|
227
|
+
|
204
228
|
Style/CollectionCompact:
|
205
229
|
Enabled: true
|
206
230
|
|
@@ -221,7 +245,7 @@ Style/DefWithParentheses:
|
|
221
245
|
|
222
246
|
Style/Documentation:
|
223
247
|
Enabled: false
|
224
|
-
|
248
|
+
|
225
249
|
Style/DocumentDynamicEvalDefinition:
|
226
250
|
Enabled: true
|
227
251
|
|
@@ -236,7 +260,7 @@ Style/GuardClause:
|
|
236
260
|
|
237
261
|
Style/HashEachMethods:
|
238
262
|
Enabled: true
|
239
|
-
|
263
|
+
|
240
264
|
Style/HashExcept:
|
241
265
|
Enabled: true
|
242
266
|
|
@@ -254,13 +278,13 @@ Style/InverseMethods:
|
|
254
278
|
|
255
279
|
Style/MissingRespondToMissing:
|
256
280
|
Enabled: false
|
257
|
-
|
281
|
+
|
258
282
|
Style/NegatedIfElseCondition:
|
259
283
|
Enabled: true
|
260
284
|
|
261
285
|
Style/Next:
|
262
286
|
Enabled: false
|
263
|
-
|
287
|
+
|
264
288
|
Style/NilLambda:
|
265
289
|
Enabled: true
|
266
290
|
|
@@ -269,7 +293,7 @@ Style/NumericLiterals:
|
|
269
293
|
|
270
294
|
Style/RaiseArgs:
|
271
295
|
Enabled: true
|
272
|
-
|
296
|
+
|
273
297
|
Style/RedundantArgument:
|
274
298
|
Enabled: true
|
275
299
|
|
@@ -290,7 +314,7 @@ Style/StderrPuts:
|
|
290
314
|
|
291
315
|
Style/StringLiterals:
|
292
316
|
Enabled: true
|
293
|
-
|
317
|
+
|
294
318
|
Style/SwapValues:
|
295
319
|
Enabled: true
|
296
320
|
|
@@ -352,6 +376,9 @@ Style/BisectedAttrAccessor:
|
|
352
376
|
Style/CaseLikeIf:
|
353
377
|
Enabled: true
|
354
378
|
|
379
|
+
Style/EndlessMethod:
|
380
|
+
Enabled: true
|
381
|
+
|
355
382
|
Style/ExplicitBlockArgument:
|
356
383
|
Enabled: true
|
357
384
|
|
@@ -361,9 +388,15 @@ Style/GlobalStdStream:
|
|
361
388
|
Style/HashAsLastArrayItem:
|
362
389
|
Enabled: true
|
363
390
|
|
391
|
+
Style/HashConversion:
|
392
|
+
Enabled: true
|
393
|
+
|
364
394
|
Style/HashLikeCase:
|
365
395
|
Enabled: true
|
366
396
|
|
397
|
+
Style/IfWithBooleanLiteralBranches:
|
398
|
+
Enabled: true
|
399
|
+
|
367
400
|
Style/OptionalBooleanParameter:
|
368
401
|
Enabled: true
|
369
402
|
|
@@ -388,5 +421,8 @@ Style/SingleArgumentDig:
|
|
388
421
|
Style/SlicingWithRange:
|
389
422
|
Enabled: true
|
390
423
|
|
424
|
+
Style/StringChars:
|
425
|
+
Enabled: true
|
426
|
+
|
391
427
|
Style/StringConcatenation:
|
392
428
|
Enabled: true
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,84 @@
|
|
1
|
+
## [0.2.05] - 2021-04-26
|
2
|
+
- `Loxxy` now transforms for loops into while loops (desugaring), fix in Scanner class
|
3
|
+
|
4
|
+
### Changed
|
5
|
+
- Method `Ast::ASTBuilder#reduce_for_stmt` converts 'for' loops into 'while' loops
|
6
|
+
- Method `Ast::ASTBuilder#reduce_for_control takes care of case for(expr1;;expr2) now test expression is set to true
|
7
|
+
|
8
|
+
### Fixed
|
9
|
+
- Method `FrontEnd::Scanner#next_token` keyword recognition was case insensitive
|
10
|
+
|
11
|
+
### Removed
|
12
|
+
- Method `Ast::Visitor#visitor_for_stmt`
|
13
|
+
- Method `BackEnd::Engine#after_for_stmt`
|
14
|
+
- Method `BackEnd::Resolver#before_for_stmt`
|
15
|
+
- Method `BackEnd::Resolver#after_for_stmt`
|
16
|
+
|
17
|
+
|
18
|
+
## [0.2.04] - 2021-04-25
|
19
|
+
- `Loxxy` passes the test suite for `for` statements
|
20
|
+
|
21
|
+
### Fixed
|
22
|
+
- Method `BackEnd::Engine#after_for_stmt` now a for(;;) executes the body once; a for without test will execute forever
|
23
|
+
- Method `BackEnd::Resolver#after_for_stmt now accepts nil test expression
|
24
|
+
|
25
|
+
## [0.2.03] - 2021-04-24
|
26
|
+
- Fixes for the set (field) expressions, `accept` methods for AST nodes are meta-programmed
|
27
|
+
|
28
|
+
### New
|
29
|
+
- Module `Ast::Visitee` provides the `define_accept` method that generate `accept` method with meta-programming
|
30
|
+
|
31
|
+
### Fixed
|
32
|
+
- Method `BackEnd::Engine#before_set_expr` methos method that ensure that the receiver is evaluated first, then the assigned value
|
33
|
+
- Method `BackEnd::Engine#after_set_expr` now pushes the value assigned to the field also onto the stack
|
34
|
+
- Class `BackEnd::Engine` a number of StnadardError exceptions are replaced by Loxxy::RuntimeError
|
35
|
+
|
36
|
+
|
37
|
+
## [0.2.02] - 2021-04-21
|
38
|
+
- Improvements in the scanner class (escape sequence for quotes and newlines), error messages closer to jlox.
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
- File `loxxy` executable doesn't show a stack trace for scanner errors
|
42
|
+
- Class `ScannerError` is now a subclass of `Loxxy::Error`
|
43
|
+
- Class `Scanner` now returns a specific error message for unterminated strings
|
44
|
+
- Class `Scanner` error messages are closer to the ones from jlox
|
45
|
+
- Class `Scanner` supports now escape sequences \" for double quotes, \n for newlines
|
46
|
+
- File `README.md` Reshuffled some text
|
47
|
+
|
48
|
+
## [0.2.01] - 2021-04-18
|
49
|
+
- Minor improvements in CLI, starting re-documenting `README.md`.
|
50
|
+
|
51
|
+
### New
|
52
|
+
- Class `Loxxy::CLIParser` parser for the command-line options
|
53
|
+
|
54
|
+
### Changed
|
55
|
+
- File `loxxy` executable now uses commad-line parsing
|
56
|
+
- File `.rubocop.yml` updated with new cops
|
57
|
+
- File `README.md` Added examples for command-line interface
|
58
|
+
- File `loxxy.gemspec` expanded description of gem
|
59
|
+
|
60
|
+
## [0.2.00] - 2021-04-17
|
61
|
+
- `Loxxy` implements the complete `Lox` language including its object-oriented features.
|
62
|
+
|
63
|
+
### New
|
64
|
+
- Class `Ast::LoxSuperExpr` an AST node that represents the occurrence of `super` in source code.
|
65
|
+
- Method `Ast::ASTBuilder#reduce_class_subclassing` action launched by the parser when detecting inheritance
|
66
|
+
- Method `Ast::ASTBuilder#reduce_super_expr` action launched by the parser when detecting the super keyword
|
67
|
+
- Method `Ast::Visitor#visit_super_expr` visit of an `Ast::LoxSuperExpr` node
|
68
|
+
- Method `BackEnd::Engine#after_super_stmt` does the lookup of an inherited method.
|
69
|
+
- Method `BackEnd::Resolver#after_super_stmt` checks for correct context for super occurrence
|
70
|
+
|
71
|
+
|
72
|
+
### Changed
|
73
|
+
- Method `Ast::ASTBuilder#reduce_class_decl` expanded in order to support superclass
|
74
|
+
- Class `Ast::LoxClassStmt` added `superclass` attribute, expanded constructor signature.
|
75
|
+
- Method `BackEnd::Engine#after_class_stmt` adds an environment for super variable.
|
76
|
+
- Class `BackEnd::LoxClass` added `superclass` attribute, expanded constructor signature.
|
77
|
+
- Method `BackEnd::LoxClass#find_method` now does the lookup in superclass(es)
|
78
|
+
- Method `BackEnd::Resolver#after_class_stmt` super variable resolution
|
79
|
+
- File `grammar.rb` changed rules to cope with superclass name and super keyword
|
80
|
+
- File `README.md` updated to reflect current implementation level
|
81
|
+
|
1
82
|
## [0.1.17] - 2021-04-11
|
2
83
|
- `Loxxy` now support custom initializer.
|
3
84
|
|
data/README.md
CHANGED
@@ -1,59 +1,213 @@
|
|
1
1
|
# loxxy
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/loxxy.svg)](https://badge.fury.io/rb/loxxy)
|
3
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/8e5p7dgjanm0qjkp?svg=true)](https://ci.appveyor.com/project/famished-tiger/loxxy)
|
3
4
|
[![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](https://github.com/famished-tiger/loxxy/blob/main/LICENSE.txt)
|
4
5
|
|
5
|
-
|
6
|
+
## What is loxxy?
|
6
7
|
A Ruby implementation of the [Lox programming language](https://craftinginterpreters.com/the-lox-language.html ),
|
7
|
-
a simple language defined in Bob Nystrom's online book [Crafting Interpreters](https://craftinginterpreters.com/ ).
|
8
|
+
a simple language defined in Bob Nystrom's excellent online book [Crafting Interpreters](https://craftinginterpreters.com/ ).
|
8
9
|
|
9
|
-
|
10
|
-
-
|
11
|
-
|
12
|
-
-
|
13
|
-
|
10
|
+
Although __Lox__ is fairly simple, it is far from being a toy language:
|
11
|
+
- Dynamically typed,
|
12
|
+
- Provides data types such as booleans, number, strings,
|
13
|
+
- Supports arithmetic operations (+, -, *, / ) and comparison ( >, >= , <, <=)
|
14
|
+
- Implements equality operators (==, !=) and the logical connectors `and` and `or`.
|
15
|
+
- Control flow statements `if`, `for` and `while`
|
16
|
+
- Functions and closures
|
17
|
+
- Object-orientation (classes, methods, inheritance).
|
18
|
+
|
19
|
+
### Loxxy gem features
|
20
|
+
- Complete tree-walking interpreter including lexer, parser and resolver
|
21
|
+
- 100% pure Ruby with clean design (not a port from some other language)
|
22
|
+
- Minimal runtime dependency (Rley gem). Won't drag a bunch of gems...
|
23
|
+
- Ruby API for integrating a Lox interpreter with your code.
|
24
|
+
- A command-line interpreter `loxxy`
|
25
|
+
- Open for your language extensions...
|
26
|
+
|
27
|
+
## How to start in 1, 2, 3...?
|
28
|
+
... in less than 3 minutes...
|
29
|
+
|
30
|
+
### 1. Installing
|
31
|
+
__Loxxy__'s installation is pretty standard:
|
32
|
+
|
33
|
+
|
34
|
+
$ gem install loxxy
|
35
|
+
|
36
|
+
Alternatively, you can install `loxxy` with Bundler.
|
37
|
+
Add this line to your application's Gemfile:
|
38
|
+
|
39
|
+
gem 'loxxy'
|
40
|
+
|
41
|
+
And then execute:
|
42
|
+
|
43
|
+
$ bundle
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
### 2. Your first `Lox` program
|
48
|
+
Create a text file and enter the following lines:
|
49
|
+
```javascript
|
50
|
+
// Your firs Lox program
|
51
|
+
print "Hello, world.";
|
52
|
+
```
|
53
|
+
|
54
|
+
### 3. Running your program...
|
55
|
+
Assuming that you named the file `hello.lox`, launch the `Loxxy` interpreter in same directory:
|
56
|
+
|
57
|
+
$ loxxy hello.lox
|
58
|
+
|
59
|
+
Lo and behold! The output device displays the famous greeting:
|
60
|
+
|
61
|
+
Hello, world.
|
62
|
+
|
63
|
+
|
64
|
+
Congrats! You ran your first `Lox` program thanks __Loxxy__ gem.
|
65
|
+
For a less superficial encounter with the language jump to the next section.
|
66
|
+
|
67
|
+
## So you want something beefier?...
|
68
|
+
Let's admit it, the hello world example was unimpressive.
|
69
|
+
To a get a taste of `Lox` object-oriented capabilities, let's try another `Hello world` variant:
|
70
|
+
|
71
|
+
```javascript
|
72
|
+
// Object-oriented hello world
|
73
|
+
class Greeter {
|
74
|
+
// in Lox, initializers/constructors are named `init`
|
75
|
+
init(who) {
|
76
|
+
this.interjection = "Hello";
|
77
|
+
this.subject = who;
|
78
|
+
}
|
79
|
+
|
80
|
+
greeting() {
|
81
|
+
this.interjection + ", " + this.subject + ".";
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
var greeter = Greeter("world"); // an instance is created here...
|
86
|
+
print greeter.greeting();
|
87
|
+
```
|
88
|
+
|
89
|
+
Running this version will result in the same famous greeting.
|
90
|
+
|
91
|
+
Our next assignment: compute the first 20 elements of the Fibbonacci sequence.
|
92
|
+
Here's an answer using the `while` loop construct:
|
93
|
+
|
94
|
+
```javascript
|
95
|
+
// Compute the first 20 elements from the Fibbonacci sequence
|
96
|
+
|
97
|
+
var a = 0; // Use the var keyword to declare a new variable
|
98
|
+
var b = 1;
|
99
|
+
var count = 20;
|
100
|
+
|
101
|
+
while (count > 0) {
|
102
|
+
print a;
|
103
|
+
print " ";
|
104
|
+
var tmp = a;
|
105
|
+
a = b;
|
106
|
+
b = tmp + b;
|
107
|
+
count = count - 1;
|
108
|
+
}
|
109
|
+
```
|
14
110
|
|
15
|
-
|
16
|
-
|
17
|
-
object-oriented feaures (classes and objects).
|
18
|
-
The goal is to implement these missing features in Q2 2021.
|
111
|
+
Assuming, that this source code was put in a file named `fibbonacci.lox`, then
|
112
|
+
the command line
|
19
113
|
|
114
|
+
$ loxxy fibbonacci.lox
|
115
|
+
|
116
|
+
Results in:
|
117
|
+
|
118
|
+
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
|
119
|
+
|
120
|
+
Fans of `for` loops will be pleased to find their favorite looping construct.
|
121
|
+
Here again, the Fibbonacci sequence refactored with a `for` loop:
|
122
|
+
|
123
|
+
```javascript
|
124
|
+
// Fibbonacci sequence - version 2
|
125
|
+
var a = 0;
|
126
|
+
var b = 1;
|
127
|
+
var count = 20;
|
128
|
+
|
129
|
+
for (var i = 0; i < count; i = i + 1) {
|
130
|
+
print a;
|
131
|
+
print " ";
|
132
|
+
var tmp = a;
|
133
|
+
a = b;
|
134
|
+
b = tmp + b;
|
135
|
+
}
|
136
|
+
```
|
137
|
+
Lets's call this file `fibbonacci_v2.lox` and execute it thanks `loxxy` CLI:
|
138
|
+
|
139
|
+
$ loxxy fibbonacci_v2.lox
|
140
|
+
|
141
|
+
We see again the same sequence:
|
142
|
+
|
143
|
+
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
|
144
|
+
|
145
|
+
To complete our quick tour of `Lox` language, let's calculate the sequence with a recursive function:
|
146
|
+
|
147
|
+
```javascript
|
148
|
+
// Fibbonacci sequence - version 3
|
149
|
+
var count = 20;
|
150
|
+
|
151
|
+
// Let's define a recursive function
|
152
|
+
fun fib(n) {
|
153
|
+
if (n < 2) return n;
|
154
|
+
return fib(n - 1) + fib(n - 2);
|
155
|
+
}
|
156
|
+
|
157
|
+
// For demo purposes, let's assign the function to a variable
|
158
|
+
var fib_fun = fib;
|
159
|
+
|
160
|
+
for (var i = 0; i < count; i = i + 1) {
|
161
|
+
print fib_fun(i);
|
162
|
+
print " ";
|
163
|
+
}
|
164
|
+
```
|
165
|
+
|
166
|
+
This completes our quick tour of `Lox`, to learn more about the language,
|
167
|
+
check the online book [Crafting Interpreters](https://craftinginterpreters.com/ )
|
20
168
|
|
21
169
|
## What's the fuss about Lox?
|
22
170
|
... Nothing...
|
23
|
-
Bob Nystrom designed a language __simple__ enough so that he could present
|
171
|
+
Bob Nystrom designed a language __simple__ enough so that he could present
|
24
172
|
two implementations (an interpreter, then a compiler) in one single book.
|
25
173
|
|
26
|
-
|
27
|
-
-
|
28
|
-
- Provides datatypes such as booleans, number, strings,
|
29
|
-
- Supports arithmetic operations (+, -, *, / ) and comparison ( >, >= , <, <=)
|
30
|
-
- Implements equality operators (==, !=) and the logical connectors `and` and `or`.
|
31
|
-
- Control flow statements `if`, `for` and `while`
|
32
|
-
- Functions and closures
|
33
|
-
- Object-orientation (classes, methods, inheritance).
|
174
|
+
In other words, __Lox__ contains interesting features found in most general-purpose
|
175
|
+
languages. In addition to that, there are [numerous implementations](https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations) in different languages
|
34
176
|
|
35
|
-
|
36
|
-
languages.
|
177
|
+
Lox interpreters, like `Loxxy` give the unique opportunity for the curious to learn the internals of reasonably-sized language.
|
37
178
|
|
38
179
|
### What's missing in Lox?
|
39
|
-
|
40
|
-
|
41
|
-
- Collections (arrays, maps, ...)
|
42
|
-
- Modules (importing stuff from other packages/files)
|
43
|
-
- Error handling (e.g. exceptions)
|
44
|
-
- Support for concurrency (e.g. threads, coroutines)
|
180
|
+
While `Lox` blends interesting features from the two mainstream paradigms (OO and functional),
|
181
|
+
it doesn't pretend to be used in real-life projects.
|
45
182
|
|
46
|
-
|
183
|
+
In fact, the language was designed to be simple to implement at the expense of missing advanced features.
|
184
|
+
Here are features I'll like to put on my wish list:
|
185
|
+
- Collection classes (e.g. Arrays, Maps (Hash))
|
186
|
+
- Modules
|
187
|
+
- Standard library
|
188
|
+
- Concurrency / parallelism constructs
|
47
189
|
|
48
|
-
|
49
|
-
|
190
|
+
That `Lox` cannot be compared to a full-featured language, is both a drawback and and an opportunity.
|
191
|
+
Indeed, an open-source language that misses some features is an invitation for the curious to tinker and experiment with extensions.
|
192
|
+
There are already a number of programming languages derived from `Lox`...
|
50
193
|
|
51
|
-
|
52
|
-
language, that might be even funnier...
|
194
|
+
## Why `Loxxy`? What's in it for me?...
|
53
195
|
|
54
|
-
|
196
|
+
### Purpose of this project:
|
197
|
+
- To deliver an open source example of a programming language fully implemented in Ruby
|
198
|
+
(from the scanner and parser to an interpreter).
|
199
|
+
- The implementation should be mature enough to run [LoxLox](https://github.com/benhoyt/loxlox),
|
200
|
+
a Lox interpreter written in Lox.
|
201
|
+
|
202
|
+
### Roadmap
|
203
|
+
- Extend the test suite
|
204
|
+
- Improve the error handling
|
205
|
+
- Improve the documentation
|
206
|
+
- Ability run the LoxLox interpreter
|
55
207
|
|
56
208
|
## Hello world example
|
209
|
+
The next examples show how to use the interpreter directly from Ruby code.
|
210
|
+
|
57
211
|
```ruby
|
58
212
|
require 'loxxy'
|
59
213
|
|
@@ -108,48 +262,10 @@ lox_input = <<-LOX_END
|
|
108
262
|
print "Hello, world!";
|
109
263
|
LOX_END
|
110
264
|
|
111
|
-
# Show that the raw parser accepts the above program
|
112
|
-
base_parser = Loxxy::FrontEnd::RawParser.new
|
113
|
-
|
114
|
-
# Now parse the input into a concrete parse tree...
|
115
|
-
ptree = base_parser.parse(lox_input)
|
116
|
-
|
117
|
-
# Display the parse tree thanks to Rley formatters...
|
118
|
-
visitor = Rley::ParseTreeVisitor.new(ptree)
|
119
|
-
tree_formatter = Rley::Formatter::Asciitree.new($stdout)
|
120
|
-
tree_formatter.render(visitor)
|
121
|
-
```
|
122
265
|
|
123
|
-
This is the output produced by the above example:
|
124
|
-
```
|
125
|
-
program
|
126
|
-
+-- declaration_plus
|
127
|
-
| +-- declaration
|
128
|
-
| +-- statement
|
129
|
-
| +-- printStmt
|
130
|
-
| +-- PRINT: 'print'
|
131
|
-
| +-- expression
|
132
|
-
| | +-- assignment
|
133
|
-
| | +-- logic_or
|
134
|
-
| | +-- logic_and
|
135
|
-
| | +-- equality
|
136
|
-
| | +-- comparison
|
137
|
-
| | +-- term
|
138
|
-
| | +-- factor
|
139
|
-
| | +-- unary
|
140
|
-
| | +-- call
|
141
|
-
| | +-- primary
|
142
|
-
| | +-- STRING: '"Hello, world!"'
|
143
|
-
| +-- SEMICOLON: ';'
|
144
|
-
+-- EOF: ''
|
145
|
-
```
|
146
266
|
|
147
267
|
## Suppported Lox language features
|
148
|
-
On one hand, the parser covers the complete Lox grammar and should therefore, in principle,
|
149
|
-
parse any valid Lox program.
|
150
268
|
|
151
|
-
On the other hand, the interpreter is under development and currently it can evaluate only a subset of __Lox__.
|
152
|
-
But the situation is changing almost daily, stay tuned...
|
153
269
|
|
154
270
|
Here are the language features currently supported by the interpreter:
|
155
271
|
|
@@ -377,25 +493,7 @@ fun add4(n) // `add4` will be the name of the function
|
|
377
493
|
print add4(6); // output: 10
|
378
494
|
```
|
379
495
|
|
380
|
-
## Installation
|
381
|
-
|
382
|
-
Add this line to your application's Gemfile:
|
383
|
-
|
384
|
-
```ruby
|
385
|
-
gem 'loxxy'
|
386
|
-
```
|
387
|
-
|
388
|
-
And then execute:
|
389
|
-
|
390
|
-
$ bundle install
|
391
|
-
|
392
|
-
Or install it yourself as:
|
393
|
-
|
394
|
-
$ gem install loxxy
|
395
|
-
|
396
|
-
## Usage
|
397
496
|
|
398
|
-
TODO: Write usage instructions here
|
399
497
|
|
400
498
|
## Other Lox implementations in Ruby
|
401
499
|
|