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, reset_pry

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.



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

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

#error_groupObject



292
293
294
# File 'lib/yadriggy/typecheck.rb', line 292

def error_group
  'type'
end

#make_base_env(klass) ⇒ TypeEnv

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

Returns:

  • (TypeEnv)

    the type enviornment.



219
220
221
# File 'lib/yadriggy/typecheck.rb', line 219

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.



240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/yadriggy/typecheck.rb', line 240

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.



272
273
274
# File 'lib/yadriggy/typecheck.rb', line 272

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

#type_as(an_ast, a_type) ⇒ Type|DynType

Sets the type of an AST to the given type.

Parameters:

  • an_ast (ASTnode|nil)

    an AST.

  • a_type (Type)

    a type.

Returns:



258
259
260
261
262
263
264
# File 'lib/yadriggy/typecheck.rb', line 258

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



276
277
278
# File 'lib/yadriggy/typecheck.rb', line 276

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

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



280
281
282
# File 'lib/yadriggy/typecheck.rb', line 280

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.



288
289
290
# File 'lib/yadriggy/typecheck.rb', line 288

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

#type_envTypeEnv

Gets the current type environment.

Returns:

  • (TypeEnv)

    the type enviornment.



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

def type_env
  @current_env
end

#typecheck(an_ast) ⇒ Type

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.

Parameters:

Returns:

  • (Type)

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



211
212
213
# File 'lib/yadriggy/typecheck.rb', line 211

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.



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

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