Class: Yadriggy::TypeChecker

Inherits:
Checker
  • Object
show all
Defined in:
lib/yadriggy/typecheck.rb

Overview

Type checker for ASTree. This provides several basic methods and utility classes for type checking. It does not specify any specific typing rules. Define a subclass of TypeChecker and write typing rules there.

A type object used by TypeChecker can be an instance of any subclass of Type. It does not have to necessarily be an object representing a "type".

Direct Known Subclasses

RubyTypeChecker

Defined Under Namespace

Classes: FreeVarFinder, TypeDef, TypeEnv

Constant Summary

Constants included from Yadriggy

DynType, Undef, VERSION, Void

Instance Method Summary collapse

Methods inherited from Checker

#ast, #ast_env, #check_all, #check_later, #error!, #error_found!, #error_messages, #errors?, #last_error, #proceed, rule

Methods included from Yadriggy

debug, debug=, define_syntax, reify

Constructor Details

#initializeTypeChecker

Returns a new instance of TypeChecker.



156
157
158
159
160
# File 'lib/yadriggy/typecheck.rb', line 156

def initialize
  super
  @typetable = {}
  @typedefs = {}
end

Instance Method Details

#add_typedef(key) ⇒ TypeDef

Adds a type definition if it does not exist. Here, a type definition is a mapping from instance variables or methods to their types. It is defined per class or individual instance object.

Parameters:

  • key (Module|Object)

    a class or an instance.

Returns:

  • (TypeDef)

    the type definition for the class or instance given by key.



192
193
194
# File 'lib/yadriggy/typecheck.rb', line 192

def add_typedef(key)
  @typedefs[key] || @typedefs[key] = TypeDef.new
end

#error_groupObject



286
287
288
# File 'lib/yadriggy/typecheck.rb', line 286

def error_group
  'type'
end

#make_base_env(klass) ⇒ Object

Makes a new base type environment with the given context class.



213
214
215
# File 'lib/yadriggy/typecheck.rb', line 213

def make_base_env(klass)
  TypeEnv::BaseTypeEnv.new(klass)
end

#type(an_ast, ast_tenv = nil) ⇒ Type

Applies typing rules to determine the type of the given AST. This method is effective in Checker.rule.

It assumes that the AST is processed by Syntax and it has usertype method. An exception is thrown when type checking fails.

Parameters:

  • an_ast (ASTnode|nil)

    an AST or nil.

  • ast_tenv (TypeEnv|nil) (defaults to: nil)

    a type environment or nil.

Returns:

  • (Type)

    the type of the given AST. It memoizes the results.



234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/yadriggy/typecheck.rb', line 234

def type(an_ast, ast_tenv=nil)
  if an_ast.nil?
    DynType
  else
    ast_type = @typetable[an_ast]
    return ast_type unless ast_type.nil?

    rule = self.class.find_rule_entry(an_ast)
    t = apply_typing_rule(rule, an_ast, ast_tenv)
    @typetable[an_ast] = t
  end
end

#type?(an_ast) ⇒ Type|nil

Gets the type of the given AST if its type has been already determined by #type. Only the memoized types are returned.

Parameters:

Returns:

  • (Type|nil)

    the type or nil if not found.



266
267
268
# File 'lib/yadriggy/typecheck.rb', line 266

def type?(an_ast)
  @typetable[an_ast]
end

#type_as(an_ast, a_type) ⇒ Type|nil

Sets the type of an AST to the given type.

Parameters:

  • an_ast (ASTnode|nil)

    an AST.

  • a_type (Type)

    a type.

Returns:

  • (Type|nil)

    the given type a_type.



252
253
254
255
256
257
258
# File 'lib/yadriggy/typecheck.rb', line 252

def type_as(an_ast, a_type)
  if an_ast.nil?
    DynType
  else
    @typetable[an_ast] = a_type
  end
end

#type_assert(is_valid, errmsg = '') ⇒ Object



270
271
272
# File 'lib/yadriggy/typecheck.rb', line 270

def type_assert(is_valid, errmsg='')
  error_found!(@current_ast, errmsg) unless is_valid
end

#type_assert_false(is_invalid, errmsg = '') ⇒ Object



274
275
276
# File 'lib/yadriggy/typecheck.rb', line 274

def type_assert_false(is_invalid, errmsg='')
  error_found!(@current_ast, errmsg) if is_invalid
end

#type_assert_later(&proc) ⇒ Object

Later invokes proc, which performs type checking. This is used for avoiding infinite regression when determining the type of ASTs.



282
283
284
# File 'lib/yadriggy/typecheck.rb', line 282

def type_assert_later(&proc)
  check_later(&proc)
end

#type_envObject

Gets the current type environment.



164
165
166
# File 'lib/yadriggy/typecheck.rb', line 164

def type_env
  @current_env
end

#typecheck(an_ast) ⇒ Object

Applies typing rules to the given AST. It returns the type of the AST or throws a CheckError. This is the entry point of the type checker. It may also type the other ASTs invoked in the given AST.

It assumes that the AST is processed by Syntax and it has usertype method.

This is an alias of check_all() but it memoizes the results.



207
208
209
# File 'lib/yadriggy/typecheck.rb', line 207

def typecheck(an_ast)
  check_all(an_ast)
end

#typedef(key) ⇒ TypeDef|nil

Obtains the type definition associated with key. Here, a type definition is a mapping from instance variables or methods to their types. It is defined per class or individual instance object. If key is nil, nil is returned.

Parameters:

  • key (Module|Object|nil)

    a class or an instance.

Returns:

  • (TypeDef|nil)

    the type definition.



176
177
178
179
180
181
182
# File 'lib/yadriggy/typecheck.rb', line 176

def typedef(key)
  if key.nil?
    nil
  else
    @typedefs[key]
  end
end