Files
sx/examples/modules/std.sx
2026-02-09 18:07:41 +02:00

221 lines
6.5 KiB
Plaintext

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, "]");
}
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 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);
}