PythonFrontend.PyEnv
module T = Textuallib.Textual
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.
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
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, ...
Method level info. We store a method/function signature, and its default arugments
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 get_used_builtins : t -> PyBuiltin.Set.t
Return a set of Builtin
the we spotted in the code
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.
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.
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
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 register_label : offset:int -> Label.info -> t -> t
Register the fact that a new label info
must be inserted before the instruction at offset
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
Register a function call. It enables us to deal correctly with builtin declaration.
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
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 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