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 |
|---|---|
|
Signed 8-bit integer |
|
Signed 16-bit integer |
|
Signed 32-bit integer |
|
Signed 64-bit integer |
|
Unsigned 8-bit integer |
|
Unsigned 16-bit integer |
|
Unsigned 32-bit integer |
|
Unsigned 64-bit integer |
|
Boolean value (0 or 1) |
|
32-bit float |
|
64-bit float |
|
Void pointer (for generic typing) |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
|
C type |
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.