Class: Yadriggy::Checker
- Inherits:
-
Object
- Object
- Yadriggy::Checker
- Includes:
- Yadriggy
- Defined in:
- lib/yadriggy/checker.rb
Overview
AST checker. It visits the AST nodes and does various checks like type checking.
Direct Known Subclasses
Constant Summary
Constants included from Yadriggy
Class Method Summary collapse
-
.all_rules ⇒ Array<Hash>
All the rules defined so far.
-
.check_init_class ⇒ Object
Initializes this class if necessary.
-
.find_rule_entry(ast) ⇒ Pair<Proc,Class>
internal-use only.
-
.rule(node_type) { ... } ⇒ void
Defines the rule for a node type.
Instance Method Summary collapse
-
#apply_typing_rule(rule, an_ast, ast_tenv) ⇒ Object
internal use only.
-
#ast ⇒ ASTnode
The current abstract syntax tree.
-
#ast_env ⇒ Object
The current environment.
-
#check(an_ast, ast_env = nil) ⇒ Object
Applies rules to the given AST.
-
#check_all(an_ast) ⇒ Object
Applies rules to the given AST.
-
#check_later { ... } ⇒ void
Later invokes the block, which performs checking.
-
#error ⇒ String
returns nil.
- #error_found!(an_ast, msg = '') ⇒ Object
- #error_group ⇒ Object
-
#initialize ⇒ Checker
constructor
Initializes the object.
-
#make_base_env(klass) ⇒ Object
Makes a new base environment with the given context class.
-
#proceed(an_ast, envi = nil) ⇒ Type
Applies the rule supplied by the superclass.
Methods included from Yadriggy
debug, debug=, define_syntax, reify
Constructor Details
#initialize ⇒ Checker
Initializes the object.
78 79 80 81 82 83 84 85 |
# File 'lib/yadriggy/checker.rb', line 78 def initialize self.class.check_init_class @error = nil @check_list = [] @current_ast = nil @current_env = nil @rule_declarator = nil end |
Class Method Details
.all_rules ⇒ Array<Hash>
Returns all the rules defined so far.
35 36 37 |
# File 'lib/yadriggy/checker.rb', line 35 def self.all_rules [@rules, @rule_declarators] end |
.check_init_class ⇒ Object
Initializes this class if necessary.
29 30 31 |
# File 'lib/yadriggy/checker.rb', line 29 def self.check_init_class init_class if @rules.nil? end |
.find_rule_entry(ast) ⇒ Pair<Proc,Class>
internal-use only. Don’t call this.
55 56 57 |
# File 'lib/yadriggy/checker.rb', line 55 def self.find_rule_entry(ast) find_rule_entry2(ast.class, ast.usertype) end |
.rule(node_type) { ... } ⇒ void
This method returns an undefined value.
Defines the rule for a node type.
21 22 23 24 25 |
# File 'lib/yadriggy/checker.rb', line 21 def self.rule(node_type, &proc) init_class if @rules.nil? @rules[node_type] = proc @rule_declarators[node_type] = self end |
Instance Method Details
#apply_typing_rule(rule, an_ast, ast_tenv) ⇒ Object
internal use only
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/yadriggy/checker.rb', line 141 def apply_typing_rule(rule, an_ast, ast_tenv) if rule.nil? error_found!(an_ast, "no typing rule for #{an_ast.class}") else old_ast = @current_ast old_tenv = @current_env old_declarator = @rule_declarator @current_ast = an_ast @current_env = ast_tenv unless ast_tenv.nil? @rule_declarator = rule[1] t = instance_exec(&rule[0]) @rule_declarator = old_declarator @current_env = old_tenv @current_ast = old_ast return t end end |
#ast ⇒ ASTnode
Returns the current abstract syntax tree.
177 178 179 |
# File 'lib/yadriggy/checker.rb', line 177 def ast @current_ast end |
#ast_env ⇒ Object
Returns the current environment.
182 183 184 |
# File 'lib/yadriggy/checker.rb', line 182 def ast_env @current_env end |
#check(an_ast, ast_env = nil) ⇒ Object
Applies rules to the given AST.
It assumes that ast is processed by Syntax and it has usertype method. An exception is thrown when the checking fails. ast may be nil.
The environment given to this method can be accessed in the rules through ast_env(). It is optional and can be any object. The initial one is made by make_base_env().
130 131 132 133 134 135 136 137 |
# File 'lib/yadriggy/checker.rb', line 130 def check(an_ast, ast_env=nil) if an_ast.nil? nil else rule = self.class.find_rule_entry(an_ast) apply_typing_rule(rule, an_ast, ast_env) end end |
#check_all(an_ast) ⇒ Object
Applies rules to the given AST. It returns the result of the rule-application or throws a CheckError. This is the entry point of the checker. It may also check the other ASTs invoked in the given AST.
101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/yadriggy/checker.rb', line 101 def check_all(an_ast) return nil if an_ast.nil? an_ast = an_ast.tree if an_ast.is_a?(ASTree) t = check(an_ast, make_base_env(an_ast.get_context_class)) until (checked = @check_list.pop).nil? @current_ast = checked[0] @current_env = checked[1] checked[2].call end t end |
#check_later { ... } ⇒ void
This method returns an undefined value.
Later invokes the block, which performs checking. The method immediately returns. This is used for avoiding infinite regression during the checking.
191 192 193 194 195 |
# File 'lib/yadriggy/checker.rb', line 191 def check_later(&proc) cur_ast = @current_ast cur_env = @current_env @check_list << [cur_ast, cur_env, proc] end |
#error ⇒ String
returns nil.
89 90 91 |
# File 'lib/yadriggy/checker.rb', line 89 def error @error || '' end |
#error_found!(an_ast, msg = '') ⇒ Object
198 199 200 201 202 203 204 205 206 207 |
# File 'lib/yadriggy/checker.rb', line 198 def error_found!(an_ast, msg='') loc = if an_ast.is_a?(ASTnode) an_ast.source_location_string else '' end @error = "#{loc} DSL #{error_group} error. #{msg}" binding.pry if Yadriggy.debug > 1 raise CheckError.new(@error) end |
#error_group ⇒ Object
210 211 212 |
# File 'lib/yadriggy/checker.rb', line 210 def error_group '' end |
#make_base_env(klass) ⇒ Object
Makes a new base environment with the given context class.
115 116 117 |
# File 'lib/yadriggy/checker.rb', line 115 def make_base_env(klass) klass end |
#proceed(an_ast, envi = nil) ⇒ Type
Applies the rule supplied by the superclass.
163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/yadriggy/checker.rb', line 163 def proceed(an_ast, envi=nil) rule = if @rule_declarator&.superclass == Object nil else @rule_declarator&.superclass.find_rule_entry(an_ast) end if rule.nil? error_found!(an_ast, 'no more rule. we cannot proceed') else apply_typing_rule(rule, an_ast, envi) end end |