Module PythonFrontend.PyEnv

module Ident = PyCommon.Ident
module Info : sig ... end

Type information about various entities (toplevel declarations, temporaries, ...).

module Symbol : sig ... end
module Signature : sig ... end
module DataStack : sig ... end

In Python, everything is an object, and the interpreter maintains a stack of references to such objects. Pushing and popping on the stack are always references to objets that leave in a heap. There is no need to model this heap, but the data stack is quite important.

type t

Global environment used during bytecode processing. Stores common global information like the toplevel symbols processed so far, or more local ones like the set of labels or variable ids currently used by a declaration.

module Label : sig ... end
type class_info = {
  1. qualified_name : Ident.t;
  2. parents : Ident.t list;
}

Class level info. For now, only the parent info (if present) is tracked, supporting multiple inheritance and its full qualified name (for nested classes). We may track more information in the future, like being an abstract class, a dataclass, ...

type method_info = {
  1. signature : Signature.t;
  2. default_arguments : T.Exp.t list;
}

Method level info. We store a method/function signature, and its default arugments

val empty : Ident.t -> t
val loc : t -> T.Location.t

Return the last recorded line information from the Python code-unit, if any.

val stack : t -> DataStack.t

Returns the DataStack.t for the current declaration

val globals : t -> Symbol.t Ident.Map.t

Return the globals map

val get_used_builtins : t -> PyBuiltin.Set.t

Return a set of Builtin the we spotted in the code

val instructions : t -> T.Instr.t list

Returns the list of all instructions recorded for the current code unit

val label_of_offset : t -> int -> Label.info option

Check if the instruction is a possible jump location, and return the label information found there, if any.

val mk_fresh_ident : t -> Info.t -> t * T.Ident.t

Generate a fresh temporary name

val get_ident_info : t -> T.Ident.t -> Info.t option

Get back the information of a temporary

val mk_fresh_label : t -> t * string

Generate a fresh label name

val map : f:(t -> 'a -> t * 'b) -> env:t -> 'a list -> t * 'b list

Similar to List.map but an env is threaded along the way

val map_result : f:(t -> 'a -> (t * 'b, 'c) IStdlib.IStd.result) -> env:t -> 'a list -> (t * 'b list, 'c) IStdlib.IStd.result

Similar to map but supports functions that return Result.t

val enter_proc : is_toplevel:bool -> is_static:bool -> module_name:Ident.t -> params:string list -> t -> t

Set the environment when entering a new code unit (like reset the instruction buffer, or id/label generators.

val set_annotations : t -> t

Configure the environment to keep track of variable annotations in the dedicated __annotations__ dictionary. Right now, we register its existence but don't store anything in it

val has_annotations : t -> bool

Returns the fact that annotations are tracked or not

val enter_node : t -> t

Set the environment when entering a new node. Reset the instructions buffer.

val reset_stack : t -> t

Reset the stack field of a node

val update_last_line : t -> int option -> t

Update the last_line field of an env, if new information is availbe.

val push : t -> DataStack.cell -> t

Push a new DataStack.cell on the datastack

val pop : t -> (t * DataStack.cell) option

Pop a DataStack.cell from the datastack, if any is available

val peek : t -> DataStack.cell option

Peek a DataStack.cell from the datastack, if any is available

val push_instr : t -> T.Instr.t -> t

Record a new instruction for the current code unit

val register_label : offset:int -> Label.info -> t -> t

Register the fact that a new label info must be inserted before the instruction at offset

val register_with_target : offset:int -> t -> t

Register the location of a with statement clean up code

val is_with_target : offset:int -> t -> bool

Check whether a code offset is the target of a with statement

val process_label : offset:int -> Label.info -> t -> t

Mark the label info at offset as processed

val register_symbol : t -> Symbol.key -> Symbol.t -> t

Register a name (function, variable, ...). It might be a global symbol at the module level or in a local object.

val lookup_symbol : t -> Symbol.key -> Symbol.t option

Lookup information about a global/local symbol previously registered via register_symbol

val register_call : t -> Ident.t -> t

Register a function call. It enables us to deal correctly with builtin declaration.

val mk_builtin_call : t -> PyBuiltin.textual -> T.Exp.t list -> t * T.Ident.t * T.Typ.t

Wrapper to compute the Textual version of a call to a "textual" builtin * function (a builtin we introduced for modeling purpose)

val register_function : t -> string -> T.Location.t -> PyCommon.signature -> T.Exp.t list -> t

Register a function declaration. We keep track of them since they might shadow Python builtins or previous definitions

val register_method : t -> enclosing_class:Ident.t -> method_name:string -> Signature.t -> T.Exp.t list -> t

Register a method declaration. We mostly keep track of their signatures

val register_fields : t -> T.TypeName.t -> PyCommon.signature -> t

Extended the set of fields of class class_name with class_fields. We might have multiple calls to this function with the same class name in a best effort attempt: Python is dynamic, and any self.foo access could give rise to such a registration

val lookup_method : t -> enclosing_class:Ident.t -> string -> method_info option

Lookup the information stored for a function/method in the relevant enclosing_class

val lookup_fields : t -> T.TypeName.t -> PyCommon.signature option

Lookup the signature of a function / method

val register_class : t -> string -> Ident.t -> Ident.t list -> t

Register a class declaration (based on LOAD_BUILD_CLASS)

val get_declared_classes : t -> class_info PythonFrontend.PyCommon.SMap.t

Return information of classes defined in the current module

val register_imported_value : t -> Ident.t -> t

register global names imported from other modules

val get_textual_imports : t -> T.Module.decl list

Get back the list of registered imports

val is_toplevel : t -> bool

Are we processing top level instructions, or something in a function/class ?

val is_static : t -> bool

Are we processing instructions from a static method ?

val get_params : t -> string list

Return the name of the method/function parameters, if any

val module_name : t -> Ident.t

Returns the name of the current module