TIFA

Python Type Inferencer and Flow Analyzer (TIFA)

TIFA uses a number of simplifications of the Python language.
  • Variables cannot change type

  • Variables cannot be deleted

  • Complex types have to be homogenous

  • No introspection or reflective characteristics

  • No dunder methods

  • No closures (maybe?)

  • You cannot write a variable out of scope

  • You cannot read a mutable variable out of scope

  • No multiple inheritance

Additionally, it reads the following as issues:
  • Cannot read a variable without having first written to it.

  • Cannot rewrite a variable unless it has been read.

Important concepts:

Issue

A problematic situation in the submitted code that will be reported but may not stop the execution. However, when an Issue occurs, any results may be invalid.

Error

A situation in execution that terminates the program.

Name

A name of a variable

Scope

The context of a function, with its own namespaces. Represented internally using numeric IDs (Scope IDs).

Scope Chain

A stack of scopes, with the innermost scope on top.

Fully Qualified Name

A string representation of a variable and its scope chain, written using “/”. For example: 0/1/4/my_variable_name

Path

A single path of execution through the control flow; every program has at least one sequential path, but IFs, FORs, WHILEs, etc. can cause multiple paths. Paths are represented using numeric IDs (Path IDs).

State

Information about a Name that indicates things like the variable’s current type and whether that name has been read, set, or overwritten.

Identifier

A wrapper around variables, used to hold their potential non-existence (which is an Issue but not an Error).

Type

A symbolic representation of the variable’s type.

Literal

Sometimes, we need a specialized representation of a literal value to be passed around. This is particularly important for accessing elements in tuples.

Name Map

(Path x Fully Qualified Names) => States

class Tifa(report=<pedal.core.report.Report object>)[source]

TIFA subclass for traversing an AST and finding common issues. You can instantiate this class, manipulate settings, and then process some code or AST.

assign_target(target, target_type, operation=None, store_with_read=False)[source]

Assign the type to the target, handling all kinds of assignment statements, including Names, Tuples/Lists, Subscripts, and Attributes.

Parameters:
  • target (AST) – The target AST Node.

  • target_type (Type) – The new TIFA type.

  • operation (None | ast.op) – The AugAssign operation, if there is one

  • store_with_read – Whether to store the variable as a read variable, or just a write variable.

Returns:

process_ast(ast_tree)[source]

Given an AST, actually performs the type and flow analyses to return a report.

Parameters:

ast_tree (AST) – The AST object

process_code(code, filename=None, reset=True)[source]

Processes the AST of the given source code to generate a report.

Parameters:
  • code (str) – The Python source code

  • filename (str) – The filename of the source code (defaults to the submissions’ main file).

  • reset (bool) – Whether or not to reset the results from the previous analysis before running this one.

Returns:

The successful or successful report object

Return type:

Report

visit(node)[source]

Process this node by calling its appropriate visit_*

Parameters:

node (AST) – The node to visit

Returns:

The type calculated during the visit.

Return type:

Type

visit_AnnAssign(node)[source]
Parameters:

node (AnnAssign)

Returns:

visit_Assign(node)[source]

Simple assignment statement: __targets__ = __value__

Parameters:

node (Assign) – An Assign node

Returns:

None

visit_Attribute(node)[source]
Parameters:

node

Returns:

visit_AugAssign(node)[source]
Parameters:

node (AugAssign)

Returns:

visit_BinOp(node)[source]
Parameters:

node

Returns:

visit_Bool(node)[source]

Visit a constant boolean value.

Parameters:

node (AST) – The boolean value Node.

Returns:

A Bool type.

Return type:

Type

visit_BoolOp(node)[source]
Parameters:

node

Returns:

visit_ClassDef(node)[source]
Parameters:

node

visit_Compare(node)[source]
Parameters:

node

Returns:

visit_Constant(node) Type[source]

Handle new 3.8’s Constant node

visit_Dict(node)[source]

Three types of dictionaries - empty - uniform type - record TODO: Handle records appropriately

visit_DictComp(node)[source]
Parameters:

node

Returns:

visit_Expr(node)[source]

Any expression being used as a statement.

Parameters:

node (AST) – An Expr node

Returns:

visit_For(node)[source]
Parameters:

node

visit_FunctionDef(node)[source]
Parameters:

node

Returns:

visit_GeneratorExp(node)[source]
Parameters:

node

Returns:

visit_If(node)[source]
Parameters:

node

visit_IfExp(node)[source]
Parameters:

node

Returns:

visit_Import(node)[source]
Parameters:

node

visit_ImportFrom(node)[source]
Parameters:

node

visit_Lambda(node)[source]
Parameters:

node

Returns:

visit_List(node)[source]
Parameters:

node

Returns:

visit_ListComp(node)[source]
Parameters:

node

Returns:

visit_Name(node)[source]
Parameters:

node

Returns:

visit_NameConstant(node)[source]
Parameters:

node

Returns:

visit_Num(node)[source]
Parameters:

node

Returns:

visit_Return(node)[source]
Parameters:

node

visit_SetComp(node)[source]
Parameters:

node

Returns:

visit_Slice(node)[source]

Handles a slice by visiting its components; cannot return a value because the slice is always the same type as its value, which is not available on the Slice node itself.

visit_Str(node)[source]
Parameters:

node

Returns:

visit_Subscript(node)[source]
Parameters:

node

Returns:

visit_UnaryOp(node)[source]
Parameters:

node

Returns:

visit_While(node)[source]
Parameters:

node

visit_With(node)[source]
Parameters:

node

visit_comprehension(node)[source]
Parameters:

node

visit_statements(nodes)[source]
Parameters:

nodes

Returns:

tifa_analysis(code=None, report=<pedal.core.report.Report object>)[source]

Perform the TIFA analysis and attach the results to the Report.

Parameters:
  • code (str or None) – The code to evaluate with TIFA. If code is not given, then it will default to the student’s main file.

  • report (pedal.core.report.Report) – The Report object to attach results to.

Returns:

A TifaAnalysis data

bundle containing all the information that TIFA learned.

Return type:

pedal.tifa.tifa_core.TifaAnalysis