Types


Summary


Static typing or dynamic typing


Shard is a statically typed programming language. This means that types are resolved at compile-time, unlike dynamically typed languages, which resolve their types at run-time. Here is an example of how both systems work:

// static typing
var x: i32 = 5;
x = 89;
// dynamic typing
var y: i32 = 5;
y = 8.9;

In the example below, only the first two lines will produce executable code, because x is of type i32, so it expects a 32-bit integer value. On the second line, we set it to 5, which is an integer lesser than 232, so the example is valid. On the other hand, we have the two last lines, which suppose that dynamic typing is implemented in Shard (it is not). So we have another variable of type i32 (y), but we assign it a floating value on the fourth line. In a language like Python, this will work, but not in languages such as Shard, C or Rust, because you cannot change the type of a variable.

Strong typing or weak typing


Shard is a strongly typed programming language. This means that operations can only be applied on values of the same type. For example, if I add a f64 with an u64, the C compiler will raise a warning (because Shard doesn’t have type checking yet).

Different data types


Here are all the data types that can be used in Shard. The types prefixed by “C_” are used for compatibility with the C programming language.

Type name

Accepted values

i8

Signed 8-bit integer

i16

Signed 16-bit integer

i32

Signed 32-bit integer

i64

Signed 64-bit integer

u8

Unsigned 8-bit integer

u16

Unsigned 16-bit integer

u32

Unsigned 32-bit integer

u64

Unsigned 64-bit integer

bool

Boolean value (0 or 1)

f32

32-bit float

f64

64-bit float

voidptr

Void pointer (for generic typing)

C_char

C type char

C_short

C type short

C_int

C type int

C_long

C type long

C_uchar

C type unsigned char

C_ushort

C type unsigned short

C_uint

C type unsigned int

C_ulong

C type unsigned long

C_void

C type void

C_size

C type size_t

C_usize

C type unsigned size_t

Casting types


To avoid strong typing restrictions, Shard allow the developer to cast types, using the as operator, which tells the compiler to interpret a type as another type. Let’s make an example:

var x: u8 = 15;
var y: u16 = x as u16;

The type of x will not be turned into u16, but interpreted as u16 only in the operation where as is used. This is like a temporary type conversion.

Array types


When declaring arrays, you need to use array types. They tell the compiler about the type of the array and its size (in elements). Here is how to use one:

[size]type
// for example
[10]i32

This tells the compiler that our array is of type i32 and length 10.

Pointer types


When declaring pointers, you need to use pointer types. They are prefixed by a theorically unlimited count of *. Here is how to use one:

var p: *i32;            // a pointer of type i32
var pp: **i32;          // a pointer of pointer of type i32
var ppp: ***i32;        // a pointer of pointer of pointer of type i32
var pppppppp: **************************i32;        // help

Type aliases


A type alias is what we can call a fake type. When you type the name of an alias, the compiler will replace it by the name of the aliased type. Type aliases are defined using the type keyword.

type int = C_int;
// now, "int" will be interpreted as "C_int"
var x: int = 42;
var x: C_int = 42;          // same

You can also define aliases of aliases:

type int = C_int;
type in = int;
type i = in;
type _ = i;
// ...

Creating new types


Shard allows the developer to create new types. They are not aliases, but real types, which correspond to a real C type. They are defined using the newtype keyword. For example, let’s imagine that you are writing a Shard binding for stdio.h:

newtype stdio_file = "FILE";

The compiler will now compile every use of stdio_file into FILE.