Type System
FPy is not statically typed. A program runs (see Language Semantics) without any type-checking, and every value carries its rounding context at run time. Static types enter only when compiling a program to a strongly-typed target, such as C++: the compiler infers a static type for each expression, and a program must type-check to be compiled — even though an ill-typed program may still run under the dynamic semantics.
This page gives the typing rules for the same core fragment as
Language Semantics. The types here are context-free: a real number has type
\(\texttt{real}\), with no rounding context attached. To emit code for a
typed target, a separate pass refines each \(\texttt{real}\) with the
rounding context it is produced under (so the backend can pick a concrete
machine type — float, double, a fixed-point format, and so on). That
refinement is out of scope here.
Types
The scalar types mirror the three scalar value kinds — booleans, real numbers, and rounding contexts — and are joined by list, tuple, and function types.
The real rounding context \(\R\) has type \(\texttt{context}\). Function symbols are assigned a function type \(T_1 \rightarrow T_2\).
Typing
Typing is the judgement \(\Gamma \vdash e : T\), read “under typing context \(\Gamma\), expression \(e\) has type \(T\)”. \(\Gamma\) assigns each variable a single type and is the solution of whole-function type inference — computed by unification, so library functions may be polymorphic. The rules below present the monomorphic case and state when a program agrees with that solution; statement well-formedness is written \(\Gamma \vdash s\ \texttt{ok}\). Because \(\Gamma\) is fixed, typing checks a program against it rather than building it up statement by statement.
Expressions
Constants have their scalar types; a variable has the type \(\Gamma\) assigns it.
A list is homogeneous; indexing recovers the element type. A tuple’s type records each component.
As in Language Semantics, + and < are representatives: arithmetic maps
reals to a real, and comparison maps reals to a boolean.
Statements
An assignment checks that its right-hand side’s type agrees with the pattern on the left. Because \(\Gamma\) is fixed — every variable already has its inferred type — a pattern needs no rules of its own: it is typed by the expression rules, a variable by T-Var and a tuple pattern \(x_1, \ldots, x_n\) like the tuple \((\, x_1, \ldots, x_n \,)\) by T-Tuple.
The \(\texttt{ret}\) operand may have any type; all returns in a function share one type, which becomes the function’s result type. An assertion tests a boolean.
Sequencing and conditionals require their parts to be well-typed; a conditional also requires a boolean guard.
The context statement requires a context-typed expression — evaluating it yields the active rounding context for the body — and binds the target to that context.