Documentation / Numbers

Numbers

Moth ships two numeric types. Strict rules around literals, spacing and failure keep a number consistent across compiler stages and backends.

Choose the explanation level: Numeric types

Numeric types

Moth uses Int for whole numbers and Float for decimal numbers.


    lives Int = 3
    progress Float = 0.75
    

An Int can be used where a Float is expected:


    lives Int = 3
    display_value Float = lives
    

A Float never silently becomes an Int. That conversion can lose information, so it needs an explicit cast.

Moth has two core numeric types.

Int

Int is a signed 32-bit integer.

Its range is:


        -2147483648 through 2147483647
    

Float

Float is a finite f64.

NaN, positive infinity and negative infinity are not valid Moth Float values. Boundaries that can introduce a non-finite result must reject it.

Promotion

Int may promote to Float at a contextual numeric boundary.


    count Int = 3
    ratio Float = count
    

Mixed Int and Float arithmetic produces Float.

There is no implicit Float -> Int conversion. Use a fallible explicit cast at an Int target.

Bool and Char are not numeric types.

Choose the explanation level: Numeric literals

Numeric literals

Whole numbers are Int values:


    score = 42
    

Numbers with a decimal point are Float values:


    progress = 0.5
    

Large and tiny values can use lowercase e notation:


    population = 1e6
    tolerance = 1e-6
    

Keep a minus sign attached to the value:


    temperature = -5
    opposite = -count
    

1E6, +1 and - count are not valid numeric forms.

The source spelling of a number determines its natural type.


    whole = 42
    decimal = 0.5
    large = 1e6
    small = 1e-6
    precise = 1.0e+21
    

Contract

  • A whole-number literal is naturally Int.
  • A decimal-point literal is naturally Float.
  • Exponents use lowercase e.
  • Uppercase E is rejected.
  • Unary + is rejected.
  • A leading - must be attached to the literal or expression it negates.
  • -1, -1e6 and -count are valid prefix forms.
  • - count is invalid.
  • Integer literals must fit the Int range.
  • Float literals must materialize to a finite Float.

    valid_literal = -42
    valid_expression = -count

    invalid_exponent = 1E6
    invalid_plus = +1
    invalid_spacing = - count
    

The invalid lines above demonstrate rejected syntax. They are not valid program forms.

Choose the explanation level: Operators

Operators

Put spaces around symbolic operators.


    total = left + right
    count += 1
    

Moth uses words for equality and logic:


    same = left is right
    different = left is not right
    ready = loaded and valid
    retry = timed_out or disconnected
    blocked = not ready
    

Division has two forms:


    real_result = 5 / 2
    whole_result = 5 // 2
    

/ produces a real Float result. // performs integer division and produces an Int.

Use templates to join text:


    greeting = ["Hello, ", "Priya"]
    

Templates handle all string joining and interpolation. + is for numbers only.

Moth keeps equality and logical operators readable.


    same = left is right
    different = left is not right
    ready = has_input and is_valid
    should_retry = timed_out or disconnected
    blocked = not ready
    
  • and and or require Bool operands.
  • not requires one Bool operand.
  • Symbolic equality and symbolic logical-not forms are not language operators.

Arithmetic results

  • Int, Int with +, -, *, %, ^, // produces Int
  • Int, Int with / produces Float
  • Float, Float with +, -, *, /, %, ^ produces Float
  • mixed Int and Float with +, -, *, /, %, ^ produces Float

// is integer division and is valid only for two Int operands.

Comparisons

  • Int and Float support equality and ordering, including mixed numeric comparisons.
  • Char supports equality and ordering.
  • Bool supports equality only.
  • String supports is and is not. It does not support ordering operators.
  • Choices and options have additional equality rules in their own references.

+ is a numeric operator only. Source string concatenation uses templates. See Strings and characters for the canonical concatenation form.

Precedence and associativity

From highest to lowest:

  • level 6: unary not, unary -
  • level 5: ^
  • level 4: *, /, //, %
  • level 3: +, -
  • level 2: is, is not, <, <=, >, >=
  • level 1: and
  • level 0: or

^ is right-associative. Other binary operators are left-associative.

Parentheses override normal precedence.

Spacing

Symbolic binary operators require spaces on both sides. Assignment = follows the same outer-spacing rule, but it is not a binary operator.


    total = left + right
    count = 1
    

These forms are invalid:


    -- INVALID: missing required spacing
    total=left+right
    count=1
    

Compound assignments follow the same rule:


    count += 1
    count //= 2
    

count+=1, count +=1 and count+= 1 are invalid.

The mutable declaration spelling ~= stays adjacent. It needs whitespace before ~ and after =:


    count ~= 1
    

count~= 1, count ~=1 and count ~ = 1 are invalid.

Operator overloading is outside Moth's language design. Operators remain compiler-owned and predictable.

Choose the explanation level: Checked arithmetic

Checked arithmetic

Moth checks arithmetic instead of quietly wrapping or producing invalid floating-point values.

These operations can fail:

  • overflowing an Int
  • dividing by zero
  • using an invalid integer exponent
  • producing NaN or infinity

A function with an Error! return can pass that failure through its normal error path:


    divide |left Int, right Int| -> Float, Error!:
        return left / right
    ;
    

Outside that kind of function, an unexpected runtime numeric failure stops the current program path.

A failure the compiler can prove in advance is reported during compilation.

Runtime numeric operations are checked.

Failures include:

  • integer overflow
  • division or modulo by zero
  • invalid integer exponents
  • non-finite Float results

Failure mode

When the enclosing function has builtin Error! as its error return slot, checked numeric failures use that error channel.


    divide |left Int, right Int| -> Float, Error!:
        return left / right
    ;

    ratio = divide(10, 0) catch:
        then 0.0
    ;
    

Custom fallible channels, non-fallible functions and entry-selected top-level runtime code use trap mode for checked numeric failure.

Numeric operators remain ordinary source expressions. The compiler lowers their failure path. They are not source-visible Error! values that can be handled in the middle of an arbitrary expression.

Compile-time failures

A statically known numeric failure is a compile-time diagnostic.

This remains true inside a function with builtin Error!.

Related behaviour

Range-loop counter updates use the same checked numeric operations.

Conversions that may lose information, such as Float -> Int, belong to the Casts documentation rather than implicit arithmetic coercion.