Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

i32.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature i32
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# i32 -- 32-bit signed integer values
#
public i32(public val i32) : num.wrap_around, has_interval is

  public thiz => i32.this.val

  # overflow checking

  # would negation -thiz cause an overflow?
  redef wrapped_on_neg => is_min

  # would addition thiz + other cause an overflow or underflow?
  public fixed overflow_on_add (other i32) => thiz > 0 && i32.max -° thiz < other
  public fixed underflow_on_add(other i32) => thiz < 0 && i32.min -° thiz > other

  # would subtraction thiz - other cause an overflow or underflow?
  public fixed overflow_on_sub (other i32) => thiz > 0 && thiz -° i32.max > other
  public fixed underflow_on_sub(other i32) => thiz < 0 && thiz -° i32.min < other

  # would multiplication thiz * other cause an overflow or underflow?
  public fixed overflow_on_mul (other i32) => as_i64 *° other.as_i64 > i32.max.as_i64
  public fixed underflow_on_mul(other i32) => as_i64 *° other.as_i64 < i32.min.as_i64

  # neg, add, sub, mul with wrap-around semantics
  public fixed prefix -° i32 => intrinsic
  public fixed infix +° (other i32) i32 => intrinsic
  public fixed infix -° (other i32) i32 => intrinsic
  public fixed infix *° (other i32) i32 => intrinsic

  # division and remainder with check for div-by-zero
  public fixed infix / (other i32)
  pre
    safety: other != 0
  => div other
  public fixed infix % (other i32)
  pre
    safety: other != 0
  => mod other

  # private division and remainder with crash in case of div-by-zero
  private div (other i32) i32 => intrinsic
  private mod (other i32) i32 => intrinsic

  # bitwise and, or and xor operations
  public fixed infix &  (other i32) i32 => intrinsic
  public fixed infix |  (other i32) i32 => intrinsic
  public fixed infix ^  (other i32) i32 => intrinsic

  # shift operations (signed)
  public fixed infix >> (other i32) i32 => intrinsic
  public fixed infix << (other i32) i32 => intrinsic

  # conversion to u32, i64 and u64, with range check
  public as_i8 i8
    pre
      thiz ≥ i8.min.as_i32
      thiz ≤ i8.max.as_i32
    =>
      low8bits.cast_to_i8
  public as_i16 i16
    pre
      thiz ≥ i16.min.as_i32
      thiz ≤ i16.max.as_i32
    =>
      low16bits.cast_to_i16
  public as_i64 i64 => intrinsic
# as_i128 NYI
  public as_u8 u8
    pre
      thiz ≥ u8.min.as_i32
      thiz ≤ u8.max.as_i32
    =>
      low8bits
  public as_u16 u16
    pre
      thiz ≥ u16.min.as_i32
      thiz ≤ u16.max.as_i32
    =>
      low16bits
  public as_u32 u32
    pre
      debug: thiz ≥ 0
    =>
      cast_to_u32
  public as_u64 u64
    pre
      debug: thiz ≥ 0
    =>
      as_i64.as_u64
  public as_u128 u128
    pre
      debug: thiz ≥ 0
    =>
      u128 0 as_i64.as_u64
  public as_int int =>
    int as_i64


  # casting bit representation to unsigned
  public low8bits    u8   => cast_to_u32.low8bits    # 0x1234_5678 ->        0x78, -0x1234_5678 -> 0x88
  public low16bits   u16  => cast_to_u32.low16bits   # 0x1234_5678 ->      0x5678, -0x1234_5678 -> 0xa988
  public cast_to_u32  u32  => intrinsic              # 0x1234_5678 -> 0x1234_5678, -0x1234_5678 -> 0xedcb_a988
  public cast_to_u64  u64  => cast_to_u32.as_u64     # 0x1234_5678 -> 0x1234_5678, -0x1234_5678 -> 0x0000_0000_edcb_a988
  public cast_to_u128 u128 => cast_to_u32.as_u128    # 0x1234_5678 -> 0x1234_5678, -0x1234_5678 -> 0x0000_0000_0000_0000_0000_0000_edcb_a988

  # conversion to float
  public as_f64 f64 => intrinsic
  public as_f32 => as_f64.as_f32


  # create hash code from this number
  public type.hash_code(a i32.this) u64 =>
    hash a.cast_to_u64


  # find the highest 1 bit in this integer and return integer with
  # this single bit set or 0 if this is 0.
  #
  public highest_one_bit i32 =>
    val.cast_to_u32.highest_one_bit.cast_to_i32


  # count the number of trailing zeros in this integer.
  #
  public trailing_zeros i32 =>
    val.cast_to_u32.trailing_zeros


  # count the number of 1 bits in the binary representation of this
  # integer.
  #
  public ones_count i32 =>
    val.cast_to_u32.ones_count


  # -----------------------------------------------------------------------
  #
  # type features:


  # identity element for 'infix +'
  #
  fixed type.zero i32 => 0


  # identity element for 'infix *'
  #
  fixed type.one  i32 => 1


  # equality
  #
  fixed type.equality(a, b i32) bool => intrinsic_constructor


  # total order
  #
  fixed type.lteq(a, b i32) bool => intrinsic_constructor


  # returns the number in whose bit representation all bits are ones
  public fixed redef type.all_bits_set => i32 -1


  # minimum
  #
  public fixed type.min => i32 -0x_8000_0000


  # maximum
  #
  public fixed type.max => i32 0x_7fff_ffff