so... jai :D

This commit is contained in:
agra
2026-02-04 01:34:30 +02:00
commit 55fc5790e4
60 changed files with 15876 additions and 0 deletions

5
examples/01-basic.sx Normal file
View File

@@ -0,0 +1,5 @@
#import "modules/std.sx";
main :: () -> s32 {
if false then 40 else 42;
}

4
examples/02-stdout.sx Normal file
View File

@@ -0,0 +1,4 @@
#import "modules/std.sx";
main :: () {
print("Hello\n");
}

22
examples/03-structs.sx Normal file
View File

@@ -0,0 +1,22 @@
#import "modules/std.sx";
Vec4 :: struct {
x, y, z, w: f32;
}
main :: () {
v1 : Vec4 = .{ 1, 2, 3, 0};
v2 := Vec4.{ 4, 1, 1, 3};
v3 := Vec4.{ w=0, x=2, y=3, z=4};
z := 5.0; // z is f32
w := 6.0; // w is f32
v4 := Vec4.{ y=3, x=9, w, z};
v4.y = 0;
print("v1: {}\nv2: {}\nv3: {}\nv4: {}\n", v1, v2, v3, v4);
}
// ** stdout **
//v1: Vec4{x:1.0, y:2.0, z:3.0, w:0.0}
//v2: Vec4{x:4.0, y:1.0, z:1.0, w:3.0}
//v3: Vec4{x:2.0, y:3.0, z:4.0, w:0.0}
//v4: Vec4{x:9.0, y:3.0, z:5.0, w:6.0}

20
examples/04-shadow.sx Normal file
View File

@@ -0,0 +1,20 @@
#import "modules/std.sx";
main :: () -> s32 {
x := 42;
{
print("scope opened\n");
defer print("scope closed\n");
// define a inner variable x shadowing the one define in the outer scope(s)
x:= 6;
print("scoped x: {}\n", x); //expect 6
}
print("main x: {}\n", x); //expect 42
}
// ** stdout **
// scope opened
// scoped x: 6
// scope closed
// main x: 42
//

20
examples/05-run.sx Normal file
View File

@@ -0,0 +1,20 @@
#import "modules/std.sx";
// this will bake x to be 7 as a global constant
x :: #run compute(5);
compute :: (v: s32) -> s32 => v + 2;
main :: () {
//test
y :: #run compute(7);
c :: 2;
print("hello {}\n", x + y * c);
}
#run main();
// ** stdout after build **
// hello 25
// ** stdout after run **
// hello 25

17
examples/06-generic.sx Normal file
View File

@@ -0,0 +1,17 @@
#import "modules/std.sx";
sum :: (a:$T, b:T) -> T {
return a + b;
}
main :: () {
x:=sum(2,3);
print("sum: {}\n", x);
print("sum: {}\n", sum(40,2));
print("sum: {}\n", sum(40,2.5));
}
// ** stdout **
// sum: 42
// sum: 42.500000
//

11
examples/07-defer.sx Normal file
View File

@@ -0,0 +1,11 @@
#import "modules/std.sx";
main :: () -> s32 {
defer print("still here\n");
return 42;
}
// ** exit code **
// 42
// ** stdout **
// still here
//

43
examples/08-types.sx Normal file
View File

@@ -0,0 +1,43 @@
#import "modules/std.sx";
SPECIAL_VALUE :u8: 42;
resolve :: (x: u8) -> s32 {
return 12 + x;
}
Foo :: struct {
a : u2; // this will have 0 as default
b : u8 = SPECIAL_VALUE;
c : u8 = ---; // default for c is undefined
d : u8 = #run xx resolve(5); // converts s32 to u8
}
main :: () {
a : Foo; // default value of 0
print("a 0 : {}\n", a);
a.a = 1;
// a.c is still undefined at this point
a.c = 8;
print("a 1 : {}\n", a);
large: f64 = 5989.5;
b : Foo = ---; // undefined
b.a = 1;
b.c = xx large; // converts f64 to u8
// expect stdout : "b: Foo{a:1, b: 42, c: 7, d: 12}"
print("b: {}", b);
print("\n");
f := Pack.{1,0,3,5,9,100,3.5};
print("{}\n", f);
}
Pack :: struct {
a: u1;
b: u2;
c: u8;
d: u32;
f: u64;
v: s32;
x: f32;
}

