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

Constructor Details

#initializeChecker

Initializes the object.



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

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.



228
229
230
# File 'lib/yadriggy/checker.rb', line 228

def ast
  @current_ast
end

#ast_envObject

Returns the current environment.

Returns:

  • (Object)

    the current environment.



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

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)


181
182
183
184
185
186
187
188
# File 'lib/yadriggy/checker.rb', line 181

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)


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

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.



242
243
244
245
246
# File 'lib/yadriggy/checker.rb', line 242

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.



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

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:



114
115
116
117
# File 'lib/yadriggy/checker.rb', line 114

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 [].



98
99
100
# File 'lib/yadriggy/checker.rb', line 98

def error_messages
  @messages
end

#errors?Boolean

Tests whether a type error was found.

Returns:

  • (Boolean)

    true if an error message is recorded.



91
92
93
# File 'lib/yadriggy/checker.rb', line 91

def errors?
  @nerrors > 0
end

#last_errorString|nil

The last error message.

Returns:

  • (String|nil)

    the message.



105
106
107
# File 'lib/yadriggy/checker.rb', line 105

def last_error
  @messages.last
end

#make_base_env(klass) ⇒ Object

Makes a new base environment with the given context class.

Parameters:

  • klass (Module)

    the context class.



166
167
168
# File 'lib/yadriggy/checker.rb', line 166

def make_base_env(klass)
  klass
end

#proceed(an_ast, envi = nil) ⇒ Type

Applies the rule supplied by the superclass.

Parameters:

  • an_ast (ASTnode)

    an AST.

  • envi (Object) (defaults to: nil)

    an environment object.

Returns:

  • (Type)

    the type of the given AST.



214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/yadriggy/checker.rb', line 214

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