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