Skip to content

Operators vs Core Host ​

Implementation status: Operator Intrinsic (language-surface hard-coded + LLVM / VM direct emit) Implemented; numeric static Host (__syx_i8_min and other per-type hosts + manifest host_ops) Implemented (Phase 45); collection HOF Host (__syx_array_map and others) Implemented (Phase 46); BigInt MVP Implemented (Phase 46); Result generic algebra (final class) Implemented (Phase 46+)

SYX splits builtin capability into two layers: user syntax mostly stays the same, but the implementation path differs.

The Two-Layer Model ​

LayerMeaningExample
Operator IntrinsicCompiler hard-coded + LLVM / VM direct emita + b / a == b / a += 1
Host ExplicitCore .sy declaration → __syx_{surface}_{op} Host functionInt8.abs(x) / Math.min(a, b) / arr.map(f)

Operators (+ / == / < / & / | and friends) always go through the Intrinsic layer; non-operator builtins (Math.min / .abs / .description / .hash / Array.map) go through the Host layer. Integer Type.min / Type.max are type bounds (static let / static computed get; not binary comparisons, and not written with ()).

Operator Intrinsic (Language-Surface Hard-Coded) ​

swift
func main() {
    var a = 1
    var b = 2
    var x = 0
    let s = a + b
    x += 1
    if (a == b) { print("eq") }
    let lt = a < b
    print(s)
    print(lt)
}

These expressions lower to NumericAdd / NumericEq / NumericLt and other MIR opcodes, compiled by codegen / LLVM into the corresponding native instructions (addsd / cmpeq, …). They do not go through a Core extension; they do not go through a Host call.

OperatorMIR operationMeaning
+NumericAddAdd
-NumericSubSubtract
*NumericMulMultiply
/NumericDivDivide
%NumericModModulo
==ValueEq / NumericEqEqual
!=ValueNeNot equal
<NumericLtLess than
<=NumericLeLess than or equal
>NumericGtGreater than
>=NumericGeGreater than or equal
&BitAndBitwise AND
|BitOrBitwise OR
^BitXorBitwise XOR
<<ShlLeft shift
>>ShrRight shift
&&BoolAndLogical AND (short-circuit)
||BoolOrLogical OR (short-circuit)
!BoolNotLogical NOT
??NilCoalesceNil coalescing
?.OptionalChainOptional chaining

Three-back-end parity: all Intrinsics behave identically on the VM / unified MIR / WASM back ends; Cranelift has been removed (Phase 77).

Host Explicit (Core + Host Functions) ​

Non-operator builtin capabilities are declared readably in Core and call per-type named Host functions __syx_{surface}_{op}:

text
// Core (packages/core/builtins/numeric/int8.sy, illustrative)
public static func min() -> Int8 { return -128i8 }
public static func abs(x: Int8) -> Int8 { return __syx_i8_abs(x) }
extension Int8 {
    func description() -> String { return __syx_value_description(self) }
}
swift
func main() {
    let lo = Int8.min                            // Type lower bound
    let hi = Int8.max
    let m = Math.min(3, 5)                       // Binary comparison → Host
    let a = Int8.abs(x: -3i8)                    // Goes through Host
    print(lo)
    print(hi)
    print(m)
    print(a)
}

Naming Contract (ADR-066 / ADR-067) ​