16
examples/09-import.sx Normal file
View File

@@ -0,0 +1,16 @@
std :: #import "modules/std.sx";
//flat
#import "modules/math.sx";
main :: () -> s32 {
{
defer std.print("after hello");
//expect stdout : hello there
std.print("hello there");
}
v:= std.Vector(3,f32).[1,2,3];
std.print("\n{}\n", v);
}

View File

@@ -0,0 +1,91 @@
#import "modules/std.sx";
Vec :: struct($N: u32, $T:Type) {
// <N x T> (LLVM Vector)
// Vector is a Builtin Type
data: Vector(N,T);
}
Complex :: ($T:Type) -> Type {
return struct {
value: T;
//..inject
count: u32;
};
}
Vec3 :: Vec(3, f32);
vec3 :: (x:f32, y:f32, z:f32) -> Vector(3,f32) {
.[x, y, z];
}
Foo :: Complex(u32);
main :: () {
v1 := Vec3.{data = .[1,3,2]};
print("v1: {}\n", v1);
//stdout: Vec(3,f32){data: [1.0, 3.0, 2.0]}
//
v2 := vec3(1,3,2);
print("v2: {}\n", v2);
//stdout: [1.0, 3.0, 2.0]
//
// [N x T] (LLVM Array)
buffer : [5]f32 = .[0, 2, 3.5, 4, 0];
print("buff: {}\n", buffer);
//stdout: [0.0, 2.0, 3.5, 4.0, 0.0]
//
comp : Foo = .{value = 42, count = 1};
print("comp: {}\n", comp);
//stdout: Foo{value: 42, count: 1}
//
// Vector arithmetic
v3 := vec3(3,2,1);
add := v2 + v3;
print("add: {}\n", add);
// Element access
v2x := v2.x;
print("v2.x: {}\n", v2x);
// Index access
v2i := v2[1];
print("v2[1]: {}\n", v2i);
// Scalar broadcast
scaled := v2 * 2.0;
print("scaled: {}\n", scaled);
// Negation
neg := -v2;
print("neg: {}\n", neg);
// sqrt
s := sqrt(9.0);
print("sqrt(9): {}\n", s);
// inline generic type
Sx :: (user: $T) -> Type {
return union {
counter: s32;
user: T;
};
}
sx := Sx(f32).user(0.5);
print("{}\n", sx);
print("{}\n", size_of(f32));
print("{}\n", size_of(Sx(f32)));
print("{}\n", size_of(Foo));
print("{}\n", size_of(Complex));
size:= size_of(Sx);
print("{}\n", size);
}

View File

@@ -0,0 +1,28 @@
#import "modules/std.sx";
math :: #import "modules/std/math.sx";
vec3 :: (x:f32, y:f32, z:f32) -> Vector(3,f32) {
.[x, y, z];
}
main :: () {
a := vec3(1, 0, 0);
b := vec3(0, 1, 0);
// dot product
d := math.dot(a, b);
print("dot: {}\n", d);
// cross product
cr := math.cross(a, b);
print("cross: {}\n", cr);
// length
v := vec3(3, 4, 0);
len := math.length(v);
print("length: {}\n", len);
// normalize
n := math.normalize(v);
print("norm: {}\n", n);
}

12
examples/12-meta.sx Normal file
View File

@@ -0,0 +1,12 @@
#import "modules/std.sx";
#import "modules/math.sx";
main :: () {
x:Type = f64;
v:f64 = 3.2;
print("{}\n", x);
print("{}\n", v);
x= Vec4;
print("{}\n", x);
}

9
examples/13-code.sx Normal file
View File

@@ -0,0 +1,9 @@
#import "modules/std.sx";
generate::() -> string {
return "print(\"hello from the other side\n\");";
}
main :: () {
#insert #run generate();
}

15
examples/14-demo.sx Normal file
View File

@@ -0,0 +1,15 @@
std :: #import "modules/std.sx";
vec3 :: (x:f32, y:f32, z:f32) -> std.Vector(3, f32) {
.[x,y,z];
}
main :: () {
v1 := vec3(1,0,0);
v2 := vec3(0,0,1);
s := 0.5;
sum := (v1 - v2);// math.cross(v1, v2);
std.print("{}\n", sum);
}

