# 1 Language features.

In these definitions, we introduce basic types into Felix with
bindings to C. These are expressed by the `type`

statement,
which gives the Felix name of the type, and then the C
name in quotes.

Note very particularly each type is distinct, type names
such as `size_t`

in C and C++ are merely aliases for
some other integer type, in Felix these types are
completely distinct.

The adjective `pod`

stands for *plain old datatype*
and tells the system that the type has a trivial destructor
and does not require finalisation.

The adjective `_gc_pointer`

tells the system the abstract
primitive is in fact a pointer and the garbage collector
must follow it.

The `requires`

clause, if specified, tells the system
that the named floating insertion must be emitted into
the generated C++ code. We will use the names of code
fragments specifying header files defined
in the **cheaders** package.

# 2 Synopsis

share/lib/std/scalar/__init__.flx

include "std/scalar/ctypedefs"; include "std/scalar/address"; include "std/scalar/memory"; include "std/scalar/bool"; include "std/scalar/int"; include "std/scalar/real"; include "std/scalar/complex"; include "std/scalar/quaternion"; include "std/scalar/char"; include "std/scalar/float_format"; include "std/kind/staticbool";

# 3 Character type

A basic 8 bit character type.

share/lib/std/scalar/ctypedefs.flx

pod type char = "char";

# 4 Efficient Integer types

These types correspond to C99 integer types. Note that Felix mandates the existence of the long long types.

Note we also require the C99 `intmax_t`

and `uintmax_t`

types. These will usually be signed and unsigned
long long, however they may be an even larger type if the
C implementor desires.

We also map C89 `size_t`

and the less useful C99 `ssize_t`

,
a signed variant of `size_t`

. These are used for array
lengths and in particular can span byte arrays as large
as can be addressed.

share/lib/std/scalar/ctypedefs.flx

pod type tiny = "signed char" requires index TYPE_tiny; pod type short = "short" requires index TYPE_short; pod type int = "int" requires index TYPE_int; pod type long = "long" requires index TYPE_long; pod type vlong = "long long" requires index TYPE_vlong; pod type utiny = "unsigned char" requires index TYPE_utiny; pod type ushort = "unsigned short" requires index TYPE_ushort; pod type uint = "unsigned int" requires index TYPE_uint; pod type ulong = "unsigned long" requires index TYPE_ulong; pod type uvlong = "unsigned long long" requires index TYPE_uvlong; pod type intmax = "intmax_t" requires C99_headers::stdint_h, index TYPE_intmax; pod type uintmax = "uintmax_t" requires C99_headers::stdint_h, index TYPE_uintmax; pod type size = "size_t" requires C89_headers::stddef_h, index TYPE_size; pod type ssize = "ssize_t" requires C89_headers::stddef_h, index TYPE_ssize; /* for concordance, required to generated loops */ class PervasiveInts { private const zero: int = "0" requires index CONST_zero; private fun isneg: int -> 2 = "$1<0" requires index FUN_isneg; private fun isnonneg: int -> 2= "$1>=0" requires index FUN_isnonneg; private proc decr: &int = "--*$1;" requires index PROC_decr; } // Shouldn't really be here! class PervasiveLogic { private fun land: bool * bool -> bool = "$1&&$2" requires index FUN_land; private fun lor: bool * bool -> bool = "$1||$2" requires index FUN_lor; private fun lnot: bool * bool -> bool = "!$1" requires index FUN_lnot; }

# 5 Exact Integer types

Here are the usual exact integer types.
Note that Felix mandates the existence of the `stdint.h`

header file from C99, and that all the exact types are
defined. This includes 64 bit signed and unsigned integers,
even on a 32 bit machine.

share/lib/std/scalar/ctypedefs.flx

pod type int8 = "int8_t" requires C99_headers::stdint_h, index TYPE_int8; pod type int16 = "int16_t" requires C99_headers::stdint_h, index TYPE_int16; pod type int32 = "int32_t" requires C99_headers::stdint_h, index TYPE_int32; pod type int64 = "int64_t" requires C99_headers::stdint_h, index TYPE_int64; pod type uint8 = "uint8_t" requires C99_headers::stdint_h, index TYPE_uint8; pod type uint16 = "uint16_t" requires C99_headers::stdint_h, index TYPE_uint16; pod type uint32 = "uint32_t" requires C99_headers::stdint_h, index TYPE_uint32; pod type uint64 = "uint64_t" requires C99_headers::stdint_h, index TYPE_uint64; pod type uint128 = "uint128_t" requires package "flx_uint256_t"; pod type uint256 = "uint256_t" requires package "flx_uint256_t";

# 6 Raw Memory

