Vector :: ($N: int, $T: Type) -> Type #builtin; write :: (str: string) -> void #builtin; sqrt :: (x: $T) -> T #builtin; size_of :: ($T: Type) -> s32 #builtin; alloc :: (size: s32) -> string #builtin; type_of :: (val: $T) -> Type #builtin; type_name :: ($T: Type) -> string #builtin; field_count :: ($T: Type) -> s32 #builtin; field_name :: ($T: Type, idx: s32) -> string #builtin; field_value :: (s: $T, idx: s32) -> Any #builtin; int_to_string :: (n: s32) -> string { if n == 0 { return "0"; } neg := n < 0; v := if neg then 0 - n else n; tmp := v; len := 0; while tmp > 0 { len += 1; tmp = tmp / 10; } total := if neg then len + 1 else len; buf := alloc(total); i := total - 1; while v > 0 { buf[i] = (v % 10) + 48; v = v / 10; i -= 1; } if neg { buf[0] = 45; } buf; } bool_to_string :: (b: bool) -> string { if b then "true" else "false"; } float_to_string :: (f: f64) -> string { neg := f < 0.0; v := if neg then 0.0 - f else f; int_part := cast(s32) v; frac := cast(s32) ((v - cast(f64) int_part) * 1000000.0); if frac < 0 { frac = 0 - frac; } istr := int_to_string(int_part); fstr := int_to_string(frac); il := istr.len; fl := fstr.len; prefix := if neg then 1 else 0; total := prefix + il + 1 + 6; buf := alloc(total); pos := 0; if neg { buf[0] = 45; pos = 1; } i := 0; while i < il { buf[pos] = istr[i]; pos += 1; i += 1; } buf[pos] = 46; pos += 1; pad := 6 - fl; j := 0; while j < pad { buf[pos] = 48; pos += 1; j += 1; } k := 0; while k < fl { buf[pos] = fstr[k]; pos += 1; k += 1; } buf; } concat :: (a: string, b: string) -> string { al := a.len; bl := b.len; buf := alloc(al + bl); i := 0; while i < al { buf[i] = a[i]; i += 1; } j := 0; while j < bl { buf[al + j] = b[j]; j += 1; } buf; } substr :: (s: string, start: s32, len: s32) -> string { buf := alloc(len); i := 0; while i < len { buf[i] = s[start + i]; i += 1; } buf; } struct_to_string :: (s: $T) -> string { result := concat(type_name(T), "{"); i := 0; while i < field_count(T) { if i > 0 { result = concat(result, ", "); } result = concat(result, field_name(T, i)); result = concat(result, ": "); result = concat(result, any_to_string(field_value(s, i))); i += 1; } concat(result, "}"); } enum_to_string :: (e: $T) -> string { concat(".", field_name(T, cast(s32) e)); } vector_to_string :: (v: $T) -> string { result := "["; i := 0; while i < field_count(T) { if i > 0 { result = concat(result, ", "); } result = concat(result, any_to_string(field_value(v, i))); i += 1; } concat(result, "]"); } array_to_string :: (a: $T) -> string { result := "["; i := 0; while i < field_count(T) { if i > 0 { result = concat(result, ", "); } result = concat(result, any_to_string(field_value(a, i))); i += 1; } concat(result, "]"); } slice_to_string :: (items: []$T) -> string { result := "["; i := 0; while i < items.len { if i > 0 { result = concat(result, ", "); } result = concat(result, any_to_string(field_value(items, i))); i += 1; } concat(result, "]"); } union_to_string :: (u: $T) -> string { tag := cast(s32) u; result := concat(".", field_name(T, tag)); payload := field_value(u, tag); pstr := any_to_string(payload); if pstr.len > 0 { result = concat(result, concat("(", concat(pstr, ")"))); } result; } any_to_string :: (val: Any) -> string { result := ""; type := type_of(val); if type == { case void: result = ""; case int: result = int_to_string(xx val); case string: { s : string = xx val; result = s; } case bool: result = bool_to_string(xx val); case float: result = float_to_string(xx val); case struct: result = struct_to_string(cast(type) val); case enum: result = enum_to_string(cast(type) val); case vector: result = vector_to_string(cast(type) val); case array: result = array_to_string(cast(type) val); case slice: result = slice_to_string(cast(type) val); case union: result = union_to_string(cast(type) val); } result; } build_print :: (fmt: string) -> string { code := "result := \"\"; "; seg_start := 0; i := 0; arg_idx := 0; while i < fmt.len { if fmt[i] == 123 { if i + 1 < fmt.len { if fmt[i + 1] == 125 { if i > seg_start { code = concat(code, "result = concat(result, substr(fmt, "); code = concat(code, int_to_string(seg_start)); code = concat(code, ", "); code = concat(code, int_to_string(i - seg_start)); code = concat(code, ")); "); } code = concat(code, "result = concat(result, any_to_string(args["); code = concat(code, int_to_string(arg_idx)); code = concat(code, "])); "); arg_idx += 1; i += 2; seg_start = i; } else if fmt[i + 1] == 123 { code = concat(code, "result = concat(result, substr(fmt, "); code = concat(code, int_to_string(seg_start)); code = concat(code, ", "); code = concat(code, int_to_string(i - seg_start + 1)); code = concat(code, ")); "); i += 2; seg_start = i; } else { i += 1; } } else { i += 1; } } else if fmt[i] == 125 { if i + 1 < fmt.len { if fmt[i + 1] == 125 { code = concat(code, "result = concat(result, substr(fmt, "); code = concat(code, int_to_string(seg_start)); code = concat(code, ", "); code = concat(code, int_to_string(i - seg_start + 1)); code = concat(code, ")); "); i += 2; seg_start = i; } else { i += 1; } } else { i += 1; } } else { i += 1; } } if seg_start < fmt.len { code = concat(code, "result = concat(result, substr(fmt, "); code = concat(code, int_to_string(seg_start)); code = concat(code, ", "); code = concat(code, int_to_string(fmt.len - seg_start)); code = concat(code, ")); "); } code = concat(code, "write(result);"); code; } print :: ($fmt: string, args: ..Any) { #insert build_print(fmt); }