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. typeset addressing = { byte, address, caddress }; Character types. typeset chars = {char};
9.1 Integers
share/lib/std/scalar/ctypedefs.flx
"natural" sized signed integer types. These correspond to C/C++ core types. typeset fast_sints = {tiny, short, int, long, vlong}; Exact sized signed integer types. In C these are typedefs. In Felix they're distinct types. typeset exact_sints = {int8,int16,int32,int64}; "natural" sized unsigned integer types. These correspond to C/C++ core types. typeset fast_uints = {utiny, ushort, uint, ulong,uvlong}; Exact sized unsigned integer types. In C these are typedefs. In Felix they're distinct types. typeset exact_uints = {uint8,uint16,uint32,uint64,uint128,uint256}; Weirdo signed integers types corresponding to typedefs in C. typeset weird_sints = {ptrdiff, ssize, intmax, intptr}; Weirdo unsigned integers types corresponding to typedefs in C. typeset weird_uints = {size, uintmax, uintptr}; All the signed integers. typeset sints = fast_sints \(\cup\) exact_sints \(\cup\) weird_sints; All the usigned integers. typeset uints = fast_uints \(\cup\) exact_uints \(\cup\) weird_uints; All the fast integers. typeset fast_ints = fast_sints \(\cup\) fast_uints; All the exact integers. typeset exact_ints = exact_sints \(\cup\) exact_uints; All the integers. typeset ints = sints \(\cup\) uints;
9.2 Floats
share/lib/std/scalar/ctypedefs.flx
All the core floating point types. typeset floats = {float, double, ldouble}; All the core approximations to real types. typeset reals = ints \(\cup\) floats; All the core approximations to complex types. typeset complexes = {fcomplex,dcomplex,lcomplex}; All the core approximations to numbers. typeset numbers = reals \(\cup\) complexes;
9.3 All Scalars.
share/lib/std/scalar/ctypedefs.flx
All the basic scalar types. typeset 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];