loxxy 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1fc5399ac3346487808eeb40403b3324cca384e3c6820d965b75f2e320759d2c
4
- data.tar.gz: f9b6497d87036f6c88ed09a72113a1ea004df9db8fd9bb945672c370993f7fde
3
+ metadata.gz: aee9fb6c5101bc39682ab401ffc0434aea9e6c4115f74a4f641d0df2d68a03ad
4
+ data.tar.gz: ccc11c428ef206db9129fabbb97526df3477e03c5dce0b1b5a2f758425c8f9cb
5
5
  SHA512:
6
- metadata.gz: 0b0fa0313a0b37882d0398238a65f10b6ea8ab4325447e1f4690ea7100bdb85dead8cb15d8e1e56b422741697d636c7e2c114cf17ad43781dc23462ab51c93af
7
- data.tar.gz: b93b3d01a0e80def496ecfeb955e64000cc88149229ceb97e2743ccda863ec23677958aad9423dd0ca433d72451e120be6fa40247db7cbc49710ac8c17ea8987
6
+ metadata.gz: dbb1a28eb85868636b304aa3ec3c2fb71f3f37f5c573740bd7d577ed4e88374ce1fea5446e39429168228e68bedbddfccd554bc6c88ec7996621956e11a42a3c
7
+ data.tar.gz: 3b4c1d6b0996a351cfd7dae5d8f80683fcbdd1eeecc17c3a7932b0675285700dfecdabecc31f505243ffaf2f1bbc1bd8babb604c154f53dad0019c4ad96b007a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [0.1.11] - 2021-04-03
2
+ - Intermediate version: `Loxxy` does class declarations
3
+
4
+ ### New
5
+ - Class `Ast::LoxClassStmt` a syntax node that represents a class declaration
6
+ - Method `Ast::ASTBuilder#reduce_class_decl` creates a `LoxClassStmt` instance
7
+ - Method `Ast::ASTBuilder#reduce_class_name`
8
+ - Method `Ast::ASTBuilder#reduce_reduce_class_body` collect the methods of the class
9
+ - Method `Ast::ASTBuilder#reduce_method_plus_more` for dealing with methods
10
+ - Method `Ast::ASTBuilder#reduce_method_plus_end`
11
+ - Method `Ast::ASTVisitor#visit_class_stmt` for visiting an `Ast::LoxClassStmt` node
12
+ - Method `Ast::LoxBlockStmt#empty?` returns true if the code block is empty
13
+ - Method `BackEnd::Engine#after_class_stmt`
14
+ - Method `BackEnd::Resolver#after_class_stmt`
15
+ - Method `BackEnd::Resolver#before_class_stmt`
16
+ - Class `BackEnd::LoxClass` implementation of a Lox class.
17
+
18
+ ### CHANGED
19
+ - File `grammar.rb` refactoring of class declaration syntax rules
20
+
1
21
  ## [0.1.10] - 2021-03-31
2
22
  - Flag return statements occurring outside functions as an error
3
23
 
@@ -110,9 +130,9 @@
110
130
  - Method `Ast::ASTVisitor#visit_fun_stmt` for visiting an `Ast::LoxFunStmt` node
111
131
  - Method `Ast::LoxBlockStmt#empty?` returns true if the code block is empty
112
132
  - Method `BackEnd::Engine#after_fun_stmt`
113
- - Method `Backend::NativeFunction#call`
114
- - Method `Backend::NativeFunction#to_str`
115
- - Method `Backend::Function` implementation of a function object.
133
+ - Method `BackEnd::NativeFunction#call`
134
+ - Method `BackEnd::NativeFunction#to_str`
135
+ - Method `BackEnd::LoxFunction` implementation of a function object.
116
136
 
117
137
  ### Changed
118
138
  - Method `BackEnd::Engine#after_call_expr`
@@ -17,4 +17,5 @@ require_relative 'lox_print_stmt'
17
17
  require_relative 'lox_if_stmt'
18
18
  require_relative 'lox_for_stmt'
19
19
  require_relative 'lox_var_stmt'
20
+ require_relative 'lox_class_stmt'
20
21
  require_relative 'lox_seq_decl'
@@ -163,6 +163,31 @@ module Loxxy
163
163
  [theChildren[0]]
164
164
  end
165
165
 
166
+ # rule('classDecl' => 'CLASS classNaming class_body')
167
+ def reduce_class_decl(_production, _range, _tokens, theChildren)
168
+ Ast::LoxClassStmt.new(tokens[1].position, theChildren[1], theChildren[2])
169
+ end
170
+
171
+ # rule('classNaming' => 'IDENTIFIER')
172
+ def reduce_class_name(_production, _range, _tokens, theChildren)
173
+ theChildren[0].token.lexeme
174
+ end
175
+
176
+ # rule('class_body' => 'LEFT_BRACE methods_opt RIGHT_BRACE')
177
+ def reduce_class_body(_production, _range, _tokens, theChildren)
178
+ theChildren[1]
179
+ end
180
+
181
+ # rule('method_plus' => 'method_plus function')
182
+ def reduce_method_plus_more(_production, _range, _tokens, theChildren)
183
+ theChildren[0] << theChildren[1]
184
+ end
185
+
186
+ # rule('method_plus' => 'function')
187
+ def reduce_method_plus_end(_production, _range, _tokens, theChildren)
188
+ theChildren
189
+ end
190
+
166
191
  # rule('funDecl' => 'FUN function')