50
examples/15-while.sx Normal file
View File

@@ -0,0 +1,50 @@
#import "modules/std.sx";
sumOf10 :: () -> s32 {
i:= 1;
s:=0;
while i <= 10 {
s+=i;
i+=1;
}
s;
}
someSum :: #run sumOf10();
main :: {
// Basic while loop: count to 5
i := 0;
while i < 5 {
i += 1;
}
print("count: {}\n", i);
// While with break
x := 1;
while x < 100 {
if x == 12 {
break;
}
x += 1;
}
print("break at: {}\n", x);
// While with continue: sum odd numbers 1-9
sum := 0;
j := 0;
while j < 10 {
j += 1;
// Skip even numbers
if j == 2 { continue; }
if j == 4 { continue; }
if j == 6 { continue; }
if j == 8 { continue; }
if j == 10 { continue; }
sum += j;
}
print("sum of odd 1-9: {}\n", sum);
print("sum {}", someSum);
}

48
examples/16-union.sx Normal file
View File

@@ -0,0 +1,48 @@
#import "modules/std.sx";
Shape :: union {
circle: f32;
rect: s32;
none;
}
main :: () {
// Construction with .variant(payload)
s :Shape = .circle(3.14);
print("circle: {}\n", s);
// Payload access
r := s.circle;
print("radius: {}\n", r);
// Void variant via enum literal
s = .none;
print("none: {}\n", s);
// Reassign with payload
s = .rect(42);
print("rect: {}\n", s);
// Explicit prefix construction
sh :Shape = Shape.circle(2.71);
print("sh: {}\n", sh);
// Field access on second union variable
sh2 :Shape = .rect(10);
val := sh2.rect;
print("rect val: {}\n", val);
// Match on union
if sh2 == {
case .circle: print("matched circle\n");
case .rect: print("matched rect\n");
case .none: print("matched none\n");
}
cs := if sh2 == {
case .circle: 1;
case .rect: 2;
case .none: 3;
}
print("case : {}", cs);
}

9
examples/17-lambda.sx Normal file
View File

@@ -0,0 +1,9 @@
#import "modules/std.sx";
main :: () {
fx :: (s:s3) -> s3 {
s;
}
print("{}\n", fx(133));
}

23
examples/18-conditions.sx Normal file
View File

@@ -0,0 +1,23 @@
#import "modules/std.sx";
main :: () {
x:= 32;
y:= 40;
if 0 <= x <= 100 and 0 <= y <= 100 {
print("contained");
}
if 0 <= x <= 100 and 0 <= y <= 100 {
print("contained");
}
if 1000 > x > -100 and 0 <= y <= 100 {
print("contained");
}
if 1000 > x >= -100 and 0 <= y <= 100 {
print("contained");
}
}

35
examples/19-varargs.sx Normal file
View File

@@ -0,0 +1,35 @@
#import "modules/std.sx";
sum :: (args: ..s32) -> s32 {
result := 0;
for args {
result = result + it;
}
result;
}
print_all :: (args: ..s32) {
for args {
write(int_to_string(it));
write(" ");
}
write("\n");
}
main :: () -> s32 {
write(int_to_string(sum(10, 20, 30)));
write("\n");
print_all(1, 2, 3, 4, 5);
arr : [3]s32 = .[10, 20, 30];
write(int_to_string(sum(..arr)));
write("\n");
for arr {
write(int_to_string(it));
write(" ");
}
write("\n");
0;
}

View File

@@ -0,0 +1,47 @@
#import "modules/std.sx";
Point :: struct {
x: s32;
y: s32;
}
// Print all arguments — accepts any type, dispatches via type-switch
print_any :: (args: ..Any) {
for args {
type := type_of(it);
if type == {
case int: write(int_to_string(cast(s32) it));
case string: write(cast(string) it);
case bool: write(bool_to_string(cast(bool) it));
case float: write(float_to_string(cast(f64) it));
case Point: {
p := cast(Point) it;
write("(");
write(int_to_string(p.x));
write(",");
write(int_to_string(p.y));
write(")");
}
}
write(" ");
}
write("\n");
}
count :: (args: ..Any) -> s32 {
args.len;
}
main :: () -> s32 {
print_any(42, "hello", true, 3.14);
// Test with struct
p := Point.{ x=10, y=20 };
print_any("point:", p, 99);
// Test count
write(int_to_string(count(1, 2, 3)));
write("\n");
0;
}

