Primitives

Table of Contents

Primitive Types and Functions

Primitive Types

Neut supports integers and floats. More specifically, the following types are supported:

  • integer types: intN (= int1, int2, int3, ..., int64)
  • float types: floatN (= float16, float32, float64)

You can also use int and float. These are a syntax sugar for target-dependent types. For example, if the target architecture is 64-bit, the int is an alias of int64. If the target is 32-bit, int is an alias of int32, etc.

Primitive Functions

These primitive types have a lot of primitive functions from LLVM:

integersfloats
arithmeticsadd, sub, mul, div, rem, udiv, urem, or, xor, shl, lshr, ashrneg, add, sub, mul, div, rem
comparisoneq, ne, gt, ge, lt, le, ugt, uge, ult, uleeq, gt, ge, lt, le, ne, ord, ueq, ugt, uge, ult, ule, une, uno, false, true

For example, add-int32, neg-float64, eq-int64, and gt-float32 are available.

Neut uses LLVM's integer types and float types for its primitive types. Thus, the primitive integer types in Neut are signless. More specifically, the signedness of an integer type in Neut resides in functions, not values.

For example, div-int64 interprets its two arguments as signed integers and returns its (signed) result. udiv-int64 interprets its two arguments as unsigned integers and returns its (unsigned) result. Integer functions prefixed with u are for unsigned functions.

The internal representation of the integer types in Neut is the same as that of LLVM. Therefore, they are based on the two's complement representation. That is why Neut doesn't have something like uadd-int64. The u-prefixed integer functions are there only when we need different behaviors for different signednesses.

The following conversion functions are also available: trunc, zext, sext, fptrunc, fpext, fptoui, fptosi, uitofp, and sitofp.

For example, trunc-int64-int32, zext-int8-int32, fptoui-float32-int64, and uitofp-int64-float64 are available.

For their detailed behaviors, please refer to the LLVM language reference.

Primitive functions for int and float are also available. For example, you can use div-int, eq-int, add-float, etc. These are aliases of the corresponding primitive functions. For example, if int is int64, the div-int is the same as div-int64.

Core Types and Functions

The preset of the core library (something like Prelude in other languages) is imported automatically and provides some types and functions. These types and functions can also be used as primitives. Things like the below are defined in the library:

data void {}

data unit {
| Unit
}

data bool {
| False
| True
}

data list(a) {
| Nil
| Cons(a, list(a))
}

// you can also write `?a` instead of `either(unit, a)`
data either(a, b) {
| Left(a)
| Right(b)
}

data pair(a, b) {
| Pair(left: a, right: b)
}

Functions for those types are also defined in the library. For more, please see the source of the core library.