167
192
  def reduce_fun_decl(_production, _range, _tokens, theChildren)
168
193
  theChildren[1]
@@ -67,6 +67,14 @@ module Loxxy
67
67
  broadcast(:after_var_stmt, aVarStmt)
68
68
  end
69
69
 
70
+ # Visit event. The visitor is about to visit a class declaration.
71
+ # @param aXlassStmt [AST::LOXClassStmt] the for statement node to visit
72
+ def visit_class_stmt(aClassStmt)
73
+ broadcast(:before_class_stmt, aClassStmt)
74
+ traverse_subnodes(aClassStmt) # The methods are visited here...
75
+ broadcast(:after_class_stmt, aClassStmt, self)
76
+ end
77
+
70
78
  # Visit event. The visitor is about to visit a for statement.
71
79
  # @param aForStmt [AST::LOXForStmt] the for statement node to visit
72
80
  def visit_for_stmt(aForStmt)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lox_compound_expr'
4
+
5
+ module Loxxy
6
+ module Ast
7
+ class LoxClassStmt < LoxCompoundExpr
8
+ attr_reader :name
9
+
10
+ # @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
11
+ # @param condExpr [Loxxy::Ast::LoxNode] iteration condition
12
+ # @param theBody [Loxxy::Ast::LoxNode]
13
+ def initialize(aPosition, aName, theMethods)
14
+ super(aPosition, theMethods)
15
+ @name = aName.dup
16
+ end
17
+
18
+ # Part of the 'visitee' role in Visitor design pattern.
19
+ # @param visitor [Ast::ASTVisitor] the visitor
20
+ def accept(visitor)
21
+ visitor.visit_class_stmt(self)
22
+ end
23
+
24
+ alias body subnodes
25
+ end # class
26
+ end # module
27
+ end # module
@@ -16,7 +16,7 @@ module Loxxy
16
16
  # @param body [Ast::LoxBlockStmt]
17
17
  def initialize(aPosition, aName, paramList, aBody)
18
18
  super(aPosition, [])
19
- @name = aName
19
+ @name = aName.dup
20
20
  @params = paramList
21
21
  @body = aBody
22
22
  end
@@ -3,6 +3,7 @@
3
3
  # Load all the classes implementing AST nodes
4
4
  require_relative '../ast/all_lox_nodes'
5
5
  require_relative 'binary_operator'
6
+ require_relative 'lox_class'
6
7
  require_relative 'lox_function'
7
8
  require_relative 'resolver'
8
9
  require_relative 'symbol_table'
@@ -68,6 +69,12 @@ module Loxxy
68
69
  # Do nothing, subnodes were already evaluated
69
70
  end
70
71
 
72
+ def after_class_stmt(aClassStmt, _visitor)
73
+ klass = LoxClass.new(aClassStmt.name, aClassStmt.methods, self)
74
+ new_var = Variable.new(aClassStmt.name, klass)
75
+ symbol_table.insert(new_var)
76
+ end
77
+
71
78
  def before_var_stmt(aVarStmt)
72
79
  new_var = Variable.new(aVarStmt.name, Datatype::Nil.instance)
73
80
  symbol_table.insert(new_var)
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../datatype/all_datatypes'
4
+
5
+ module Loxxy
6
+ module BackEnd
7
+ # Representation of a Lox class.
8
+ class LoxClass
9
+ # @return [String] The name of the class
10
+ attr_reader :name
11
+
12
+ # @return [Array<>] the list of methods
13
+ attr_reader :methods
14
+ attr_reader :stack
15
+
16
+ # Create a class with given name
17
+ # @param aName [String] The name of the class
18
+ def initialize(aName, theMethods, anEngine)
19
+ @name = aName.dup
20
+ @methods = theMethods
21
+ @stack = anEngine.stack
22
+ end
23
+
24
+ def accept(_visitor)
25
+ stack.push self
26
+ end
27
+
28
+ # Logical negation.
29
+ # As a function is a truthy thing, its negation is thus false.
30
+ # @return [Datatype::False]
31
+ def !
32
+ Datatype::False.instance
33
+ end
34
+
35
+ # Text representation of a Lox function
36
+ def to_str
37
+ name
38
+ end
39
+ end # class
40
+ end # module
41
+ end # module
@@ -6,7 +6,6 @@ module Loxxy
6
6
  module BackEnd
