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

Type.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 Type
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# Type -- parent feature of all type features
#
# type features 'f.type' are declared implicitly for every feature f.
# Type features do not contain state, they are unit types.
#
# All type features inherit directly (Any.type) or indirectly (all
# others type features) from this feature.
#
module:public Type ref is


  # name of this type, including type parameters, e.g. 'option (list i32)'.
  #
  public name String => intrinsic


  # string representation of this type to be used for debugging.
  #
  # result has the form "Type of '<name>'", but this might change in the future
  #
  public redef as_string => "Type of '$name'"


  # convenience prefix operator to create a string from a value.
  #
  # This permits usage of `$` as a prefix operator in a similar way both
  # inside and outside of constant strings: $x and "$x" will produce the
  # same string.
  #
  # NYI: Redefinition allows the type feature to be distinguished from its normal counterpart, see #3913
  #
  public redef prefix $ => Type.this.as_string


  # There is no dynamic type of a type instance since this would result in an
  # endless hierarchy of types, so dynamic_type is redefined to just return
  # Type.type here.
  #
  public redef dynamic_type => Type.type


  # Is this type assignable to a type parameter with constraint `T`?
  #
  # The result of this is a compile-time constant that can be used to specialize
  # code for a particular type.
  #
  #   is_of_integer_type(n T : numeric) => T : integer
  #   say (is_of_integer_type 1234)    # true
  #   say (is_of_integer_type 3.14)    # false
  #
  # it is most useful in conjunction preconditions or `if` statements as in
  #
  #   pair(a,b T) is
  #     same
  #       pre T : property.equatable
  #   =>
  #     a = b
  #
  # or
  #
  #   val(n T) is
  #
  #     # check if T is numeric, if so
  #     # return true if n > zero,
  #     # return nil if T is not numeric
  #     #
  #     more_than_zero option bool =>
  #       if T : numeric then
  #         n > T.zero
  #       else
  #         nil
  #
  public infix : (T type) =>

    # Fuzion's middle end will replace calls to `Type.infix :` by calls to either
    # `Type.infix_colon_true` or `Type.infix_colon_false` depending on the result.
    #
    # The code for `Type.infix :` is dummy code that ensures that the front end will
    # know that infix_colon_true and infix_colon_false are required and will not be
    # removed.
    #
    infix_colon_true T && infix_colon_false T

  # actual feature called instead of `infix :` in case the result is `true`
  #
  private infix_colon_true  (T type) bool => true

  # actual feature called instead of `infix :` in case the result is `false`
  #
  private infix_colon_false (T type) bool => false


# Get the Type instance corresponding to a given type
#
# The result of `type_as_value x` is the same as `x.type`.
#
# Internally, Fuzion's front end implements `x.type` using
# `type_as_value x`. The middle end then replaces calls to
# `type_as_value` by `T`'s type clazz.
#
public type_as_value(T type) => T


# universe feature to determine the compile-time type of an expression.
#
# This is to be called without an actual type passed to `T`, but `T` should be
# inferred from the actual value argument `_`.
#
# The value argument is evaluated and ignored.
#
# The result is the type of the value argument boxed into a ref value and returned
# as a value of type `Type`.
#
# examples:
#
#   `type_of "bla"` is `String`
#   `type_of (panic "***")` will terminate
#
public type_of(T type, _ T) => T


# universe feature to determine the compile-time type of an expression.
#
# This is to be called without an actual type passed to `T`, but `T` should be
# inferred from the result type of the actual value argument `_`.
#
# The function passed as value argument is ignored, it is not called.
#
# The result is the result type of the value argument boxed into a ref value and
# returned as a value of type `Type`.
#
# examples:
#
#   `type_of_lazy ()->"bla"` is Type of `String`
#   `type_of_lazy ()->(panic "***")` is Type of `void`.
#
# NYI: Fuzion should have better syntax sugar for lazy value arguments such that
# we do not need the `()->` prefix to create a lambda.  Then, `type_of` could
# have a lazy argument and `type_of_lazy` could be removed.
#
public type_of_lazy(T type, _ ()->T) => T
last changed: 2025-01-23