loxxy 0.1.03 → 0.1.04
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/CHANGELOG.md +18 -3
- data/lib/loxxy/ast/all_lox_nodes.rb +1 -0
- data/lib/loxxy/ast/ast_builder.rb +5 -0
- data/lib/loxxy/ast/ast_visitor.rb +8 -0
- data/lib/loxxy/ast/lox_return_stmt.rb +21 -0
- data/lib/loxxy/back_end/engine.rb +21 -5
- data/lib/loxxy/back_end/function.rb +7 -0
- data/lib/loxxy/front_end/grammar.rb +1 -1
- data/lib/loxxy/front_end/scanner.rb +2 -0
- data/lib/loxxy/version.rb +1 -1
- data/spec/interpreter_spec.rb +14 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 16614a276ddf1553d4373e5da9ab78d7f03f2fc8cadec6190c28bb27bdd95b99
|
4
|
+
data.tar.gz: 98903f6ec0c9e010fd429f6b1753b34f52b4cfc67c7eafd21b1103c6ac429bba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8278546ef246d8f4d5db72b18d5c91dfa3dc1d7f18f81b7491ca01df38a64495a3b5eb26df0fa18b652f59d56784efb8fe9348b5b65d091aa27a09e6b8f144a4
|
7
|
+
data.tar.gz: deaa7b43f225788b9366610572f5994eec8950a8e66c8159b83a18b874139d322270f274c4753dc28b6926b7c295d42a2f77600211dfbd0df0e24b82e1a155b5
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
|
+
## [0.1.04] - 2021-02-28
|
2
|
+
|
3
|
+
### Added
|
4
|
+
- Class `Ast::LoxReturnStmt` a node that represents a return statement
|
5
|
+
- Method `Ast::ASTBuilder#reduce_return_stmt`
|
6
|
+
- Method `Ast::ASTVisitor#visit_return_stmt` for visiting an `Ast::LoxReturnStmt` node
|
7
|
+
- Method `BackEnd::Engine#after_return_stmt` to handle return statement
|
8
|
+
- Method `BackEnd::Function#!` implementing the logical negation of a function (as value).
|
9
|
+
- Test suite for logical operators (in project repository)
|
10
|
+
- Test suite for block code
|
11
|
+
- Test suite for call and function declaration (initial)
|
12
|
+
|
13
|
+
### Changed
|
14
|
+
- Method `BackEnd::Engine#after_call_expr` now generate a `catch` and `throw` events
|
15
|
+
|
1
16
|
## [0.1.03] - 2021-02-26
|
2
|
-
- Runtime argument
|
17
|
+
- Runtime argument checking for arithmetic and comparison operators
|
3
18
|
|
4
19
|
### Added
|
5
20
|
- Test suite for arithmetic and comparison operators (in project repository)
|
@@ -221,11 +236,11 @@
|
|
221
236
|
- The interpreter can evaluate substraction between two numbers.
|
222
237
|
|
223
238
|
### Added
|
224
|
-
- Method `Datatype::Number#-`
|
239
|
+
- Method `Datatype::Number#-` implementing the subtraction operation
|
225
240
|
|
226
241
|
### Changed
|
227
242
|
- File `README.md` minor editorial changes.
|
228
|
-
- File `lx_string_spec.rb` Added test for string
|
243
|
+
- File `lx_string_spec.rb` Added test for string concatenation
|
229
244
|
- File `number_spec.rb` Added tests for addition and subtraction operations
|
230
245
|
- File `interpreter_spec.rb` Added tests for subtraction operation
|
231
246
|
|
@@ -12,6 +12,7 @@ require_relative 'lox_logical_expr'
|
|
12
12
|
require_relative 'lox_assign_expr'
|
13
13
|
require_relative 'lox_block_stmt'
|
14
14
|
require_relative 'lox_while_stmt'
|
15
|
+
require_relative 'lox_return_stmt'
|
15
16
|
require_relative 'lox_print_stmt'
|
16
17
|
require_relative 'lox_if_stmt'
|
17
18
|
require_relative 'lox_for_stmt'
|
@@ -221,6 +221,11 @@ module Loxxy
|
|
221
221
|
Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
|
222
222
|
end
|
223
223
|
|
224
|
+
# rule('returnStmt' => 'RETURN expression_opt SEMICOLON')
|
225
|
+
def reduce_return_stmt(_production, _range, tokens, theChildren)
|
226
|
+
Ast::LoxReturnStmt.new(tokens[1].position, theChildren[1])
|
227
|
+
end
|
228
|
+
|
224
229
|
# rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as ''
|
225
230
|
def reduce_while_stmt(_production, _range, tokens, theChildren)
|
226
231
|
Ast::LoxWhileStmt.new(tokens[1].position, theChildren[2], theChildren[4])
|
@@ -91,6 +91,14 @@ module Loxxy
|
|
91
91
|
broadcast(:after_print_stmt, aPrintStmt)
|
92
92
|
end
|
93
93
|
|
94
|
+
# Visit event. The visitor is about to visit a return statement.
|
95
|
+
# @param aReturnStmt [AST::LOXReturnStmt] the return statement node to visit
|
96
|
+
def visit_return_stmt(aReturnStmt)
|
97
|
+
broadcast(:before_return_stmt, aReturnStmt)
|
98
|
+
traverse_subnodes(aReturnStmt)
|
99
|
+
broadcast(:after_return_stmt, aReturnStmt, self)
|
100
|
+
end
|
101
|
+
|
94
102
|
# Visit event. The visitor is about to visit a while statement node.
|
95
103
|
# @param aWhileStmt [AST::LOXWhileStmt] the while statement node to visit
|
96
104
|
def visit_while_stmt(aWhileStmt)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lox_compound_expr'
|
4
|
+
|
5
|
+
module Loxxy
|
6
|
+
module Ast
|
7
|
+
class LoxReturnStmt < LoxCompoundExpr
|
8
|
+
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
9
|
+
# @param anExpression [Ast::LoxNode] expression to return
|
10
|
+
def initialize(aPosition, anExpression)
|
11
|
+
super(aPosition, [anExpression])
|
12
|
+
end
|
13
|
+
|
14
|
+
# Part of the 'visitee' role in Visitor design pattern.
|
15
|
+
# @param visitor [Ast::ASTVisitor] the visitor
|
16
|
+
def accept(visitor)
|
17
|
+
visitor.visit_return_stmt(self)
|
18
|
+
end
|
19
|
+
end # class
|
20
|
+
end # module
|
21
|
+
end # module
|
@@ -19,7 +19,7 @@ module Loxxy
|
|
19
19
|
# @return [BackEnd::SymbolTable]
|
20
20
|
attr_reader :symbol_table
|
21
21
|
|
22
|
-
# @return [Array<Datatype::
|
22
|
+
# @return [Array<Datatype::BuiltinDatatype>] Data stack for the expression results
|
23
23
|
attr_reader :stack
|
24
24
|
|
25
25
|
# @return [Hash { Symbol => UnaryOperator}]
|
@@ -98,6 +98,10 @@ module Loxxy
|
|
98
98
|
@ostream.print tos ? tos.to_str : 'nil'
|
99
99
|
end
|
100
100
|
|
101
|
+
def after_return_stmt(_returnStmt, _aVisitor)
|
102
|
+
throw(:return)
|
103
|
+
end
|
104
|
+
|
101
105
|
def after_while_stmt(aWhileStmt, aVisitor)
|
102
106
|
loop do
|
103
107
|
condition = stack.pop
|
@@ -192,21 +196,32 @@ module Loxxy
|
|
192
196
|
callee = stack.pop
|
193
197
|
aCallExpr.arguments.reverse_each { |arg| arg.accept(aVisitor) }
|
194
198
|
|
195
|
-
|
199
|
+
case callee
|
200
|
+
when NativeFunction
|
196
201
|
stack.push callee.call # Pass arguments
|
197
|
-
|
202
|
+
when Function
|
198
203
|
new_env = Environment.new(symbol_table.current_env)
|
199
204
|
symbol_table.enter_environment(new_env)
|
200
205
|
callee.parameters&.each do |param_name|
|
201
206
|
local = Variable.new(param_name, stack.pop)
|
202
207
|
symbol_table.insert(local)
|
203
208
|
end
|
204
|
-
|
209
|
+
catch(:return) do
|
210
|
+
callee.call(aVisitor)
|
211
|
+
throw(:return)
|
212
|
+
end
|
205
213
|
|
206
214
|
symbol_table.leave_environment
|
215
|
+
else
|
216
|
+
raise Loxxy::RuntimeError, 'Can only call functions and classes.'
|
207
217
|
end
|
208
218
|
end
|
209
219
|
|
220
|
+
def complete_call
|
221
|
+
callee = ret_stack.pop
|
222
|
+
symbol_table.leave_environment if callee.kind_of?(Function)
|
223
|
+
end
|
224
|
+
|
210
225
|
def after_grouping_expr(_groupingExpr)
|
211
226
|
# Do nothing: work was already done by visiting /evaluating the subexpression
|
212
227
|
end
|
@@ -255,7 +270,8 @@ module Loxxy
|
|
255
270
|
negate_op = UnaryOperator.new('-', [Datatype::Number])
|
256
271
|
unary_operators[:-@] = negate_op
|
257
272
|
|
258
|
-
negation_op = UnaryOperator.new('!', [Datatype::BuiltinDatatype
|
273
|
+
negation_op = UnaryOperator.new('!', [Datatype::BuiltinDatatype,
|
274
|
+
BackEnd::Function])
|
259
275
|
unary_operators[:!] = negation_op
|
260
276
|
end
|
261
277
|
|
@@ -34,6 +34,13 @@ module Loxxy
|
|
34
34
|
body.empty? ? Datatype::Nil.instance : body.accept(aVisitor)
|
35
35
|
end
|
36
36
|
|
37
|
+
# Logical negation.
|
38
|
+
# As a function is a truthy thing, its negation is thus false.
|
39
|
+
# @return [Datatype::False]
|
40
|
+
def !
|
41
|
+
Datatype::False.instance
|
42
|
+
end
|
43
|
+
|
37
44
|
# Text representation of a Lox function
|
38
45
|
def to_str
|
39
46
|
"<fn #{name}>"
|
@@ -74,7 +74,7 @@ module Loxxy
|
|
74
74
|
rule('elsePart_opt' => [])
|
75
75
|
|
76
76
|
rule('printStmt' => 'PRINT expression SEMICOLON').as 'print_stmt'
|
77
|
-
rule('returnStmt' => 'RETURN expression_opt SEMICOLON')
|
77
|
+
rule('returnStmt' => 'RETURN expression_opt SEMICOLON').as 'return_stmt'
|
78
78
|
rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as 'while_stmt'
|
79
79
|
rule('block' => 'LEFT_BRACE declaration_plus RIGHT_BRACE').as 'block_stmt'
|
80
80
|
rule('block' => 'LEFT_BRACE RIGHT_BRACE').as 'block_empty'
|
@@ -92,6 +92,7 @@ module Loxxy
|
|
92
92
|
|
93
93
|
private
|
94
94
|
|
95
|
+
# rubocop: disable Lint/DuplicateBranch
|
95
96
|
def _next_token
|
96
97
|
skip_intertoken_spaces
|
97
98
|
curr_ch = scanner.peek(1)
|
@@ -125,6 +126,7 @@ module Loxxy
|
|
125
126
|
|
126
127
|
return token
|
127
128
|
end
|
129
|
+
# rubocop: enable Lint/DuplicateBranch
|
128
130
|
|
129
131
|
def build_token(aSymbolName, aLexeme)
|
130
132
|
begin
|
data/lib/loxxy/version.rb
CHANGED
data/spec/interpreter_spec.rb
CHANGED
@@ -424,6 +424,20 @@ LOX_END
|
|
424
424
|
expect(sample_cfg[:ostream].string).to eq('<fn foo><native fn>')
|
425
425
|
end
|
426
426
|
|
427
|
+
it 'should support return statements' do
|
428
|
+
program = <<-LOX_END
|
429
|
+
fun max(a, b) {
|
430
|
+
if (a > b) return a;
|
431
|
+
|
432
|
+
return b;
|
433
|
+
}
|
434
|
+
|
435
|
+
max(3, 2);
|
436
|
+
LOX_END
|
437
|
+
result = subject.evaluate(program)
|
438
|
+
expect(result).to eq(3)
|
439
|
+
end
|
440
|
+
|
427
441
|
it 'should print the hello world message' do
|
428
442
|
expect { subject.evaluate(hello_world) }.not_to raise_error
|
429
443
|
expect(sample_cfg[:ostream].string).to eq('Hello, world!')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loxxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.04
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|
@@ -103,6 +103,7 @@ files:
|
|
103
103
|
- lib/loxxy/ast/lox_node.rb
|
104
104
|
- lib/loxxy/ast/lox_noop_expr.rb
|
105
105
|
- lib/loxxy/ast/lox_print_stmt.rb
|
106
|
+
- lib/loxxy/ast/lox_return_stmt.rb
|
106
107
|
- lib/loxxy/ast/lox_seq_decl.rb
|
107
108
|
- lib/loxxy/ast/lox_unary_expr.rb
|
108
109
|
- lib/loxxy/ast/lox_var_stmt.rb
|