Class: Yadriggy::Checker

Inherits:
Object
  • Object
show all
Includes:
Yadriggy
Defined in:
lib/yadriggy/checker.rb

Overview

AST checker. It visits the AST nodes and does various checks like type checking.

Constant Summary

Constants included from Yadriggy

DynType, Undef, VERSION, Void

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Yadriggy

debug, debug=, define_syntax, reify, reset_pry

Constructor Details

#initializeChecker

Initializes the object.



80
81
82
83
84
85
86
87
88
# File 'lib/yadriggy/checker.rb', line 80

def initialize
  self.class.check_init_class
  @nerrors = 0
  @messages = []
  @check_list = []
  @current_ast = nil
  @current_env = nil
  @rule_declarator = nil
end

Class Method Details

.rule(node_type) { ... } ⇒ void

This method returns an undefined value.

Defines the rule for a node type.

Parameters:

  • node_type (Class)

    the type of the AST node.

Yields:

  • The block is executed for the node with 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

#astASTnode

Returns the current abstract syntax tree.

Returns:

  • (ASTnode)

    the current abstract syntax tree.



233
234
235
# File 'lib/yadriggy/checker.rb', line 233

def ast
  @current_ast
end

#ast_envObject

Returns the current environment.

Returns:

  • (Object)

    the current environment.



238
239
240
# File 'lib/yadriggy/checker.rb', line 238

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().

Returns:

  • (Object)


186
187
188
189
190
191
192
193
# File 'lib/yadriggy/checker.rb', line 186

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.

Parameters:

Returns:

  • (Object)


154
155
156
157
158
159
160
161
162
163
164
# File 'lib/yadriggy/checker.rb', line 154

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.

Yields:

  • The block is later executed for checking.



247
248
249
250
251
# File 'lib/yadriggy/checker.rb', line 247

def check_later(&proc)
  cur_ast = @current_ast
  cur_env = @current_env
  @check_list << [cur_ast, cur_env, proc]
end

#error!(an_ast, msg = '') ⇒ Object

Records an error message.

Parameters:

  • an_ast (ASTnode)

    the AST causing the error.

  • msg (String) (defaults to: '')

    the error message.



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/yadriggy/checker.rb', line 126

def error!(an_ast, msg='')
  loc  = if an_ast.is_a?(ASTnode)
           an_ast.source_location_string
         else
           ''
         end
  emsg = "#{loc} DSL #{error_group} error. #{msg}"
  @nerrors += 1
  @messages << emsg
  binding.pry if Yadriggy.debug > 1
  emsg
end

#error_found!(an_ast, msg = '') ⇒ void

This method returns an undefined value.

Throws an error.

Parameters:

  • an_ast (ASTnode)

    the AST causing the error.

  • msg (String) (defaults to: '')

    the error message.

Raises:



116
117
118
119
# File 'lib/yadriggy/checker.rb', line 116

def error_found!(an_ast, msg='')
  emsg = error!(an_ast, msg)
  raise CheckError.new(emsg)
end

#error_messagesArray<String>

Gets an array of error messages.

Returns:

  • (Array<String>)

    error messages or [].



100
101
102
# File 'lib/yadriggy/checker.rb', line 100

def error_messages
  @messages
end

#errors?Boolean

Tests whether a type error was found.

Returns:

  • (Boolean)

    true if an error message is recorded.



93
94
95
# File 'lib/yadriggy/checker.rb', line 93

def errors?
  @nerrors > 0
end

#last_errorString|nil

The last error message.

Returns:

  • (String|nil)

    the message.



107
108
109
# File 'lib/yadriggy/checker.rb', line 107

def last_error
  @messages.last
end

#make_base_env(klass) ⇒ Object

Makes a new base environment with the given context class. It is called by check_all. Override this method to customize check_all.

Parameters:

  • klass (Module)

    the context class.



171
172
173
# File 'lib/yadriggy/checker.rb', line 171

def make_base_env(klass)
  klass
end

#proceed(an_ast, envi = nil) ⇒ Object

Applies the rule supplied by the superclass.

Parameters:

  • an_ast (ASTnode)

    an AST.

  • envi (Object) (defaults to: nil)

    an environment object.

Returns:

  • (Object)

    the result of the application.



219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/yadriggy/checker.rb', line 219

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