iyi

Prelude, 0.18.0

Object

What the compiler emits instructions for — SPEC.md, "0.1.0", item 3.

In the prelude: every iyi program has it, with no import.

A @[Primitive] method has no body on purpose: the annotation names an instruction the code generator writes at the call site. So this file is not an implementation, it is the list of machine operations iyi admits, and its shape is a language decision rather than a library one.

**This is iyi's list, not Crystal's.** src/primitives.cr declares twelve numeric types and crosses them with each other, which is 2,580 definitions expanded on every build and **0.11 s of a 0.17 s front end** — measured by deleting the block and building again. iyi crosses five, which is 445.

The five are Int32, Int64, UInt8, UInt64 and Float64: the default integer, the one a byte count grows into, the byte itself, the one an address and a size are, and a float. UInt16 joins them for comparison alone, for the reason written at the cross below: a wide character is compared on every Windows path. Int8, Int16, Int128 and the unsigned middle exist as types and have no arithmetic, because no sample writes one — the same rule the rest of the prelude is built on. Writing 1_i8 + 1_i8 is an "undefined method" and that is the honest answer: 0.1.0 does not have eight-bit arithmetic rather than having it slowly.

**Comparison is not refused the same way, and that is a defect this file cannot close.** Object#== answers false for anything no type claimed, which is right about two objects and a lie about two numbers: without import std/int, 1_i8 == 1_i8 is false rather than an error, and it was 92_u16 == 92_u16 answering false that hid two Windows defects for a week. Refusing it needs both sides' types at once, which a method body does not have — a guard on the receiver alone refuses 5 == nil, where false is the correct answer, and it was measured doing exactly that to eleven exercises. The fix belongs in overload resolution, where the compiler knows both types; until then UInt16 being in the cross is what the library's own callers needed, and this paragraph is the rest of the truth.

Objectclass

Objectiyi doc Object
class Object

  def !=(other) : Bool

  def ==(other) : Bool

  # Case equality, what a `when` asks of each arm: equality, unless a type
  # answers with something stronger - a range, a class, a tuple.
  def ===(other) : Bool

  def class

  # Every type is usable as a `Hash` key, and one that has not said how it
  # hashes hashes to its type: correct and useless, every value of the type
  # in one slot, the honest default. A type used as a key defines `hash`.
  def hash : Int32

  # `value.in?(a, b)` — the Kemal port's way of writing an alternation. On
  # `Object` because it is about the value, not about any one type of it.
  def in?(*values : *T) : Bool forall T

  # What a value looks like written down rather than printed: the two differ
  # for `nil` and strings, and `#{value.inspect}` shows a value is absent.
  def inspect : String

  # The type's own name, which is what a value that has said nothing about
  # itself can honestly print. A type that wants better defines its own.
  def to_s : String
end