Types
Primitive data types
Primitive data type are the building blocks of which other more complex types are derived from. Each primitive type has the following 3 attributes:
- Type: Indicates the name for the type
- Width: How many bits it takes up
- Intended interpretation: How it should be interpreted
Integral types
Type | Width | Intended interpretation |
---|---|---|
byte |
8 |
signed byte (two’s complement) |
ubyte |
8 |
unsigned byte |
short |
16 |
signed short (two’s complement) |
ushort |
16 |
unsigned short |
int |
32 |
signed int (two’s complement) |
uint |
32 |
unsigned int |
long |
64 |
signed long (two’s complement) |
ulong |
64 |
unsigned long |
There are also some types aliases to be aware of:
Type | Width | Intended interpretation |
---|---|---|
size_t |
Value of config entry types:max_width |
unsigned |
ssize_t |
Value of config entry types:max_width |
signed byte (two’s complement) |
Decimal
TODO: Add this
- float32, float64 etc
Rules
There are a few rules that the type system abides by and which one should know about when dealing with types in T.
Promotion
T has the concept of type promotion meaning that certain types when used in expressions with other different types will have some kind of automatic conversion take place.
Promotion takes place for integral types, below we have an example where
a smaller type (byte
) is automatically coerced to the bigger type (the
long
) when assigned to the variable of the type long
:
No explicit cast was required for the statement il = 1
This example is available as part of the test suite.
Literals
There is one case whereby automatic conversion (known as “coercion”) is applied and that is with the usage of numeric literals. Firstly, however, we must discuss the default encoding scheme.
Below we have a table of ranges of values (literal values) and the types
they can be coerced to. By this we mean that if you had a statement
where you were, for example, assigning one of these literals to a
variable of type T
that you would infact be able to assign such a
value to said type T
. That “type T
” is what we have in the
Coercible-to column:
Range | Coercible-to |
---|---|
0 … 255 |
ubyte , ushort , uint , ulong |
0 … 65_535 |
ushort , uint , ulong |
0 … 4_294_967_295 |
uint , ulong |
0 … 18_446_744_073_709_551_615 |
ulong |
0 … 127 |
byte , ubyte , short , ushort , int , uint , long , ulong |
0 … 32_7676 |
short , ushort , int , uint , long , ulong |
0 … 2_147_483_647 |
int , uint , long , ulong |
0 … 9_223_372_036_854_775_807 |
long , ulong |
If the expression being assigned is not a literal but rather a composed
expression such as a “negated literal” (a UnaryOpExpression
with an
operation of -
and a embedded LiteralValue
) then the following table
applies:
Range | Coercible-to |
---|---|
-128 … 127 |
byte , short , int , long |
-32_768 … 32_767 |
short , int , long |
-2_147_483_648 … 2_147_483_647 |
int , long |
-9_223_372_036_854_775_808 … 9_223_372_036_854_775_807 |
long |
- TODO: Sign/zero extension
- TODO: Mention that this is something the code emitter will have to
do by comparing the
CastedValueInstruction
’stoType
and thegetInstrType()
of the embeddedValue
-based instruction - It should, however, follow a predictable/lang-specc’d procedure
- TODO: Mention that this is something the code emitter will have to
do by comparing the