struct Aa { mut: val int nums []int } struct Bb { mut: a Aa } struct Cu { mut: b Bb nums []int aarr []Aa num int } struct Lol { b []string @[json: lol] c string @[json: cc] d int } struct User { name string mut: age int } struct Foo { typ string } struct Empty { } // We need to make sure that this compiles with all the reserved names. struct ReservedKeywords { delete int exit int unix int error int malloc int calloc int free int panic int auto int char int do int double int extern int float int inline int long int register int restrict int short int signed int typedef int unsigned int void int while int } fn test_empty_struct() { d := &Empty{} d2 := Empty{} println('&empty:') println(d) // != voidptr(0) println('empty:') println(d2) // empty struct print println(sizeof(Empty)) // == 0 } fn test_struct_levels() { mut c := Cu{} println(c.nums.len) assert c.nums.len == 0 c.nums << 3 assert c.nums.len == 1 assert c.nums[0] == 3 c.nums[0] = 4 assert c.nums[0] == 4 c.b.a.val = 34 assert c.b.a.val == 34 c.b.a.nums = [0].repeat(0) c.b.a.nums << 0 c.b.a.nums << 2 assert c.b.a.nums.len == 2 assert c.b.a.nums[0] == 0 assert c.b.a.nums[1] == 2 c.b.a.nums[0] = 7 assert c.b.a.nums[0] == 7 c.aarr << Aa{ val: 8 } assert c.aarr.len == 1 assert c.aarr[0].val == 8 c.num = 20 assert c.num == 20 c.aarr[0].val = 10 assert c.aarr[0].val == 10 } fn test_struct_str() { u := User{'Bob', 30} println(u) // make sure the struct is printable // assert u.str() == '{name:"Bob", age:30}' // QTODO } fn test_at() { foo := Foo{ typ: 'test' } // type: 'test' println(foo.typ) } fn test_reserved_keywords() { // Make sure we can initialize them correctly using full syntax. rk_holder := ReservedKeywords{0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3} // Test a few as it'll take too long to test all. If it's initialized // correctly, other fields are also probably valid. assert rk_holder.unix == 5 assert rk_holder.while == 3 rk_holder2 := ReservedKeywords{ inline: 9 } // Make sure partial initialization works too. assert rk_holder2.inline == 9 assert rk_holder2.while == 0 // Zero value as not specified. } struct User2 { mut: name string } fn test_mutable_fields() { mut u := User2{} u.name = 'Peter' assert u.name == 'Peter' } struct Def { a int b int = 7 } fn test_default_vals() { d := Def{} assert d.a == 0 assert d.b == 7 d2 := Def{10, 20} assert d2.a == 10 assert d2.b == 20 } fn test_assoc_with_vars() { def2 := Def{ a: 12 } mut merged := Def{ ...def2 a: 42 } assert merged.a == 42 assert merged.b == 7 merged = Def{ ...def2 b: 9 } assert merged == Def{12, 9} def3 := &Def{100, 200} merged1 := Def{ ...(*def3) } merged2 := &Def{ ...(*def3) } assert merged1.a == 100 assert merged1.b == 200 assert merged2.a == 100 assert merged2.b == 200 } const const_def = Def{ a: 100 } fn test_assoc_with_constants() { println(1) /* TODO: merged := { const_def | a: 42 } assert merged.a == 42 assert merged.b == 7 again := { const_def | b: 22 } assert again.a == 100 assert again.b == 22 */ } struct AttrTest { a int // private immutable (default) mut: b int // private mutable c int // (you can list multiple fields with the same access modifier) pub: d int // public immutable (readonly) pub mut: e int // public, but mutable only in parent module f int // public and mutable both inside and outside parent module } fn fooo() { _ := AttrTest{1, 2, 3, 4, 5, 6} } /* @[typedef] pub struct C.fixed { points [10]C.point } @[typedef] pub struct C.point { x int y int } fn test_fixed_field() { f := &C.fixed{} p := f.points[0] //f.nums[0] = 10 //println(f.nums[0]) println(p.x) //nums: [10]int //} } */ struct C.issue24102_child { x int } struct C.issue24102_parent { count int Child C.issue24102_child } fn test_plain_c_struct_definition_with_nested_selector_and_str() { parent := C.issue24102_parent{ count: 3 Child: C.issue24102_child{ x: 7 } } assert parent.count == 3 assert parent.Child.x == 7 rendered := '${parent}' assert rendered.contains('count: 3') assert rendered.contains('Child:') assert rendered.contains('x: 7') } @[params] struct Config { mut: n int def int = 10 } fn foo_config(def int, c Config) { assert c.def == def } fn bar_config(c Config, def int) { assert c.def == def } fn foo_user(u User) {} fn foo_mut_user(mut u User) { u.age++ } fn test_struct_literal_args() { foo_config(20, n: 10 def: 20 ) foo_config(10) foo_config(10, n: 40) foo_config(40, n: 30, def: 40) bar_config(Config{}, 10) bar_config(Config{ def: 4 }, 4) foo_user(name: 'Peter') foo_user(name: 'Peter') foo_user(age: 7) foo_user(name: 'Stew', age: 50) mut user := User{'Stew', 50} foo_mut_user(mut user) assert user.age == 51 } struct City { name string population int } struct Country { name string capital City } fn test_levels() { _ := Country{ name: 'UK' capital: City{ name: 'London' population: 10 } } } // Struct where an initialized field is after a non-initialized field. struct StructWithDefaultValues1 { field_uninitialized int field_initialized int = 5 } // Struct where an initialized field is before a non-initialized field. struct StructWithDefaultValues2 { field_initialized int = 3 field_uninitialized int } // Struct where an initialized field is before several non-initialized fields. struct StructWithDefaultValues3 { field_initialized int = 2 field_uninitialized int field_uninitialized_too int } fn test_struct_with_default_values_init() { s1 := StructWithDefaultValues1{ field_uninitialized: 5 } s2 := StructWithDefaultValues2{ field_uninitialized: 5 } // Partially initialized s3 := StructWithDefaultValues3{ field_uninitialized: 5 } assert s1.field_initialized == 5 assert s2.field_initialized == 3 assert s3.field_initialized == 2 } fn test_struct_with_default_values_no_init() { // Don't inititialize s1 := StructWithDefaultValues1{} s2 := StructWithDefaultValues2{} s3 := StructWithDefaultValues3{} assert s1.field_initialized == 5 assert s2.field_initialized == 3 assert s3.field_initialized == 2 } struct FieldsWithOptionVoidReturnType { f fn () ! @[required] g fn () ? @[required] } fn test_fields_anon_fn_with_option_void_return_type() { foo := FieldsWithOptionVoidReturnType{ f: fn () ! { return error('oops') } g: fn () ? { return } } foo.f() or { assert err.msg() == 'oops' } foo.g() or { assert false } } struct Commands { show []fn () string } fn a() string { return 'HELLOW' } fn b() string { return 'WOLLEH' } fn test_fields_array_of_fn() { commands := Commands{ show: [a, b] } println(commands.show) assert '${commands.show}' == '[fn () string, fn () string]' } fn test_struct_update() { c := Country{ name: 'test' } c2 := Country{ ...c capital: City{ name: 'city' } } assert c2.capital.name == 'city' assert c2.name == 'test' } // Test anon structs struct Book { x Foo author struct { name string age int } title string } fn test_anon() { empty_book := Book{} assert empty_book.author.age == 0 assert empty_book.author.name == '' println(empty_book.author.age) book := Book{ author: struct {'Peter Brown', 23} } assert book.author.name == 'Peter Brown' assert book.author.age == 23 println(book.author.name) book2 := Book{ author: struct { name: 'Samantha Black' age: 24 } } assert book2.author.name == 'Samantha Black' assert book2.author.age == 24 println(book2.author.name) } fn test_anon_auto_stringify() { b := Book{} s := b.str() assert s.contains('author: ') assert s.contains('name: ') assert s.contains('age: 0') }