Class: Loxxy::BackEnd::Resolver
- Inherits:
-
Object
- Object
- Loxxy::BackEnd::Resolver
- Defined in:
- lib/loxxy/back_end/resolver.rb
Overview
A class aimed to perform variable resolution when it visits the parse tree. Resolving means retrieve the declaration of a variable/function everywhere it is referenced.
Instance Attribute Summary collapse
-
#locals ⇒ Hash {LoxNode => Integer}
readonly
A map from a LoxNode involving a variable and the number of enclosing scopes where it is declared.
-
#scopes ⇒ Array<Hash{String => Boolean}>
readonly
A stack of Hashes of the form String => Boolean.
Instance Method Summary collapse
-
#after_assign_expr(anAssignExpr, aVisitor) ⇒ Object
Assignment expressions require their variables resolved.
- #after_block_stmt(_aBlockStmt) ⇒ Object
- #after_call_expr(aCallExpr, aVisitor) ⇒ Object
- #after_for_stmt(aForStmt, aVisitor) ⇒ Object
- #after_if_stmt(anIfStmt, aVisitor) ⇒ Object
- #after_var_stmt(aVarStmt) ⇒ Object
- #after_variable_expr(aVarExpr, aVisitor) ⇒ Object
- #after_while_stmt(aWhileStmt, aVisitor) ⇒ Object
-
#analyze(aVisitor) ⇒ Loxxy::Datatype::BuiltinDatatype
Given an abstract syntax parse tree visitor, launch the visit and execute the visit events in the output stream.
-
#before_block_stmt(_aBlockStmt) ⇒ Object
block statement introduces a new scope.
- #before_for_stmt(aForStmt) ⇒ Object
-
#before_fun_stmt(aFunStmt, aVisitor) ⇒ Object
function declaration creates a new scope for its body & binds its parameters for that scope.
-
#before_var_stmt(aVarStmt) ⇒ Object
A variable declaration adds a new variable to current scope.
-
#before_variable_expr(aVarExpr) ⇒ Object
Variable expressions require their variables resolved.
-
#initialize ⇒ Resolver
constructor
A new instance of Resolver.
Constructor Details
#initialize ⇒ Resolver
Returns a new instance of Resolver.
25 26 27 28 |
# File 'lib/loxxy/back_end/resolver.rb', line 25 def initialize @scopes = [] @locals = {} end |
Instance Attribute Details
#locals ⇒ Hash {LoxNode => Integer} (readonly)
A map from a LoxNode involving a variable and the number of enclosing scopes where it is declared.
23 24 25 |
# File 'lib/loxxy/back_end/resolver.rb', line 23 def locals @locals end |
#scopes ⇒ Array<Hash{String => Boolean}> (readonly)
A stack of Hashes of the form String => Boolean
18 19 20 |
# File 'lib/loxxy/back_end/resolver.rb', line 18 def scopes @scopes end |
Instance Method Details
#after_assign_expr(anAssignExpr, aVisitor) ⇒ Object
Assignment expressions require their variables resolved
82 83 84 |
# File 'lib/loxxy/back_end/resolver.rb', line 82 def after_assign_expr(anAssignExpr, aVisitor) resolve_local(anAssignExpr, aVisitor) end |
#after_block_stmt(_aBlockStmt) ⇒ Object
47 48 49 |
# File 'lib/loxxy/back_end/resolver.rb', line 47 def after_block_stmt(_aBlockStmt) end_scope end |
#after_call_expr(aCallExpr, aVisitor) ⇒ Object
98 99 100 101 102 |
# File 'lib/loxxy/back_end/resolver.rb', line 98 def after_call_expr(aCallExpr, aVisitor) # Evaluate callee part aCallExpr.callee.accept(aVisitor) aCallExpr.arguments.reverse_each { |arg| arg.accept(aVisitor) } end |
#after_for_stmt(aForStmt, aVisitor) ⇒ Object
55 56 57 58 59 60 |
# File 'lib/loxxy/back_end/resolver.rb', line 55 def after_for_stmt(aForStmt, aVisitor) aForStmt.test_expr.accept(aVisitor) aForStmt.body_stmt.accept(aVisitor) aForStmt.update_expr&.accept(aVisitor) after_block_stmt(aForStmt) end |
#after_if_stmt(anIfStmt, aVisitor) ⇒ Object
62 63 64 65 |
# File 'lib/loxxy/back_end/resolver.rb', line 62 def after_if_stmt(anIfStmt, aVisitor) anIfStmt.then_stmt.accept(aVisitor) anIfStmt.else_stmt&.accept(aVisitor) end |
#after_var_stmt(aVarStmt) ⇒ Object
77 78 79 |
# File 'lib/loxxy/back_end/resolver.rb', line 77 def after_var_stmt(aVarStmt) define(aVarStmt.name) end |
#after_variable_expr(aVarExpr, aVisitor) ⇒ Object
94 95 96 |
# File 'lib/loxxy/back_end/resolver.rb', line 94 def after_variable_expr(aVarExpr, aVisitor) resolve_local(aVarExpr, aVisitor) end |
#after_while_stmt(aWhileStmt, aVisitor) ⇒ Object
67 68 69 70 |
# File 'lib/loxxy/back_end/resolver.rb', line 67 def after_while_stmt(aWhileStmt, aVisitor) aWhileStmt.body.accept(aVisitor) aWhileStmt.condition.accept(aVisitor) end |
#analyze(aVisitor) ⇒ Loxxy::Datatype::BuiltinDatatype
Given an abstract syntax parse tree visitor, launch the visit and execute the visit events in the output stream.
34 35 36 37 38 39 40 |
# File 'lib/loxxy/back_end/resolver.rb', line 34 def analyze(aVisitor) begin_scope aVisitor.subscribe(self) aVisitor.start aVisitor.unsubscribe(self) end_scope end |
#before_block_stmt(_aBlockStmt) ⇒ Object
block statement introduces a new scope
43 44 45 |
# File 'lib/loxxy/back_end/resolver.rb', line 43 def before_block_stmt(_aBlockStmt) begin_scope end |
#before_for_stmt(aForStmt) ⇒ Object
51 52 53 |
# File 'lib/loxxy/back_end/resolver.rb', line 51 def before_for_stmt(aForStmt) before_block_stmt(aForStmt) end |
#before_fun_stmt(aFunStmt, aVisitor) ⇒ Object
function declaration creates a new scope for its body & binds its parameters for that scope
105 106 107 108 109 |
# File 'lib/loxxy/back_end/resolver.rb', line 105 def before_fun_stmt(aFunStmt, aVisitor) declare(aFunStmt.name) define(aFunStmt.name) resolve_function(aFunStmt, aVisitor) end |
#before_var_stmt(aVarStmt) ⇒ Object
A variable declaration adds a new variable to current scope
73 74 75 |
# File 'lib/loxxy/back_end/resolver.rb', line 73 def before_var_stmt(aVarStmt) declare(aVarStmt.name) end |
#before_variable_expr(aVarExpr) ⇒ Object
Variable expressions require their variables resolved
87 88 89 90 91 92 |
# File 'lib/loxxy/back_end/resolver.rb', line 87 def before_variable_expr(aVarExpr) var_name = aVarExpr.name if !scopes.empty? && (scopes.last[var_name] == false) raise StandardError, "Can't read variable #{var_name} in its own initializer" end end |