Abstract Syntax Tree (AST)
Abstract Syntax Tree
The Abstract Syntax Tree (AST) is a representation of an FPy program.
This module contains the AST for FPy programs.
- class fpy2.ast.fpyast.Acos(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inverse cosine
- class fpy2.ast.fpyast.Acosh(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inverse hyperbolic cosine
- class fpy2.ast.fpyast.Add(first: Expr, second: Expr, loc: Location | None)
Bases:
BinaryOpFPy node: addition
- class fpy2.ast.fpyast.And(args: Iterable[Expr], loc: Location | None)
Bases:
NaryOpFPy node: logical conjunction
- class fpy2.ast.fpyast.AnyTypeAnn(loc: Location | None)
Bases:
TypeAnnFPy AST: any type annotation
- is_equiv(other)
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Argument(name: Id, type: TypeAnn, loc: Location | None)
Bases:
AstFPy AST: function argument
- class fpy2.ast.fpyast.Asin(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inverse sine
- class fpy2.ast.fpyast.Asinh(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inverse hyperbolic sine
- class fpy2.ast.fpyast.AssertStmt(test: Expr, msg: Expr | None, loc: Location | None)
Bases:
StmtFPy AST: assert statement
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Assign(target: Id | TupleBinding, type: TypeAnn | None, expr: Expr, loc: Location | None)
Bases:
StmtFPy AST: variable assignment
- is_equiv(other)
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Ast(loc: Location | None)
Bases:
ABCFPy AST: abstract base class for all AST nodes.
- format() str
Format the AST node as a string.
- property loc
Get the location of the AST node.
- class fpy2.ast.fpyast.Atan(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inverse tangent
- class fpy2.ast.fpyast.Atan2(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: atan(y / x) with correct quadrant
- class fpy2.ast.fpyast.Atanh(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inverse hyperbolic tangent
- class fpy2.ast.fpyast.Attribute(value: Expr, attr: str, loc: Location | None)
Bases:
ExprFPy AST: attribute expression x.y
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.BaseFormatter
Bases:
objectAbstract base class for AST formatters.
- class fpy2.ast.fpyast.BinaryOp(first: Expr, second: Expr, loc: Location | None)
Bases:
NaryExprFPy AST: binary operation
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.BoolTypeAnn(loc: Location | None)
Bases:
TypeAnnFPy AST: boolean type annotation
- is_equiv(other)
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.BoolVal(val: bool, loc: Location | None)
Bases:
ValueExprFPy AST: boolean value
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Call(func: Var | Attribute, fn: object, args: Iterable[Expr], kwargs: Iterable[tuple[str, Expr]], loc: Location | None)
Bases:
NaryExprFPy AST: function call
- is_equiv(other)
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Cast(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: round to the current context, asserting the result is exact
- class fpy2.ast.fpyast.Cbrt(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: cube-root
- class fpy2.ast.fpyast.Ceil(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: ceiling
- class fpy2.ast.fpyast.Compare(ops: Iterable[CompareOp], args: Iterable[Expr], loc: Location | None)
Bases:
ExprFPy AST: comparison chain
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.CompareOp(*values)
Bases:
EnumComparison operators as an enumeration
- invert()
Assuming a op b, returns op such that b op a.
- symbol()
Get the symbol for the operator.
- class fpy2.ast.fpyast.Const1_Pi(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: 1/π (constant)
- class fpy2.ast.fpyast.Const2_Pi(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: 2/π (constant)
- class fpy2.ast.fpyast.Const2_SqrtPi(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: 2/√π (constant)
- class fpy2.ast.fpyast.ConstE(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: e (constant)
- class fpy2.ast.fpyast.ConstInf(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: infinity (constant)
- class fpy2.ast.fpyast.ConstLn2(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: ln(2) (constant)
- class fpy2.ast.fpyast.ConstLog10E(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: log₁₀(e) (constant)
- class fpy2.ast.fpyast.ConstLog2E(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: log₂(e) (constant)
- class fpy2.ast.fpyast.ConstNan(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: NaN (constant)
- class fpy2.ast.fpyast.ConstPi(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: π (constant)
- class fpy2.ast.fpyast.ConstPi_2(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: π/2 (constant)
- class fpy2.ast.fpyast.ConstPi_4(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: π/4 (constant)
- class fpy2.ast.fpyast.ConstSqrt1_2(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: √(1/2) (constant)
- class fpy2.ast.fpyast.ConstSqrt2(func: Var | Attribute, loc: Location | None)
Bases:
NullaryOpFPy node: √2 (constant)
- class fpy2.ast.fpyast.ContextStmt(target: Id, ctx: Expr, body: StmtBlock, loc: Location | None)
Bases:
StmtFPy AST: with statement
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.ContextTypeAnn(loc: Location | None)
Bases:
TypeAnnFPy AST: context type annotation
- is_equiv(other)
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Copysign(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: copysign
- class fpy2.ast.fpyast.Cos(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: cosine
- class fpy2.ast.fpyast.Cosh(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: hyperbolic cosine
- class fpy2.ast.fpyast.DeclContext(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: extracts the rounding context of a number.
- class fpy2.ast.fpyast.Decnum(val: str, loc: Location | None)
Bases:
RationalValFPy AST: decimal number
- as_rational() Fraction
Returns the represented rational value as a Fraction in simplest form.
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Digits(func: Var | Attribute, m: int, e: int, b: int, loc: Location | None)
Bases:
RationalValFPy AST: scientific notation
- as_rational() Fraction
Returns the represented rational value as a Fraction in simplest form.
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Dim(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: dimension operator
- class fpy2.ast.fpyast.Div(first: Expr, second: Expr, loc: Location | None)
Bases:
BinaryOpFPy node: subtraction
- class fpy2.ast.fpyast.EffectStmt(expr: Expr, loc: Location | None)
Bases:
StmtFPy AST: an expression without a result
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Empty(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)
Bases:
NamedNaryOpFPy node: empty operator
- class fpy2.ast.fpyast.Enumerate(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: enumerate operator
- class fpy2.ast.fpyast.Erf(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: error function
- class fpy2.ast.fpyast.Erfc(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: complementary error function
- class fpy2.ast.fpyast.Exp(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: exponential (base e)
- class fpy2.ast.fpyast.Exp2(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: exponential (base 2)
- class fpy2.ast.fpyast.Expm1(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: exp(x) - 1
- class fpy2.ast.fpyast.Expr(loc: Location | None)
Bases:
AstFPy AST: expression
- abstractmethod is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Fdim(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: max(x - y, 0)
- class fpy2.ast.fpyast.Floor(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: floor
- class fpy2.ast.fpyast.Fma(func: Var | Attribute, first: Expr, second: Expr, third: Expr, loc: Location | None)
Bases:
NamedTernaryOpFPy node: fused-multiply add
- class fpy2.ast.fpyast.Fmod(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: fmod(x, y)
Represents the C standard library’s fmod function, defined as:
fmod(x, y) = x - trunc(x / y) * y
The result has the same sign as the dividend x.
- class fpy2.ast.fpyast.ForStmt(target: Id | TupleBinding, iterable: Expr, body: StmtBlock, loc: Location | None)
Bases:
StmtFPy AST: for statement
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.ForeignVal(val: Any, loc: Location | None)
Bases:
ValueExprFPy AST: native Python value
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.FuncDef(name: str, args: Iterable[Argument], body: StmtBlock, meta: FuncMeta, *, loc: Location | None = None)
Bases:
AstFPy AST: function definition
- class fpy2.ast.fpyast.FuncMeta(free_vars: set[NamedId], ctx: Context | FPCoreContext | None, spec: Any, props: dict[str, Any], env: ForeignEnv)
Bases:
objectFunction definition metadata
- ctx: Context | FPCoreContext | None
overriding global context (if any)
- env: ForeignEnv
foreign environment associated with the function
- props: dict[str, Any]
additional properties (if any)
- spec: Any
function specification (if any)
- fpy2.ast.fpyast.FuncSymbol: TypeAlias = fpy2.ast.fpyast.Var | fpy2.ast.fpyast.Attribute
FPy function symbols have the recursive form
- symbol ::= Var ( symbol )
- Attribute ( symbol, _ )
This type alias only shallowly checks the type
- class fpy2.ast.fpyast.Hexnum(func: Var | Attribute, val: str, loc: Location | None)
Bases:
RationalValFPy AST: hexadecimal number
- as_rational() Fraction
Returns the represented rational value as a Fraction in simplest form.
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Hypot(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: sqrt(x ** 2 + y ** 2)
- class fpy2.ast.fpyast.Id
Bases:
ABCAbstract base class for identifiers.
- is_equiv(other) bool
Check if this identifier is equivalent to another identifier.
This method is for compability with AST classes.
- class fpy2.ast.fpyast.If1Stmt(cond: Expr, body: StmtBlock, loc: Location | None)
Bases:
StmtFPy AST: if statement with one branch
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.IfExpr(cond: Expr, ift: Expr, iff: Expr, loc: Location | None)
Bases:
ExprFPy AST: if expression
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.IfStmt(cond: Expr, ift: StmtBlock, iff: StmtBlock, loc: Location | None)
Bases:
StmtFPy AST: if statement (with two branches)
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.IndexedAssign(var: NamedId, indices: Iterable[Expr], expr: Expr, loc: Location | None)
Bases:
StmtFPy AST: assignment to tuple indexing
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Integer(val: int, loc: Location | None)
Bases:
RationalValFPy AST: integer
- as_rational() Fraction
Returns the represented rational value as a Fraction in simplest form.
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.IsFinite(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: is the value finite?
- class fpy2.ast.fpyast.IsInf(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: is the value infinite?
- class fpy2.ast.fpyast.IsNan(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: is the value NaN?
- class fpy2.ast.fpyast.IsNormal(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: is the value normal?
- class fpy2.ast.fpyast.Len(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: length operator
- class fpy2.ast.fpyast.Lgamma(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: logarithm of the absolute value of the gamma function
- class fpy2.ast.fpyast.ListComp(targets: Collection[Id | TupleBinding], iterables: Collection[Expr], elt: Expr, loc: Location | None)
Bases:
ExprFPy AST: list comprehension expression
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.ListExpr(elts: Iterable[Expr], loc: Location | None)
Bases:
ExprFPy AST: list expression
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.ListRef(value: Expr, index: Expr, loc: Location | None)
Bases:
ExprFPy AST: list indexing expression
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.ListSlice(value: Expr, start: Expr | None, stop: Expr | None, loc: Location | None)
Bases:
ExprFPy AST: list slicing expression
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.ListTypeAnn(elt: TypeAnn, loc: Location | None)
Bases:
TypeAnnFPy AST: native list type annotation
- is_equiv(other) bool
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Location(source: str, start_line: int, start_column: int, end_line: int, end_column: int)
Bases:
objectParse location: line and column number.
- class fpy2.ast.fpyast.Log(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: logarithm (base e)
- class fpy2.ast.fpyast.Log10(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: logarithm (base 10)
- class fpy2.ast.fpyast.Log1p(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: log(x + 1)
- class fpy2.ast.fpyast.Log2(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: logarithm (base 2)
- class fpy2.ast.fpyast.Logb(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: extracts the (normalized) exponent of a number.
- class fpy2.ast.fpyast.Max(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)
Bases:
NamedNaryOpFPy node: max(x, y, …)
- class fpy2.ast.fpyast.Min(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)
Bases:
NamedNaryOpFPy node: min(x, y, …)
- class fpy2.ast.fpyast.Mod(first: Expr, second: Expr, loc: Location | None)
Bases:
BinaryOpFPy node: a % b
Represents Python’s modulus operator, defined as:
a = (a // b) * b + (a % b)
The result has the same sign as the divisor b.
- class fpy2.ast.fpyast.Mul(first: Expr, second: Expr, loc: Location | None)
Bases:
BinaryOpFPy node: subtraction
- class fpy2.ast.fpyast.NamedBinaryOp(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
BinaryOpFPy AST: binary operation with a named function
- class fpy2.ast.fpyast.NamedId(base: str, count: int | None = None)
Bases:
IdNamed identifier.
A named identifier consists of a base name and an optional count to indicate its version.
- class fpy2.ast.fpyast.NamedNaryOp(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)
Bases:
NaryOpFPy AST: n-ary operation with a named function
- class fpy2.ast.fpyast.NamedTernaryOp(func: Var | Attribute, first: Expr, second: Expr, third: Expr, loc: Location | None)
Bases:
TernaryOpFPy AST: ternary operation with a named function
- class fpy2.ast.fpyast.NamedUnaryOp(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
UnaryOpFPy AST: unary operation with a named function
- class fpy2.ast.fpyast.NaryExpr(loc: Location | None)
Bases:
ExprFPy AST: expression with N arguments
- class fpy2.ast.fpyast.NaryOp(args: Iterable[Expr], loc: Location | None)
Bases:
NaryExprFPy AST: n-ary operation
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.NearbyInt(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: nearest integer
- class fpy2.ast.fpyast.Not(arg: Expr, loc: Location | None)
Bases:
UnaryOpFPy node: logical negation
- class fpy2.ast.fpyast.NullaryOp(func: Var | Attribute, loc: Location | None)
Bases:
NaryExprFPy AST: (named) nullary operation
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Or(args: Iterable[Expr], loc: Location | None)
Bases:
NaryOpFPy node: logical disjunction
- class fpy2.ast.fpyast.PassStmt(loc: Location | None)
Bases:
StmtFPy AST: pass (skip) statement
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Pow(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: x ** y
- class fpy2.ast.fpyast.Range1(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: range(stop)
- class fpy2.ast.fpyast.Range2(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: range(start, stop)
- class fpy2.ast.fpyast.Range3(func: Var | Attribute, first: Expr, second: Expr, third: Expr, loc: Location | None)
Bases:
NamedTernaryOpFPy node: range(start, stop, step)
- class fpy2.ast.fpyast.Rational(func: Var | Attribute, p: int, q: int, loc: Location | None)
Bases:
RationalValFPy AST: rational number
- as_rational() Fraction
Returns the represented rational value as a Fraction in simplest form.
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.RationalVal(loc: Location | None)
Bases:
RealValFPy AST: abstract rational value
- abstractmethod as_rational() Fraction
Returns the represented rational value as a Fraction in simplest form.
- is_integer() bool
Returns true if the represented value is an integer.
- class fpy2.ast.fpyast.RealTypeAnn(ctx: Context | None, loc: Location | None)
Bases:
TypeAnnFPy AST: real type annotation
- is_equiv(other)
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Remainder(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: remainder(x, y)
Represents the IEEE 754 remainder function, defined as:
remainder(x, y) = x - round(x / y) * y
The result is the value closest to zero.
- class fpy2.ast.fpyast.ReturnStmt(expr: Expr, loc: Location | None)
Bases:
StmtFPy AST: return statement
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Round(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: inter-format rounding
- class fpy2.ast.fpyast.RoundAt(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: inter-format rounding with absolute position
- class fpy2.ast.fpyast.RoundInt(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: round
- class fpy2.ast.fpyast.Signbit(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: is the signbit 1?
- class fpy2.ast.fpyast.Sin(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: sine
- class fpy2.ast.fpyast.Sinh(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: hyperbolic sine
- class fpy2.ast.fpyast.Size(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)
Bases:
NamedBinaryOpFPy node: size operator
- class fpy2.ast.fpyast.SizedTensorTypeAnn(dims: list[int | NamedId], elt: TypeAnn, loc: Location | None)
Bases:
TypeAnnFPy AST: sized, homogenous tensor type annotation
- is_equiv(other) bool
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.SourceId(base: str, loc: Location, count: int | None = None)
Bases:
NamedIdNamed identifier from the original source.
A source identifier should only be generated by the parser.
- class fpy2.ast.fpyast.Sqrt(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: square-root
- class fpy2.ast.fpyast.Stmt(loc: Location | None)
Bases:
AstFPy AST: statement
- abstractmethod is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Sub(first: Expr, second: Expr, loc: Location | None)
Bases:
BinaryOpFPy node: subtraction
- class fpy2.ast.fpyast.Sum(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: summation
- class fpy2.ast.fpyast.Tan(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: tangent
- class fpy2.ast.fpyast.Tanh(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: hyperbolic tangent
- class fpy2.ast.fpyast.TernaryOp(first: Expr, second: Expr, third: Expr, loc: Location | None)
Bases:
NaryExprFPy AST: ternary operation
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Tgamma(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: gamma function
- class fpy2.ast.fpyast.Trunc(func: Var | Attribute, arg: Expr, loc: Location | None)
Bases:
NamedUnaryOpFPy node: truncation
- class fpy2.ast.fpyast.TupleBinding(elts: Iterable[Id | Self], loc: Location | None)
Bases:
AstFPy AST: tuple binding
- class fpy2.ast.fpyast.TupleExpr(elts: Iterable[Expr], loc: Location | None)
Bases:
ExprFPy AST: tuple expression
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.TupleTypeAnn(elts: list[TypeAnn], loc: Location | None)
Bases:
TypeAnnFPy AST: native tuple type annotation
- is_equiv(other) bool
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.TypeAnn(loc: Location | None)
Bases:
AstFPy AST: typing annotation
- abstractmethod is_equiv(other) bool
Check if this type annotation is equivalent to another type annotation.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.UnaryOp(arg: Expr, loc: Location | None)
Bases:
NaryExprFPy AST: unary operation
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.UnderscoreId
Bases:
IdPlaceholder identifier.
When used in an assignment, the value is not bound. This identifier is illegal as a variable.
- class fpy2.ast.fpyast.Var(name: NamedId, loc: Location | None)
Bases:
ExprFPy AST: variable
- is_equiv(other) bool
Check if this expression is structuarlly equivalent to another expression.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two expressions represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.WhileStmt(cond: Expr, body: StmtBlock, loc: Location | None)
Bases:
StmtFPy AST: while statement
- is_equiv(other) bool
Check if this statement is structurally equivalent to another statement.
This is essentially a recursive equality check. The dunder method __eq__ is used to check if two statements represent exactly the same tree, e.g., id(self) == id(other).
- class fpy2.ast.fpyast.Zip(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)
Bases:
NamedNaryOpFPy node: zip operator
- fpy2.ast.fpyast.get_default_formatter() BaseFormatter
Get the default formatter for FPy AST.
- fpy2.ast.fpyast.set_default_formatter(formatter: BaseFormatter)
Set the default formatter for FPy AST.
Visitors
Visitor base class for FPy AST nodes.
- class fpy2.ast.DefaultVisitor
Bases:
VisitorDefault visitor: visits all nodes without doing anything.
- class fpy2.ast.DefaultTransformVisitor
Bases:
VisitorDefault visitor: visits all nodes without doing anything.
Formatter
The AST can be formatted to a string representation using the fpy2.ast.Formatter class.
Abstract base class for AST formatters.
- class fpy2.ast.Formatter
Bases:
BaseFormatter“Pretty printer for FPy AST
Analyses
- class fpy2.analysis.ArraySizeInfer
Bases:
objectArray size inference.
- static analyze(func: FuncDef, *, partial_eval: PartialEvalInfo | None = None, type_info: TypeAnalysis | None = None) ArraySizeAnalysis
Analyze a function definition to infer array sizes.
- Parameters:
func – Function definition to analyze.
partial_eval – Optional pre-computed partial-evaluation info.
type_info – Optional pre-computed type analysis.
- class fpy2.analysis.CallGraph
Bases:
objectCall graph analysis.
Builds the DAG of functions transitively called from a root
FuncDef. RaisesCallGraphErroron recursion.
- class fpy2.analysis.ContextUse
Bases:
objectContext-use analysis.
This analysis computes, for each rounding context scope in a function, the set of context-sensitive expressions evaluated under it.
Context scopes are introduced by:
withstatements (ContextStmt), andthe function-level context annotation in
FuncDef.
The analysis attempts partial evaluation to resolve context expressions to concrete
Contextvalues. When partial evaluation does not fully reduce a context expression, or when a function is entered without an overriding context, a fresh symbolic context variable (NamedId) is generated.
- class fpy2.analysis.DefineUse
Bases:
objectDefinition-use analysis.
This analysis computes: - the set of definitions available at the entry/exit of each block; - the set of definitions introduced at each statement; - set of all definitions for each variable; - set of all uses for each definition. - the definition referenced by each use.
Each definition has a reference its immediate previous definition(s) which represents a (possibly cyclic) graph of definitions.
- class fpy2.analysis.FormatInfer
Bases:
objectFormat inference for FPy functions.
This analysis bounds the number format for each expression and variable definition in an FPy program. It uses two pre-analyses (
TypeInferandContextUse) and then performs a single forward pass over the AST.Format lattice:
FormatBound ::= None | SetFormat(values) (known finite set of reals) | Format (REAL_FORMAT is the scalar top) | TupleFormat(elts) | ListFormat(elt)
Join rule:
join(None, None) = None join(SetFormat(a), SetFormat(b)) = SetFormat(a ∪ b) join(SetFormat(s), fmt) = fmt if every value in s fits in fmt = REAL_FORMAT otherwise join(f, f) = f join(f1, f2) = (AbstractFormat.from_format(f1) | AbstractFormat.from_format(f2)).format() (when both abstractable) = REAL_FORMAT (otherwise) join(Tuple(a..), Tuple(b..)) = Tuple(join(ai, bi)..) join(List(a), List(b)) = List(join(a, b))This rule is applied at all control-flow merge points (phi nodes), including branch merges (
if/if1) and loop back-edges (while/for).Loops are handled in one of two modes:
Bounded iteration: when a
forloop’s iterable has a statically-known length (perArraySizeAnalysis), the analysis drives the phi update for exactly that many body executions. This mirrors runtime semantics and avoids any widening fall-back — important for the exact-arithmetic lattice, which has infinite ascending chains.Fixpoint + widening:
whileloops andforloops over symbolic-length iterables iterate body + join until phi bounds stop changing. The AbstractFormat-mediated scalar join introduces infinite ascending chains when exact arithmetic (+/-/*underREAL) is applied to a phi’d value, so the fixpoint runs at mostloop_iter_limititerations before switching joins to widen-mode (distinct scalar Formats fall back toREAL_FORMAT) to force convergence.
Usage:
from fpy2.analysis import FormatInfer info = FormatInfer.analyze(func) for d, fmt in info.by_def.items(): print(d.name, '->', fmt)
- DEFAULT_LOOP_ITER_LIMIT = 10
Default number of body+join iterations a loop fixpoint runs before switching to widen-mode (joins of distinct scalar Formats fall back to
REAL_FORMATto force convergence). Tunable via theloop_iter_limitparameter ofanalyze().
- static analyze(func: FuncDef, *, def_use: DefineUseAnalysis | None = None, type_info: TypeAnalysis | None = None, ctx_use: ContextUseAnalysis | None = None, array_size: ArraySizeAnalysis | None = None, pre_cache: PreAnalysisCache | None = None, fn_fmt: FunctionFormat | None = None, loop_iter_limit: int = 10) FormatAnalysis
Performs format analysis on an FPy function.
Walks into every
Callwhosefnis a knownFunctionand recurses to produce a graph ofFormatAnalysismirroring the call graph (FormatAnalysis.by_call). Structural pre-analyses (def-use, types, context scopes, array sizes) are shared across all sub-analyses via aPreAnalysisCache— eachFuncDefis structurally analyzed at most once for the lifetime of a top-level call toanalyze().FormatInferitself re-runs per instantiation so each callee sees the caller’s active rounding context.The call graph must be acyclic; recursion (direct or mutual) is not handled by the per-call-site sub-analysis. A
CallGraphacyclicity check runs at this entry and raisesCallGraphErrorif a cycle is reachable.- Parameters:
func – The
FuncDefAST node to analyse.def_use – Optional pre-computed definition-use analysis.
type_info – Optional pre-computed type analysis.
ctx_use – Optional pre-computed context-use analysis.
array_size – Optional pre-computed array-size analysis. Used to recognise
forloops whose iterable has a statically-known length, so the phi update can be driven exactly that many times instead of iterating to a fixpoint. This is strictly more precise — important for the exact-arithmetic lattice (+/-/*underREAL) which has infinite ascending chains.pre_cache – Optional
PreAnalysisCacheshared with sub-analyses. Useful when a caller wants to amortize structural analysis across multiple independentanalyze()invocations on a shared corpus. WhenNone, a fresh cache is allocated for this call (and its recursive descents).fn_fmt – Format-level signature to instantiate the function at. Supplies the incoming rounding context (used to pin the function’s outermost scope when symbolic) and a per-parameter initial format (used to bypass the declared parameter types — typically derived from the caller’s call-site argument formats). The
ret_fmtslot is treated as expected and overwritten in the result.Nonefalls back to the legacy behaviour: symbolic outer scopes degrade toREAL_FORMATand parameter formats come from the declared types.loop_iter_limit – Number of loop body+join iterations to run before forcing joins of distinct scalar Formats to widen to
REAL_FORMAT. Only applies to loops without a known iteration count (whileloops, andforloops over symbolic-size iterables).
- Returns:
A
FormatAnalysiswhoseby_def,by_expr, andby_calldescribe the formats inferred at every definition site, expression, and reachable sub-call.- Raises:
TypeError – If func is not a
FuncDef.CallGraphError – If the call graph reachable from func contains a cycle (FPy forbids recursion).
- class fpy2.analysis.LiveVars
Bases:
objectLive variable analysis for the FPy AST.
- class fpy2.analysis.PartialEval
Bases:
objectPartial evaluation.
This analysis evaluates parts of the program that can be determined statically, allowing for potential optimizations and simplifications before runtime.
- class fpy2.analysis.Purity
Bases:
objectPure function analysis.
A function is considered pure if it has no side effects.
- class fpy2.analysis.Reachability
Bases:
objectThis class performs a reachability analysis on an FPy program.
It classifies statements each statement as - “possibly reachable”: there exists an execution path from the entry to the statement. - “unreachable”: there is no execution path from the entry to the statement.
The dataflow equation for reachability is:
OUT[s] = |_| IN[s]
The resulting ReachabilityAnalysis has four fields: - has_entry: is the statement reachable? - has_exit: is there a reachable path through the statement? - ret_stmts: all return statements in the program - `has_fallthrough: is there a path that does not end in a return statement
The analysis may optionally assert three properties: - check_all_reachable: every statement in the program is reachable - check_no_fallthrough: every program path ends at a return statement - check_single_exit: the program has only one return statement
- class fpy2.analysis.ReachingDefs
Bases:
objectReaching definitions analysis.
This analysis computes: - the set of definitions available at the entry/exit of each block; - the set of definitions introduced at each statement; - set of all definitions for each variable;
Each definition has a reference its immediate previous definition(s) which represents a (possibly cyclic) graph of definitions.
- class fpy2.analysis.SyntaxCheck
Bases:
objectSyntax checker for the FPy AST.
Basic syntax check to eliminate malformed FPy programs that the parser can’t detect.
Rules enforced:
Variables:
any variables must be defined before it is used;
If statements:
any variable must be defined along both branches when used after the if statement
Function calls:
the function part of a call must be either a variable or an attribute access (e.g., obj.method)
- class fpy2.analysis.TypeInfer
Bases:
objectType inference for the FPy language.
FPy is not statically typed, but compilation may require statically determining the types throughout the program. The FPy type inference algorithm is a Hindley-Milner based algorithm.
- static check(func: FuncDef, def_use: DefineUseAnalysis | None = None) TypeAnalysis
Analyzes the function for type errors.
Produces a type signature for the function if it is well-typed and a mapping from definition to type.
- static infer_primitive(prim: Primitive) FunctionType
Returns the type signature of a primitive.
Transformations
- class fpy2.transform.ConstFold
Bases:
objectConstant folding.
This transform evaluates expressions that can be determined statically: - constants constructors - operations (math, lists, etc.)
- static apply(func: FuncDef, *, def_use: DefineUseAnalysis | None = None, enable_context: bool = True, enable_op: bool = True) FuncDef
Applies constant folding.
Optionally, specify: - enable_context: whether to enable constant folding for context constructors [default: True] - enable_op: whether to enable constant folding for operations [default: True]
- class fpy2.transform.ConstPropagate
Bases:
objectConstant propagation.
For any occurence of the form x = c where c is a constant, this transform replaces all uses of x with c.
- class fpy2.transform.CopyPropagate
Bases:
objectCopy propagation.
This transform replaces any variable that is assigned another variable.
- class fpy2.transform.DeadCodeEliminate
Bases:
objectDead code elimination. - removes any unused statements - removes any unused free variables - removes any never-executed branch - removes empty bodies
- class fpy2.transform.ForBundling
Bases:
objectTransformation pass to bundle updated variables in for loops.
This pass rewrites the IR to bundle updated variables in for loops into a single variable. This transformation ensures there is only one phi node per while loop.
- class fpy2.transform.ForUnpack
Bases:
objectTransformation pass to move any tuple unpacking in a for loop to its body:
for x, y in iterable: ...
becomes:
for t in iterable: x, y = t ...
where t is a fresh variable.
- class fpy2.transform.ForUnroll
Bases:
objectUnrolling for for loops.
- static apply(func: FuncDef, where: int | None = None, times: int = 1, strategy: ForUnrollStrategy = ForUnrollStrategy.STRICT, reaching_defs: ReachingDefsAnalysis | None = None, temp_id: NamedId | None = None, len_id: NamedId | None = None, idx_id: NamedId | None = None)
Apply the transformation.
- Parameters:
where (int | None) – The index of the while loop to unroll. If None, unroll all while loops.
times (int) – The number of times to unroll the loop.
- class fpy2.transform.FuncInline
Bases:
objectFunction inlining.
- static apply(func: FuncDef, *, def_use: DefineUseAnalysis | None = None, funcs: Iterable[FuncDef] | None = None, recursive: bool = True) FuncDef
Applies function inlining to func returning the transformed function.
Raises CallGraphError if the call graph reachable from func contains a cycle (FPy forbids recursion; inlining a recursive call would not terminate).
- class fpy2.transform.IfBundling
Bases:
objectTransformation pass to pack mutated variables in if statements.
This pass rewrites the AST to pack mutated variables in an if statement into a single mutated variable. This ensures a convenient translation into more functional languages.
- class fpy2.transform.LiftContext
Bases:
objectTransformation pass to lift context expressions to the top-level.
- class fpy2.transform.Monomorphize
Bases:
objectMonomorphize pass.
This pass overrides type or context variables with more specific types.
- class fpy2.transform.RenameTarget
Bases:
objectRenames targets, that is, left-hand side of assignments, in an FPy program.
- class fpy2.transform.RoundElim
Bases:
objectRewrite expressions whose implicit rounding to the active context is provably an identity. Arithmetic ops (
Add/Sub/Mul/Abs/Neg) hoist intowith fp.REAL:preambles; explicitRound/Castnodes collapse to their argument.See the module docstring for the rewrite shape, the greedy-outermost policy, and the soundness invariants.
- class fpy2.transform.SimplifyIf
Bases:
objectControl flow simplification:
Transforms if statements into if expressions. The inner block is hoisted into the outer block and each phi variable is made explicit with an if expression.
- class fpy2.transform.SplitLoop
Bases:
objectSplit loop transformation.
This transformation rewrites a single
forloop:for x1, ..., xk in xs: BODY[x1, ..., xk]
into a nested loop:
t1 = xs t2 = factor with Z: n = len(t1) assert n % t2 == 0 for i in range(0, n, t2): with Z: slice = t1[i:i+t2] for x1, ..., xk in slice: BODY[x1, ..., xk]
- class fpy2.transform.SubstVar
Bases:
objectReplaces occurence of variables with expressions.
This transformation is the basis for: - copy propagation - constant propagation
- class fpy2.transform.WhileBundling
Bases:
objectTransformation pass to bundle updated variables in while loops.
This pass rewrites the IR to bundle updated variables in while loops into a single variable. This transformation ensures there is only one phi node per while loop.
- class fpy2.transform.WhileUnroll
Bases:
objectUnrolling for while loops.
- class fpy2.transform.ZipElim
Bases:
objectRewrite
zip(...)iterables into indexed loops over the source vectors. See the module docstring for the patterns recognized and the ordering constraint withfpy2.transform.ForUnpack.