Raw memory operations provide an uninterpreted byte and
two address types.
We also provide a mapping of `ptrdiff_t`

which is a signed
type holding the result of subtracting two pointers or
addresses of the same type.

Finally, we provide signed and unsigned integers of the same size as addresses and pointers which can be used to perform arbitrary integer operations.

share/lib/std/scalar/ctypedefs.flx

pod type byte = "unsigned char" requires index TYPE_byte; type caddress = "void *"; _gc_pointer type address = "void *" requires index TYPE_address; pod type ptrdiff = "ptrdiff_t" requires C89_headers::stddef_h, index TYPE_ptrdiff; pod type intptr = "intptr_t" requires C99_headers::stdint_h, index TYPE_intptr; pod type uintptr = "uintptr_t" requires C99_headers::stdint_h, index TYPE_uintptr;

# 7 Integer literal constructors.

In Felix, integer types are lifted from C in the library. Therefore, constructors for these types must also be defined in the library, including literals.

In Felix, internally, all literals are represented opaquely. There are three components to a literal: the Felix type, the string value of the lexeme decoded by the parser, and a string representing the C++ value to be emitted by the compiler back end.

The grammar specification consists of regular definitions used to recognize the literal, and decoding routines written in Scheme used to produce the triple required by the compiler.

# 8 Floating types

Note that Felix requires the long double type from C99. Also note that the complex types are taken from C++ and not C!

share/lib/std/scalar/ctypedefs.flx

pod type float = "float" requires index TYPE_float; pod type double = "double" requires index TYPE_double; pod type ldouble = "long double" requires index TYPE_ldouble; pod type fcomplex = "::std::complex<float>" requires Cxx_headers::complex, index TYPE_fcomplex; pod type dcomplex = "::std::complex<double>" requires Cxx_headers::complex, index TYPE_dcomplex; pod type lcomplex = "::std::complex<long double>" requires Cxx_headers::complex, index TYPE_lcomplex;

# 9 Groupings of the types.

We can define sets of types so they may be used in in function bindings to avoid a lot of repetition.

The `typesetof`

operator takes a comma separated list
of parenthesised type names, and represents a finite
set of types.

The \(\cup\) operator, spelled `\cup`

, can be used to find the setwise
union of two typesets.

share/lib/std/scalar/ctypedefs.flx

Types associated with raw address calculations. typedef addressing = typesetof ( byte, address, caddress ); Character types. typedef chars = typesetof (char);

## 9.1 Integers

share/lib/std/scalar/ctypedefs.flx

"natural" sized signed integer types. These correspond to C/C++ core types. typedef fast_sints = typesetof (tiny, short, int, long, vlong); Exact sized signed integer types. In C these are typedefs. In Felix they're distinct types. typedef exact_sints = typesetof(int8,int16,int32,int64); "natural" sized unsigned integer types. These correspond to C/C++ core types. typedef fast_uints = typesetof (utiny, ushort, uint, ulong,uvlong); Exact sized unsigned integer types. In C these are typedefs. In Felix they're distinct types. typedef exact_uints = typesetof (uint8,uint16,uint32,uint64,uint128,uint256); Weirdo signed integers types corresponding to typedefs in C. typedef weird_sints = typesetof (ptrdiff, ssize, intmax, intptr); Weirdo unsigned integers types corresponding to typedefs in C. typedef weird_uints = typesetof (size, uintmax, uintptr); All the signed integers. typedef sints = fast_sints \(\cup\) exact_sints \(\cup\) weird_sints; All the usigned integers. typedef uints = fast_uints \(\cup\) exact_uints \(\cup\) weird_uints; All the fast integers. typedef fast_ints = fast_sints \(\cup\) fast_uints; All the exact integers. typedef exact_ints = exact_sints \(\cup\) exact_uints; All the integers. typedef ints = sints \(\cup\) uints;

## 9.2 Floats

share/lib/std/scalar/ctypedefs.flx

All the core floating point types. typedef floats = typesetof (float, double, ldouble); All the core approximations to real types. typedef reals = ints \(\cup\) floats; All the core approximations to complex types. typedef complexes = typesetof (fcomplex,dcomplex,lcomplex); All the core approximations to numbers. typedef numbers = reals \(\cup\) complexes;

## 9.3 All Scalars.

share/lib/std/scalar/ctypedefs.flx

All the basic scalar types. typedef basic_types = bool \(\cup\) numbers \(\cup\) chars \(\cup\) addressing; // we define this now, we will open it later... instance [t in basic_types] Eq[t] { fun == : t * t -> bool = "$1==$2"; } // we open this now even though we haven't developed // the instances yet.... open[T in basic_types] Show[T];