User APICore / Host
Int8.min / Int8.maxType bounds (static let / computed get; not Host)
Math.min(a, b) / Math.max(a, b)Binary comparison convenience layer → __syx_int_min / __syx_int_max
Int8.clamp / Math.clamp→ __syx_*_min / __syx_*_max
Math.gcd / lcm / clamp / signPure SYX (W902 Math Phase-1)
Math.pi / e / tau / …Constant static getters (literals; W902)
Math.fabs / fmin / fmax / fclampFloat64 convenience → __syx_f64_*
Math.sinh / cosh / tanh / fmod / copysign / expm1 / log1pPhase-2 → __syx_f64_* (W903)
Math.isNaN / isInfinite / isFinitePhase-2 Bool classification → `__syx_f64_isnan
Math.asinh / acosh / atanh / remainder / nextUp / nextDown / mulAddSoft → __syx_f64_* (W904; remainder ≠ fmod)
Math.erf / erfc / tgamma / lgammaSoft special → __syx_f64_* via libm (W905)
Math.sqrtf / sinf / cosf / tanf / expf / logf / fabsf / floorfF32 → __syx_f32_* (W906; *f suffix)
Math.ceilf / roundf / truncf / powf / asinf / acosf / atanf / hypotfF32 slice-2 → __syx_f32_* (W907)
Math.atan2f / log2f / log10f / exp2f / cbrtf / sinhf / coshf / tanhfF32 slice-3 → __syx_f32_* (W908)
Math.fmodf / copysignf / expm1f / log1pf / asinhf / acoshf / atanhf / erffF32 slice-4 → __syx_f32_* (W909; erff via libm)
Math.erfcf / tgammaf / lgammaf / remainderf / isNaNf / isInfinitef / isFinitef / nextUpfF32 slice-5 → __syx_f32_* (W910; classify→Bool)
Math.nextDownf / mulAddfF32 Soft closeout → __syx_f32_* (W911)
Float64.sqrt/sin/cos/tan/exp/log/floor/ceilF64 instance methods first slice → CallHost MathFloat* (W912)
Float64.abs/trunc/round/asin/acos/atan/exp2/cbrtF64 instance methods second slice → CallHost (W913; abs≡fabs)
Float64.log2/log10/pow/atan2/hypot/sinh/cosh/tanhF64 instance methods third slice → CallHost (W914; Phase-1 closeout + Soft hyperbolic first slice)
Float64.expm1/log1p/asinh/acosh/atanh/remainder/nextUp/nextDownF64 Soft remainder instance first slice → CallHost (W915)
Float64.fmod/copysign/mulAdd/erf/erfc/tgamma/lgamma/isNaNF64 Soft closeout + special first slice + isNaN → CallHost (W916)
Float64.isInfinite/isFiniteF64 classify closeout → CallHost (W917)
Float32.sqrt/sin/cos/tan/exp/logF32 instance methods first slice → CallHost (W917)
Float32.floor/ceil/abs/trunc/round/asin/acos/atanF32 instance methods second slice → CallHost (W918; abs≡fabsf)
Float32.log2/log10/pow/atan2/hypot/sinh/cosh/tanhF32 instance methods third slice → CallHost (W919; Phase-1 closeout + Soft hyperbolic first slice)
Float32.expm1/log1p/asinh/acosh/atanh/remainder/nextUp/nextDownF32 Soft remainder instance first slice → CallHost (W920)
Float32.fmod/copysign/mulAdd/erf/erfc/tgamma/lgamma/isNaNF32 Soft closeout + special + isNaN → CallHost (W921)
Float32.exp2/cbrt/isInfinite/isFiniteF32 instance closeout → CallHost (W922; parity with F64×42)
Int8.abs(x)__syx_i8_abs
.descriptionextension → __syx_value_description
.debugDescriptionextension → __syx_value_debug_description
hash(into:)extension → __syx_hasher_combine
Array.map(f)extension → __syx_array_map
Array.filter(f)extension → __syx_array_filter
Array.reduce(...)extension → __syx_array_reduce
BigInt.fromString(s)__syx_bigint_from_string
BigInt.toString(b)__syx_bigint_to_string

manifest: the host_ops field of lib/internal/manifest.json lists all host functions; the compiler looks them up in the table and links directly during codegen.

Phase 44 → 46 Evolution ​

  • Phase 44: builtin types moved into Core (packages/core/builtins/**)
  • Phase 45: min / max / abs changed from compiler hard-coded to Core extension + Host (per-type host + host_ops field)
  • Phase 46: protocol witnesses (hash / description / debugDescription) changed from compiler hard-coded to Core extensions; collection HOFs (map / filter / reduce) became Host-based; BigInt MVP; Result algebra (final class)

Phase 46 removal: the compiler's ToDescription / bare HasherCombine fallback; builtin witnesses go only through Core extension → Host.

__syx_* vs the User Surface ​

CategoryUser surfaceInternal
Numeric type methodsInt8.abs / Int8.clamp__syx_i8_abs / `__syx_i8_min
Protocol witnessesx.description__syx_value_description
Collection HOFsarr.map(f)__syx_array_map
Arbitrary Host functionsMyHost.foo(x)__syx_myhost_foo

Application code should avoid calling __syx_* directly (internal APIs may change between versions). Use the convenience layer exposed by lib/*.sy.

Collection HOFs ​

swift
func main() {
    let xs: Array<Int> = [1, 2, 3]
    let ys = xs.map({ x in x * 2 })
    let zs = ys.filter({ x in x > 2 })
    print(ys.count)
    print(zs.count)
}

Phase 46 status: map / filter / reduce are fully Host-based on Array / Set / Dictionary; three-back-end parity.

BigInt MVP ​

text
extension BigInt {
    public static func fromString(_ s: String) -> BigInt { return __syx_bigint_from_string(s) }
    public func toString() -> String { return __syx_bigint_to_string(self) }
}

Status: BigInt basic arithmetic MVP (add / sub / mul / div / cmp / fromString / toString).

Result Generics (final class) ​

text
// packages/core/builtins/result.sy (illustrative; Result is prelude — do not redeclare)
final class Result&lt;T, E&gt; { … }

Status: Result<T, E> is a final class (Phase 46 GA) providing static ok / static err / isOk and other basic APIs; extensions (such as map / flatMap) are left to each application.

Comparison with Intrinsics ​

NeedPath
+ - * /Intrinsic (compiler hard-coded)
== < >Intrinsic (Equatable / Comparable witness)
Int8.min / max (bounds)static let / computed get
Math.min / Int8.abs / clampHost (__syx_int_min / __syx_i8_abs / `_syx*_min
.descriptionHost (__syx_value_description)
arr.map(f)Host (__syx_array_map)
BigInt.addHost (__syx_bigint_add)
User-defined operatorsIntrinsic path (operator func + precedence declaration)

Complete Example ​

swift
func main() {
    let a: Int8 = 5i8
    let b: Int8 = 3i8
    print(Int8.min)                           // type lower bound (Host/static)
    print(Math.min(Int(a), Int(b)))           // binary comparison → Host
    print(a.description)                      // extension → Host

    // Operators are still Intrinsic
    let sum = a + b                           // Intrinsic
    let ok = a < b                            // Intrinsic
    print(sum)
    print(ok)
}

Further Reading ​


Next chapter → Runtime Extensions (Dynamic Host Plugins)

See also → docs/adr/architecture-decisions.md · plan/topics/hostfn-extension.md · Chapter 26, Memory Management

SYX · Apache-2.0