Threadon / Types

Types

every value has one, and it's checked

The type list

Threadon has eight built-in types.

TypeWhat it holdsNotes
Int88-bit signed integerwraps, range -128 to 127
Int1616-bit signed integerwraps, range -32,768 to 32,767
Int3232-bit signed integerthe default integer, wraps, range -2,147,483,648 to 2,147,483,647
Int6464-bit signed integerwraps, range -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
UInt88-bit unsigned integerwraps, range 0 to 255
UInt1616-bit unsigned integerwraps, range from 0 to 65,535
UInt3232-bit unsigned integerwraps, range from 0 to 4,294,967,295
UInt6464-bit unsigned integerwraps, range from 0 to 18,446,744,073,709,551,615
Float1616-bit floatprints like a normal float, half precision
Float3232-bit floatthe default float, single precision
Float6464-bit floatIf you want more precision and a bigger range, double precision
Boolboolean valuetrue or false (prints contextually based on language)
Stringtextsequence of characters, no concatenation yet
NoneTypeno valueonly used for return types or representing absence of value

Besides these, you can define your own struct types. See Structs.

Integers

A plain number in your code, like 42, is an Int32. Use the cast syntax to store it in a smaller type:

a: Int8 = Int8(10)
b: Int16 = Int16(300)
c: Int32 = 70000

If you go past the range of an integer you'll get an error if you've enabled --debug and if you're using floats you will get an error if you use the flag --flag-inf.

Look at what happens as an Int8 climbs past its maximum of 127:

def main() -> Int32
    print(Int8(127))
    print(Int8(128))
    print(Int8(255))
    return 0
RuntimeError: compiler error: Error: Integer literal 128 out of range for type 'Int8' at line 3 print(Int8(128)) ^

It won't even compile. But if you let the user input a number you've still that risk

def main() -> Int32
    print(Int8(input("input a number")))
    return 0
input a number: 128 [RUNTIME ERROR] │ Error: Integer overflow in string conversion (value out of range for Int8) ├─> Location: String → Int8 cast └─> Process terminated with exit code 1

Floats

A number with a decimal point, like 2.5, is a Float32. Float16 is the smaller sibling and Float64 the bigger sibling.

Floats print with six decimals, always. There is no formatting control yet.

def main() -> Int32
    print(Float32(2.5))
    print(Float64(0.1))
    print(Float16(1.5))
    return 0
2.500000 0.100000 1.500000

Note that print(2.5) and print(Float32(2.5)) print the same thing. The literal is already a float.

Bools

Bool holds true or false. The literals are True and False. Conditions must be bools, so comparisons return bools.

def main() -> Int32
    print(True)
    print(False)
    print(3 < 5)
    print(3 == 5)
    return 0
True False True False

Strings

A String is a piece of text, written with double quotes.

name: String = "John"

Strings have no tools yet. You can't concatenate them, you can't take their length, you can't convert a number into a string. The two things you can do with a string are pass it to print or input, and convert it into a number. All of that is on the Limits page.

NoneType

NoneType means "no value". It is used as the return type of functions that don't return anything.

Always have a return in a function. You can type just returnWithout a value but the program needs to return something on every path

This


  def main() -> Int32:
      if 1 == 1:
          return 0
      else:
          print()
  

is illegal.

Error: Function must return a value on all code paths at line 5 print() ^
def say_hi() -> NoneType
    print("hi")
    return

Values that were never set

If you declare a variable without giving it a value, it starts at zero. Integers start at 0, floats at 0.0, bools at false.

def main() -> Int32
    n: Int32
    f: Float32
    b: Bool
    print(n)
    print(f)
    print(b)
    return 0
0 0.000000 False

It's still a good idea to set a value yourself. The zero behavior is a convenience, not a promise, and relying on it makes code harder to read.

One exception: struct fields you leave out of an initializer are not zeroed. They hold garbage. See Structs.

Strict type checking

Threadon checks types at compile time and is strict about it. Two things you will hit immediately:

  • You can't mix integer and float in the same expression. 1 + 2.5 is a compile error. Convert first: Float32(1) + 2.5.
  • You can't compare different types. 1 == 1.0 is a compile error.
  • You can't assign a value to a variable of a different type. x: Int32 = 3.5 is a compile error.

The one lenient case: an integer literal can adapt to the type of the variable you assign it to. x: Int8 = 5 works, even though 5 on its own is an Int32. The literal is retyped to fit. See Variables.

Everything else has to match exactly, or you convert it with a cast.