PythonFrontend.PyEnvmodule T = Textuallib.Textualmodule Ident = PyCommon.Identmodule Info : sig ... endType information about various entities (toplevel declarations, temporaries, ...).
module Symbol : sig ... endmodule Signature : sig ... endmodule DataStack : sig ... endIn 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 ... endClass 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.tReturn the last recorded line information from the Python code-unit, if any.
val stack : t -> DataStack.tReturns the DataStack.t for the current declaration
val get_used_builtins : t -> PyBuiltin.Set.tReturn 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 optionCheck 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.resultSimilar 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 ->
tSet 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 -> boolReturns 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 -> tPush a new DataStack.cell on the datastack
val pop : t -> (t * DataStack.cell) optionPop a DataStack.cell from the datastack, if any is available
val peek : t -> DataStack.cell optionPeek a DataStack.cell from the datastack, if any is available
val register_label : offset:int -> Label.info -> t -> tRegister 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 -> boolCheck whether a code offset is the target of a with statement
val process_label : offset:int -> Label.info -> t -> tMark the label info at offset as processed
val register_symbol : t -> Symbol.key -> Symbol.t -> tRegister 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 optionLookup 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 ->
tRegister 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 ->
tRegister a method declaration. We mostly keep track of their signatures
val register_fields : t -> T.TypeName.t -> PyCommon.signature -> tExtended 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 optionLookup the information stored for a function/method in the relevant enclosing_class
val lookup_fields : t -> T.TypeName.t -> PyCommon.signature optionLookup 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.tReturn information of classes defined in the current module
val get_textual_imports : t -> T.Module.decl listGet back the list of registered imports
val is_toplevel : t -> boolAre we processing top level instructions, or something in a function/class ?
val is_static : t -> boolAre we processing instructions from a static method ?
val get_params : t -> string listReturn the name of the method/function parameters, if any