7
7
  # rubocop: disable Style/AccessorGrouping
8
8
  # Representation of a Lox function.
9
- # It is a named slot that can be associated with a value at the time.
10
9
  class LoxFunction
11
10
  # @return [String] The name of the function (if any)
12
11
  attr_reader :name
@@ -18,7 +17,7 @@ module Loxxy
18
17
  attr_reader :closure
19
18
 
20
19
  # Create a function with given name
21
- # @param aName [String] The name of the variable
20
+ # @param aName [String] The name of the function
22
21
  def initialize(aName, parameterList, aBody, anEngine)
23
22
  @name = aName.dup
24
23
  @parameters = parameterList
@@ -53,6 +53,15 @@ module Loxxy
53
53
  end_scope
54
54
  end
55
55
 
56
+ # A class declaration adds a new variable to current scope
57
+ def before_class_stmt(aClassStmt)
58
+ declare(aClassStmt.name)
59
+ end
60
+
61
+ def after_class_stmt(aClassStmt, _visitor)
62
+ define(aClassStmt.name)
63
+ end
64
+
56
65
  def before_for_stmt(aForStmt)
57
66
  before_block_stmt(aForStmt)
58
67
  end
@@ -122,7 +131,7 @@ module Loxxy
122
131
  def before_fun_stmt(aFunStmt, aVisitor)
123
132
  declare(aFunStmt.name)
124
133
  define(aFunStmt.name)
125
- resolve_function(aFunStmt, :function ,aVisitor)
134
+ resolve_function(aFunStmt, :function, aVisitor)
126
135
  end
127
136
 
128
137
  private
@@ -37,12 +37,14 @@ module Loxxy
37
37
  rule('declaration' => 'varDecl')
38
38
  rule('declaration' => 'statement')
39
39
 
40
- rule('classDecl' => 'CLASS classNaming class_body')
40
+ rule('classDecl' => 'CLASS classNaming class_body').as 'class_decl'
41
41
  rule('classNaming' => 'IDENTIFIER LESS IDENTIFIER')
42
- rule('classNaming' => 'IDENTIFIER')
43
- rule('class_body' => 'LEFT_BRACE function_star RIGHT_BRACE')
44
- rule('function_star' => 'function_star function')
45
- rule('function_star' => [])
42
+ rule('classNaming' => 'IDENTIFIER').as 'class_name'
43
+ rule('class_body' => 'LEFT_BRACE methods_opt RIGHT_BRACE').as 'class_body'
44
+ rule('methods_opt' => 'method_plus')
45
+ rule('methods_opt' => [])
46
+ rule('method_plus' => 'method_plus function').as 'method_plus_more'
47
+ rule('method_plus' => 'function').as 'method_plus_end'
46
48
 
47
49
  rule('funDecl' => 'FUN function').as 'fun_decl'
48
50
 
data/lib/loxxy/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.1.10'
4
+ VERSION = '0.1.11'
5
5
  end
@@ -451,6 +451,23 @@ LOX_END
451
451
  end
452
452
  # rubocop: enable Style/StringConcatenation
453
453
 
454
+ it 'should support class declaration' do
455
+ program = <<-LOX_END
456
+ class Duck {
457
+ noise() {
458
+ quack();
459
+ }
460
+
461
+ quack() {
462
+ print "quack";
463
+ }
464
+ }
465
+ print Duck;
466
+ LOX_END
467
+ expect { subject.evaluate(program) }.not_to raise_error
468
+ expect(sample_cfg[:ostream].string).to eq('Duck')
469
+ end
470
+
454
471
  it 'should print the hello world message' do
455
472
  program = <<-LOX_END
456
473
  var greeting = "Hello"; // Declaring a variable
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.10
4
+ version: 0.1.11
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-03-31 00:00:00.000000000 Z
11
+ date: 2021-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -93,6 +93,7 @@ files:
93
93
  - lib/loxxy/ast/lox_binary_expr.rb
94
94
  - lib/loxxy/ast/lox_block_stmt.rb
95
95
  - lib/loxxy/ast/lox_call_expr.rb
96
+ - lib/loxxy/ast/lox_class_stmt.rb
96
97
  - lib/loxxy/ast/lox_compound_expr.rb
97
98
  - lib/loxxy/ast/lox_for_stmt.rb
98
99
  - lib/loxxy/ast/lox_fun_stmt.rb
@@ -113,6 +114,7 @@ files:
113
114
  - lib/loxxy/back_end/engine.rb
114
115
  - lib/loxxy/back_end/entry.rb
115
116
  - lib/loxxy/back_end/environment.rb
117
+ - lib/loxxy/back_end/lox_class.rb
116
118
  - lib/loxxy/back_end/lox_function.rb
117
119
  - lib/loxxy/back_end/resolver.rb
118
120
  - lib/loxxy/back_end/symbol_table.rb