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.Abs(arg: Expr, loc: Location | None)

Bases: UnaryOp

FPy node: absolute value

class fpy2.ast.fpyast.Acos(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: inverse cosine

class fpy2.ast.fpyast.Acosh(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: inverse hyperbolic cosine

class fpy2.ast.fpyast.Add(first: Expr, second: Expr, loc: Location | None)

Bases: BinaryOp

FPy node: addition

class fpy2.ast.fpyast.And(args: Iterable[Expr], loc: Location | None)

Bases: NaryOp

FPy node: logical conjunction

class fpy2.ast.fpyast.AnyTypeAnn(loc: Location | None)

Bases: TypeAnn

FPy 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: Ast

FPy AST: function argument

class fpy2.ast.fpyast.Asin(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: inverse sine

class fpy2.ast.fpyast.Asinh(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: inverse hyperbolic sine

class fpy2.ast.fpyast.AssertStmt(test: Expr, msg: Expr | None, loc: Location | None)

Bases: Stmt

FPy 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: Stmt

FPy 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: ABC

FPy 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: NamedUnaryOp

FPy node: inverse tangent

class fpy2.ast.fpyast.Atan2(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: NamedBinaryOp

FPy node: atan(y / x) with correct quadrant

class fpy2.ast.fpyast.Atanh(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: inverse hyperbolic tangent

class fpy2.ast.fpyast.Attribute(value: Expr, attr: str, loc: Location | None)

Bases: Expr

FPy 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: object

Abstract base class for AST formatters.

class fpy2.ast.fpyast.BinaryOp(first: Expr, second: Expr, loc: Location | None)

Bases: NaryExpr

FPy 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: TypeAnn

FPy 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: ValueExpr

FPy 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: NaryExpr

FPy 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: NamedUnaryOp

FPy 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: NamedUnaryOp

FPy node: cube-root

class fpy2.ast.fpyast.Ceil(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: ceiling

class fpy2.ast.fpyast.Compare(ops: Iterable[CompareOp], args: Iterable[Expr], loc: Location | None)

Bases: Expr

FPy 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: Enum

Comparison 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: NullaryOp

FPy node: 1/π (constant)

class fpy2.ast.fpyast.Const2_Pi(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: 2/π (constant)

class fpy2.ast.fpyast.Const2_SqrtPi(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: 2/√π (constant)

class fpy2.ast.fpyast.ConstE(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: e (constant)

class fpy2.ast.fpyast.ConstInf(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: infinity (constant)

class fpy2.ast.fpyast.ConstLn2(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: ln(2) (constant)

class fpy2.ast.fpyast.ConstLog10E(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: log₁₀(e) (constant)

class fpy2.ast.fpyast.ConstLog2E(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: log₂(e) (constant)

class fpy2.ast.fpyast.ConstNan(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: NaN (constant)

class fpy2.ast.fpyast.ConstPi(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: π (constant)

class fpy2.ast.fpyast.ConstPi_2(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: π/2 (constant)

class fpy2.ast.fpyast.ConstPi_4(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: π/4 (constant)

class fpy2.ast.fpyast.ConstSqrt1_2(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: √(1/2) (constant)

class fpy2.ast.fpyast.ConstSqrt2(func: Var | Attribute, loc: Location | None)

Bases: NullaryOp

FPy node: √2 (constant)

class fpy2.ast.fpyast.ContextStmt(target: Id, ctx: Expr, body: StmtBlock, loc: Location | None)

Bases: Stmt

FPy 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: TypeAnn

FPy 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: NamedBinaryOp

FPy node: copysign

class fpy2.ast.fpyast.Cos(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: cosine

class fpy2.ast.fpyast.Cosh(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: hyperbolic cosine

class fpy2.ast.fpyast.DeclContext(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: extracts the rounding context of a number.

class fpy2.ast.fpyast.Decnum(val: str, loc: Location | None)

Bases: RationalVal

FPy 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: RationalVal

FPy 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: NamedUnaryOp

FPy node: dimension operator

class fpy2.ast.fpyast.Div(first: Expr, second: Expr, loc: Location | None)

Bases: BinaryOp

FPy node: subtraction

class fpy2.ast.fpyast.EffectStmt(expr: Expr, loc: Location | None)

Bases: Stmt

FPy 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: NamedNaryOp

FPy node: empty operator

class fpy2.ast.fpyast.Enumerate(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: enumerate operator

class fpy2.ast.fpyast.Erf(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: error function

class fpy2.ast.fpyast.Erfc(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: complementary error function

class fpy2.ast.fpyast.Exp(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: exponential (base e)

class fpy2.ast.fpyast.Exp2(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: exponential (base 2)

class fpy2.ast.fpyast.Expm1(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: exp(x) - 1

class fpy2.ast.fpyast.Expr(loc: Location | None)

Bases: Ast

FPy 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: NamedBinaryOp

FPy node: max(x - y, 0)

class fpy2.ast.fpyast.Floor(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: floor

class fpy2.ast.fpyast.Fma(func: Var | Attribute, first: Expr, second: Expr, third: Expr, loc: Location | None)

Bases: NamedTernaryOp

FPy node: fused-multiply add

class fpy2.ast.fpyast.Fmod(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: NamedBinaryOp

FPy 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: Stmt

FPy 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: ValueExpr

FPy 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: Ast

FPy 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: object

Function definition metadata

ctx: Context | FPCoreContext | None

overriding global context (if any)

env: ForeignEnv

foreign environment associated with the function

free_vars: set[NamedId]

free variables used in the function body

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: RationalVal

FPy 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: NamedBinaryOp

FPy node: sqrt(x ** 2 + y ** 2)

class fpy2.ast.fpyast.Id

Bases: ABC

Abstract 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.

abstractmethod names() set[NamedId]

Return a set of all named identifiers contained in this identifier.

This method is for compability with AST classes.

class fpy2.ast.fpyast.If1Stmt(cond: Expr, body: StmtBlock, loc: Location | None)

Bases: Stmt

FPy 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: Expr

FPy 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: Stmt

FPy 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: Stmt

FPy 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: RationalVal

FPy 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: NamedUnaryOp

FPy node: is the value finite?

class fpy2.ast.fpyast.IsInf(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: is the value infinite?

class fpy2.ast.fpyast.IsNan(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: is the value NaN?

class fpy2.ast.fpyast.IsNormal(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: is the value normal?

class fpy2.ast.fpyast.Len(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: length operator

class fpy2.ast.fpyast.Lgamma(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy 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: Expr

FPy 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: Expr

FPy 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: Expr

FPy 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: Expr

FPy 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: TypeAnn

FPy 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: object

Parse location: line and column number.

class fpy2.ast.fpyast.Log(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: logarithm (base e)

class fpy2.ast.fpyast.Log10(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: logarithm (base 10)

class fpy2.ast.fpyast.Log1p(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: log(x + 1)

class fpy2.ast.fpyast.Log2(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: logarithm (base 2)

class fpy2.ast.fpyast.Logb(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: extracts the (normalized) exponent of a number.

class fpy2.ast.fpyast.Max(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)

Bases: NamedNaryOp

FPy node: max(x, y, …)

class fpy2.ast.fpyast.Min(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)

Bases: NamedNaryOp

FPy node: min(x, y, …)

class fpy2.ast.fpyast.Mod(first: Expr, second: Expr, loc: Location | None)

Bases: BinaryOp

FPy 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: BinaryOp

FPy node: subtraction

class fpy2.ast.fpyast.NamedBinaryOp(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: BinaryOp

FPy AST: binary operation with a named function

class fpy2.ast.fpyast.NamedId(base: str, count: int | None = None)

Bases: Id

Named identifier.

A named identifier consists of a base name and an optional count to indicate its version.

names() set[NamedId]

Return a set of all named identifiers contained in this identifier.

This method is for compability with AST classes.

class fpy2.ast.fpyast.NamedNaryOp(func: Var | Attribute, args: Iterable[Expr], loc: Location | None)

Bases: NaryOp

FPy 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: TernaryOp

FPy AST: ternary operation with a named function

class fpy2.ast.fpyast.NamedUnaryOp(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: UnaryOp

FPy AST: unary operation with a named function

class fpy2.ast.fpyast.NaryExpr(loc: Location | None)

Bases: Expr

FPy AST: expression with N arguments

class fpy2.ast.fpyast.NaryOp(args: Iterable[Expr], loc: Location | None)

Bases: NaryExpr

FPy 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: NamedUnaryOp

FPy node: nearest integer

class fpy2.ast.fpyast.Neg(arg: Expr, loc: Location | None)

Bases: UnaryOp

FPy node: negation

class fpy2.ast.fpyast.Not(arg: Expr, loc: Location | None)

Bases: UnaryOp

FPy node: logical negation

class fpy2.ast.fpyast.NullaryOp(func: Var | Attribute, loc: Location | None)

Bases: NaryExpr

FPy 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: NaryOp

FPy node: logical disjunction

class fpy2.ast.fpyast.PassStmt(loc: Location | None)

Bases: Stmt

FPy 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: NamedBinaryOp

FPy node: x ** y

class fpy2.ast.fpyast.Range1(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: range(stop)

class fpy2.ast.fpyast.Range2(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: NamedBinaryOp

FPy node: range(start, stop)

class fpy2.ast.fpyast.Range3(func: Var | Attribute, first: Expr, second: Expr, third: Expr, loc: Location | None)

Bases: NamedTernaryOp

FPy node: range(start, stop, step)

class fpy2.ast.fpyast.Rational(func: Var | Attribute, p: int, q: int, loc: Location | None)

Bases: RationalVal

FPy 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: RealVal

FPy 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: TypeAnn

FPy 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.RealVal(loc: Location | None)

Bases: ValueExpr

FPy AST: real value

class fpy2.ast.fpyast.Remainder(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: NamedBinaryOp

FPy 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: Stmt

FPy 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: NamedUnaryOp

FPy node: inter-format rounding

class fpy2.ast.fpyast.RoundAt(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: NamedBinaryOp

FPy node: inter-format rounding with absolute position

class fpy2.ast.fpyast.RoundInt(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: round

class fpy2.ast.fpyast.Signbit(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: is the signbit 1?

class fpy2.ast.fpyast.Sin(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: sine

class fpy2.ast.fpyast.Sinh(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: hyperbolic sine

class fpy2.ast.fpyast.Size(func: Var | Attribute, first: Expr, second: Expr, loc: Location | None)

Bases: NamedBinaryOp

FPy node: size operator

class fpy2.ast.fpyast.SizedTensorTypeAnn(dims: list[int | NamedId], elt: TypeAnn, loc: Location | None)

Bases: TypeAnn

FPy 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: NamedId

Named identifier from the original source.

A source identifier should only be generated by the parser.

loc: Location

source location

class fpy2.ast.fpyast.Sqrt(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: square-root

class fpy2.ast.fpyast.Stmt(loc: Location | None)

Bases: Ast

FPy 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.StmtBlock(stmts: list[Stmt])

Bases: Ast

FPy AST: list of statements

class fpy2.ast.fpyast.Sub(first: Expr, second: Expr, loc: Location | None)

Bases: BinaryOp

FPy node: subtraction

class fpy2.ast.fpyast.Sum(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: summation

class fpy2.ast.fpyast.Tan(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: tangent

class fpy2.ast.fpyast.Tanh(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: hyperbolic tangent

class fpy2.ast.fpyast.TernaryOp(first: Expr, second: Expr, third: Expr, loc: Location | None)

Bases: NaryExpr

FPy 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: NamedUnaryOp

FPy node: gamma function

class fpy2.ast.fpyast.Trunc(func: Var | Attribute, arg: Expr, loc: Location | None)

Bases: NamedUnaryOp

FPy node: truncation

class fpy2.ast.fpyast.TupleBinding(elts: Iterable[Id | Self], loc: Location | None)

Bases: Ast

FPy AST: tuple binding

class fpy2.ast.fpyast.TupleExpr(elts: Iterable[Expr], loc: Location | None)

Bases: Expr

FPy 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: TypeAnn

FPy 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: Ast

FPy 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: NaryExpr

FPy 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: Id

Placeholder identifier.

When used in an assignment, the value is not bound. This identifier is illegal as a variable.

names() set[NamedId]

Return a set of all named identifiers contained in this identifier.

This method is for compability with AST classes.

class fpy2.ast.fpyast.ValueExpr(loc: Location | None)

Bases: Expr

FPy Ast: terminal expression

class fpy2.ast.fpyast.Var(name: NamedId, loc: Location | None)

Bases: Expr

FPy 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: Stmt

FPy 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: NamedNaryOp

FPy 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: Visitor

Default visitor: visits all nodes without doing anything.

class fpy2.ast.DefaultTransformVisitor

Bases: Visitor

Default 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

format(ast: Ast) str

Pretty print the given AST

Analyses

class fpy2.analysis.ArraySizeInfer

Bases: object

Array 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: object

Call graph analysis.

Builds the DAG of functions transitively called from a root FuncDef. Raises CallGraphError on recursion.

static analyze(func: FuncDef) CallGraphAnalysis

Build the call graph rooted at func.

class fpy2.analysis.ContextUse

Bases: object

Context-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:

  • with statements (ContextStmt), and

  • the function-level context annotation in FuncDef.

The analysis attempts partial evaluation to resolve context expressions to concrete Context values. 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.

static analyze(func: FuncDef, *, def_use: DefineUseAnalysis | None = None) ContextUseAnalysis

Runs context-use analysis on a function.

Parameters:
  • func – The function to analyze.

  • def_use – Optional pre-computed definition-use analysis. If None, it is computed automatically.

class fpy2.analysis.DefineUse

Bases: object

Definition-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: object

Format 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 (TypeInfer and ContextUse) 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 for loop’s iterable has a statically-known length (per ArraySizeAnalysis), 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: while loops and for loops over symbolic-length iterables iterate body + join until phi bounds stop changing. The AbstractFormat-mediated scalar join introduces infinite ascending chains when exact arithmetic (+/-/* under REAL) is applied to a phi’d value, so the fixpoint runs at most loop_iter_limit iterations before switching joins to widen-mode (distinct scalar Formats fall back to REAL_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_FORMAT to force convergence). Tunable via the loop_iter_limit parameter of analyze().

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 Call whose fn is a known Function and recurses to produce a graph of FormatAnalysis mirroring the call graph (FormatAnalysis.by_call). Structural pre-analyses (def-use, types, context scopes, array sizes) are shared across all sub-analyses via a PreAnalysisCache — each FuncDef is structurally analyzed at most once for the lifetime of a top-level call to analyze(). FormatInfer itself 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 CallGraph acyclicity check runs at this entry and raises CallGraphError if a cycle is reachable.

Parameters:
  • func – The FuncDef AST 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 for loops 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 (+/-/* under REAL) which has infinite ascending chains.

  • pre_cache – Optional PreAnalysisCache shared with sub-analyses. Useful when a caller wants to amortize structural analysis across multiple independent analyze() invocations on a shared corpus. When None, 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_fmt slot is treated as expected and overwritten in the result. None falls back to the legacy behaviour: symbolic outer scopes degrade to REAL_FORMAT and 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 (while loops, and for loops over symbolic-size iterables).

Returns:

A FormatAnalysis whose by_def, by_expr, and by_call describe 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: object

Live variable analysis for the FPy AST.

static analyze(ast: FuncDef | Expr)

Analyze the live variables in a function.

class fpy2.analysis.PartialEval

Bases: object

Partial evaluation.

This analysis evaluates parts of the program that can be determined statically, allowing for potential optimizations and simplifications before runtime.

static apply(func: FuncDef, *, def_use: DefineUseAnalysis | None = None)

Applies partial evaluation.

class fpy2.analysis.Purity

Bases: object

Pure function analysis.

A function is considered pure if it has no side effects.

static analyze(func: FuncDef, def_use: DefineUseAnalysis | None = None) bool

Analyze the given function and return True if it is pure, False otherwise.

static analyze_expr(expr: Expr, def_use: DefineUseAnalysis) bool

Analyze the given expression and return True if it is pure, False otherwise.

class fpy2.analysis.Reachability

Bases: object

This 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

static analyze(func: FuncDef, *, check_all_reachable: bool = False, check_no_fallthrough: bool = False, check_single_exit: bool = False)

Run the analysis. Each check_* flag opts into one of the three optional assertions documented on the class.

class fpy2.analysis.ReachingDefs

Bases: object

Reaching 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: object

Syntax 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)

static check(func: FuncDef, *, free_vars: set[NamedId] | None = None, ignore_unknown: bool = True, allow_wildcard: bool = False)

Analyzes the function for syntax errors.

Returns the subset of free_vars that are relevant to FPy.

class fpy2.analysis.TypeInfer

Bases: object

Type 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: object

Constant 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: object

Constant propagation.

For any occurence of the form x = c where c is a constant, this transform replaces all uses of x with c.

static apply(func: FuncDef, *, names: set[NamedId] | None = None) FuncDef

Applies constant propagation.

If names is provided, only propagate variables in this set.

class fpy2.transform.CopyPropagate

Bases: object

Copy propagation.

This transform replaces any variable that is assigned another variable.

static apply(func: FuncDef, *, names: set[NamedId] | None = None) FuncDef

Applies copy propagation to the given AST.

class fpy2.transform.DeadCodeEliminate

Bases: object

Dead code elimination. - removes any unused statements - removes any unused free variables - removes any never-executed branch - removes empty bodies

class fpy2.transform.ForBundling

Bases: object

Transformation 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: object

Transformation 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.

static apply(func: FuncDef) FuncDef

Apply the transformation to the given function definition.

class fpy2.transform.ForUnroll

Bases: object

Unrolling 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: object

Function 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: object

Transformation 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: object

Transformation pass to lift context expressions to the top-level.

class fpy2.transform.Monomorphize

Bases: object

Monomorphize pass.

This pass overrides type or context variables with more specific types.

class fpy2.transform.RenameTarget

Bases: object

Renames targets, that is, left-hand side of assignments, in an FPy program.

static apply(func: FuncDef, rename: dict[NamedId, NamedId])

Renames targets in the function.

static apply_block(block: StmtBlock, rename: dict[NamedId, NamedId])

Renames targets in a block.

class fpy2.transform.RoundElim

Bases: object

Rewrite expressions whose implicit rounding to the active context is provably an identity. Arithmetic ops (Add/Sub/Mul/Abs/Neg) hoist into with fp.REAL: preambles; explicit Round / Cast nodes collapse to their argument.

See the module docstring for the rewrite shape, the greedy-outermost policy, and the soundness invariants.

static apply(func: FuncDef) FuncDef

Apply the transformation to a FuncDef. Returns a new FuncDef; the input is not mutated.

Runs DefineUse, ContextUse, and FormatInfer internally — these are pre-analyses the rewrite needs to decide eliminability per expression.

class fpy2.transform.SimplifyIf

Bases: object

Control 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: object

Split loop transformation.

This transformation rewrites a single for loop:

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: object

Replaces occurence of variables with expressions.

This transformation is the basis for: - copy propagation - constant propagation

static apply(func: FuncDef, def_use: DefineUseAnalysis, subst: Mapping[AssignDef, Expr])

Given a substitution from variable definitions to expressions, replaces all occurences of the variables with the corresponding expressions. The original definition will not be renamed.

class fpy2.transform.WhileBundling

Bases: object

Transformation 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: object

Unrolling for while loops.

static apply(func: FuncDef, where: int | None = None, times: int = 1)

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.ZipElim

Bases: object

Rewrite zip(...) iterables into indexed loops over the source vectors. See the module docstring for the patterns recognized and the ordering constraint with fpy2.transform.ForUnpack.

static apply(func: FuncDef) FuncDef

Apply the transformation to a FuncDef. Returns a new FuncDef; the input is not mutated.