19
examples/21-categories.sx Normal file
View File

@@ -0,0 +1,19 @@
#import "modules/std.sx";
Point :: struct {
x, y: s32;
}
Color :: struct {
r, g, b: s32;
}
main :: () {
p := Point.{10, 20};
c := Color.{255, 128, 0};
print("p: {}\n", p);
print("c: {}\n", c);
print("n: {}\n", 42);
print("s: {}\n", "hello");
print("b: {}\n", true);
}

11
examples/22-anytype.sx Normal file
View File

@@ -0,0 +1,11 @@
#import "modules/std.sx";
main :: {
i := 0;
while i < 10 {
i+=1;
if i == 2 then continue;
if i == 5 then break;
}
print("{}\n", i);
}

17
examples/modules/math.sx Normal file
View File

@@ -0,0 +1,17 @@
#import "std.sx";
dot :: (a: Vector(3,f32), b: Vector(3,f32)) -> f32 {
return a.x*b.x + a.y*b.y + a.z*b.z;
}
cross :: (a: Vector(3,f32), b: Vector(3,f32)) -> Vector(3,f32) {
.[a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x];
}
length :: (v: Vector(3,f32)) -> f32 {
return sqrt(dot(v, v));
}
normalize :: (v: Vector(3,f32)) -> Vector(3,f32) {
return v / length(v);
}

220
examples/modules/std.sx Normal file
View File

@@ -0,0 +1,220 @@
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);
}

98
examples/vision.sx Normal file
View File

@@ -0,0 +1,98 @@
main :: {
// imagine a game loop
while(running) {
render_ui(build_menu);
}
}
build_menu :: (ctx: ViewContext) -> View {
// use ctx to allocate some state at the for Menu ViewContext
state : MenuState = ctx.state(MenuState);
// named args
HStack(ctx,
children = .[
Button(ctx,
label = "Up",
onTap = ctx.callback(goUp, state),
),
ScrollView(ctx,
LazyVStack(ctx,
builder = ctx.callback(build_menu_entry, state),
),
)
],
);
}
build_menu_entry :: (ctx: *ViewContext, index: s32, state: *MenuState) -> View {
entry := state.entries[index];
is_selected := index == state.selected_index;
icon := if entry.is_dir then "[D]" else " ";
Button(ctx,
label = concat(icon, " ", entry.name),
on_tap = ctx.callback(menu_go, state, index),
);
}
ViewContext :: struct {
//TBD
}
MenuState :: struct {
current_path: string;
entries: List(MenuEntry);
error_message: string;
}
MenuEntry :: struct {
name: string;
is_dir: bool;
}
menu_go_up :: (state: *MenuState) {
parent := fs.path.dirname(state.current_path) else return;
// this frees the current path & copies parent to be owned by MenuState
state.current_path = parent;
menu_refresh(state);
}
menu_go :: (state: *MenuState, s32 index) {
entry := state.entries[index] else return;
state.current_path := concat(state.current_path, "/", entry.name);
menu_refresh(state);
}
menu_refresh :: (state: *MenuState) {
// this could retain the capacity
state.entries.clear();
// this would basically create a copy of the empty string :(
state.error_message = "";
// ... multi return params vs Generic Result to deal with exceptions
// ... nullable
dir := io.Dir.open(state.current_path);
if !dir {
state.error_message = "failed to open";
return;
};
defer dir.close();
for iter.iterate() {
entries.append(.{it.name, it.kind == .Directory});
}
}
HStackState :: struct {
spacing: f32 = 8;
alignment: VerticalAlignment = .center;
padding: f32 = 0;
background: ?Color;
corner_radius: f32 = 0,
}
HStack :: (ctx: ViewContext, children: []View) -> View {
data := ctx.alloc(HStackState);
data.* = .{};
}