mirror of
https://github.com/nasa/fpp.git
synced 2025-12-11 19:23:13 -06:00
147 lines
5.3 KiB
Plaintext
147 lines
5.3 KiB
Plaintext
== Evaluation
|
|
|
|
*Evaluation* is the process of transforming an <<Expressions,expression>> into
|
|
a <<Values,value>>.
|
|
In FPP, all evaluation happens during
|
|
<<Analysis-and-Translation_Analysis,analysis>>,
|
|
in resolving expressions to compile-time constant values.
|
|
|
|
=== Evaluating Expressions
|
|
|
|
Evaluation of expressions occurs as stated in the
|
|
<<Expressions,expression descriptions>>. Evaluation of integer
|
|
expressions occurs at type <<Types_Internal-Types_Integer,_Integer_>>,
|
|
using enough bits to represent the result without overflow.
|
|
Evaluation of floating-point expressions occurs using 64-bit floating-point
|
|
arithmetic.
|
|
|
|
=== Type Conversion
|
|
|
|
The following rules govern the conversion of a value stem:[v_1] of canonical type
|
|
stem:[T_1]
|
|
to a value stem:[v_2] of canonical type stem:[T_2].
|
|
|
|
==== Unsigned Primitive Integer Values
|
|
|
|
. If stem:[T_1] and stem:[T_2] are both unsigned primitive integer types and
|
|
stem:[T_2] is
|
|
narrower than stem:[T_1], then construct stem:[v_2] by truncating the
|
|
unsigned
|
|
binary representation of stem:[v_1] to the width of stem:[v_2]. For
|
|
example, converting `0x1234: U16` to `U8` yields `0x34: U8`.
|
|
|
|
. Otherwise if stem:[T_1] and stem:[T_2] are both unsigned primitive integer
|
|
types, then
|
|
stem:[v_2] is the integer value of stem:[v_1] at the type of
|
|
stem:[v_2]. For example,
|
|
converting `0x12: U8` to `U16` yields `0x12: U16`.
|
|
|
|
==== Signed Primitive Integer Values
|
|
|
|
. If stem:[T_1] and stem:[T_2] are both signed primitive integer types and
|
|
stem:[T_2] is narrower than stem:[T_1], then construct stem:[v_2] by truncating
|
|
the two's complement binary representation of stem:[v_1] to the width of
|
|
stem:[v_2]. For example, converting `-0x1234: I16` to `I8` yields `-0x34:
|
|
I8`.
|
|
|
|
. Otherwise if stem:[T_1] and stem:[T_2] are both signed primitive integer
|
|
types, then stem:[v_2]
|
|
is the integer value of stem:[v_1] at the type of stem:[v_2]. For
|
|
example, converting `-0x12: I8` to `I16` yields `-0x12: I16`.
|
|
|
|
==== Primitive Integer Values of Mixed Sign
|
|
|
|
If stem:[T_1] and stem:[T_2] are primitive integer types with one signed and
|
|
one unsigned,
|
|
then do the following:
|
|
|
|
. Construct the value stem:[v] by converting stem:[v_1] to the type
|
|
stem:[T], where
|
|
stem:[T] is signed if stem:[T_1] is signed and unsigned if
|
|
stem:[T_1] is unsigned, and
|
|
stem:[T] has the same width as stem:[T_2].
|
|
|
|
. Construct stem:[v_2] by converting stem:[v] to stem:[T_2].
|
|
|
|
For example converting `-1: I8` to `U16` yields `0xFFFF: U16`
|
|
|
|
==== Primitive and Non-Primitive Integer Values
|
|
|
|
If stem:[T_1] is _Integer_ and stem:[T_2] is a primitive integer type, then
|
|
proceed as if stem:[T_1] were a signed primitive integer
|
|
type of the narrowest bit width that will hold stem:[v_1].
|
|
For example, converting `-0x1234` to `I8` yields `-0x34: I8`.
|
|
|
|
If stem:[T_1] is a primitive integer type and stem:[T_2] is
|
|
_Integer_, then stem:[v_2] is the integer value of stem:[v_1]
|
|
at type _Integer_. For example, converting
|
|
`0xFFFF: U32` to _Integer_ yields `0xFFFF:` _Integer_.
|
|
|
|
==== Floating-Point Values
|
|
|
|
We use the standard rules for IEEE floating-point values to convert
|
|
among integer values to and from floating-point values and
|
|
floating-point values to and from each other.
|
|
|
|
==== String Values
|
|
|
|
If stem:[T_1] is a string type and stem:[T_2] is a string type,
|
|
then let stem:[v_2 = v_1].
|
|
|
|
As noted in the section on <<Values_String-Values,string values>>, if the size
|
|
of type stem:[T_2] is less than the length of value stem:[v_1], then string
|
|
truncation may occur.
|
|
Any such truncation is handled by the generated code.
|
|
The FPP type system does not perform any truncation.
|
|
|
|
==== Array Values
|
|
|
|
If stem:[T_2] is an array type and stem:[T_1 = T_2], then
|
|
let stem:[v_2 = v_1].
|
|
|
|
Otherwise if stem:[T_1] is
|
|
a numeric type, Boolean type, enum type, or string type
|
|
and stem:[T_2] is an anonymous array type or array type with stem:[n]
|
|
elements, then
|
|
|
|
. Let stem:[T'_2] be the element type of stem:[T_2].
|
|
|
|
. Let stem:[w] be the result of converting stem:[v_1] to type stem:[T'_2].
|
|
|
|
. Let stem:[v_2] be the unique array value of type stem:[T_2]
|
|
with value stem:[w] at each element.
|
|
|
|
Otherwise if stem:[T_1] is an anonymous array type and stem:[T_2] is an
|
|
anonymous array type or array type, both with stem:[n] elements, then
|
|
|
|
. Let stem:[T'_2] be the element type of stem:[T_2].
|
|
|
|
. For each stem:[i in [0,n-1\]], let stem:[w_i] be the result of converting
|
|
element stem:[i] of stem:[v_1] to type stem:[T'_2].
|
|
|
|
. Let stem:[v_2] be the unique array value of type stem:[T_2]
|
|
with value stem:[w_i] at each element stem:[i].
|
|
|
|
Otherwise the conversion is not valid.
|
|
|
|
==== Structure Values
|
|
|
|
If stem:[T_2] is a struct type and stem:[T_1 = T_2], then
|
|
let stem:[v_2 = v_1].
|
|
|
|
Otherwise if stem:[T_1] is an anonymous struct type and stem:[T_2] is
|
|
an anonymous struct type or struct type
|
|
such that for each member stem:[m] `:` stem:[v_m] of stem:[T_1] there is a member
|
|
stem:[m] `:` stem:[T_m] in stem:[T_2], then use the value of stem:[T_2] with
|
|
the following members:
|
|
|
|
. For each member stem:[m] `:` stem:[T_m] of stem:[T_2] such that there is a member
|
|
stem:[m] `:` stem:[v_m] in stem:[v_1], add the member stem:[m] `:` stem:[v'_m],
|
|
where stem:[v'_m] is the result of converting stem:[v_m] to stem:[T_m].
|
|
|
|
. For each member stem:[m] `:` stem:[T_m] of stem:[T_2] such that there is no member
|
|
stem:[m] `:` stem:[v_m] in stem:[v_1], add the member stem:[m] `:` stem:[v'_m],
|
|
where stem:[v'_m] is the <<Types_Default-Values,default value>> at type stem:[T_m].
|
|
|
|
Otherwise the conversion is invalid.
|