// this file is just to test the scanner & parser so there may // be a bunch of stuff in here that does not really make sense /* multi line comment */ /*// nested comment a */ /* // nested comment b */ /*/* nested comment c */*/ [has_globals] module main import mod_a import mod_b.submod_a import mod_c { sym_a, TypeA, TypeB[T] } #include #flag -L lib_a __global ( global_a string global_b = 'global_b_value' ) const ( const_a = 1 const_b = 'two' ) // we don't want this parsed as `TypeA[unsafe]` __global global_before_fn_with_attr_a TypeA [unsafe] pub fn fn_with_attr_after_global_a() {} type AliasA = int type SumTypeA = StructA | int | string | []string pub type OptionalA = ?int pub type DatabasePool[T] = fn (tid int) T pub type C.BOOL = bool // we don't want this to be parsed as: // `type FnA = fn() fn...` type FnA = fn() fn fn_after_type_fn_a() int {} // we don't want this to be parsed as: // `type FnA = fn() ?fn...` type FnB = fn() ? fn fn_after_type_fn_b() int {} pub const const_array_followed_by_attribute_a = ['a', 'b'] [attribute_after_array_init] fn fn_with_attribute_after_array_init() { println('v') } [attribute_a] @[attribute_b] enum EnumA { value_a [json: 'ValueA'] value_b @[json: 'ValueB'] // NOTE: will not work with old attribute syntax due to ambiguity value_c = 2 @[json: 'ValueC'] } enum EnumB as u16 { value_a value_b } [attribute_a: 'attribute_a_val'; attribute_b] @[attribute_c: 'attribute_c_val'] @[attribute_d] ['/product/edit'; post] struct StructA { field_a int field_b string field_c fn(int) int field_d string = 'foo' field_e int = 1 + 2 + (4*4) // NOTE: will not work with old attribute syntax due to ambiguity field_f string = 'bar' @[attribute_a; attribute_b] field_g int = 111 @[attribute_a; attribute_b] field_h int = field_h_default() @[attribute_a] } fn StructA.static_method_a() int { return 1 } // TODO: modifiers struct StructB { StructA // embedded mut: field_a int [attribute_a: 'value_a'] field_b string @[attribute_b: 'value_b'] field_c struct { field_a string field_b int = 1 } } struct StructC { StructA foo.StructA mut: // TODO: modifiers field_a int field_b string } struct StructD { field_a shared int field_b shared []int = [0] } struct StructD { field_a ?&StructD } struct C.StructA {} interface InterfaceA { field_a string method_a() string method_b(string) string } // TODO: modifiers interface InterfaceB { InterfaceA // embedded mut: method_a(string) string } interface InterfaceGenericA[T] { field_a T } fn C.external_fn_a(arg_a int) int __global total_m = 0 [unsafe] fn fn_with_comment_and_attribute_a() {} [attribute_a: 'attribute_a_val'; attribute_b] [attribute_c: 'attribute_c_val'] [attribute_d] fn fn_a(arg_a string, arg_b int) int { println('fn_a($arg_a, $arg_b)') return 1 } // TODO: error on missing name/type // fn fn_b(arg_a string, arg_b, arg_c, arg_d int) int { fn fn_b(arg_a string, arg_b int, arg_c int, arg_d int) int { println('fn_b($arg_a, $arg_b, $arg_c, $arg_d)') return 1 } fn fn_c(arg_a [][]StructA, arg_b [4]StructA) [][]StructA { println('fn_b($arg_a, $arg_b)') return arg_a } fn fn_d(arg_a GenericStructA[int], arg_b moda.GenericStructA[int]) { println('fn_d($arg_a, $arg_b)') } fn C.fn_d(GenericStructA[int], moda.GenericStructA[int]) fn fn_optional_a() ?int { return 1 } fn fn_optional_b() ?int { return fn_optional_a()? } fn fn_optional_c() ?&StructD { a := StructD{ field_a: &StructD{} } dump(a.field_a) dump(a.field_a?.field_a) assert a.field_a?.field_a == none return a.field_a? } fn fn_opt_c() ?int { return fn_optional_a()! } fn fn_result_a() ! { return 1 } fn fn_result_b() !int { return 1 } fn fn_multi_return_a() (int, int) { return 1,2 } fn fn_multi_return_optional_a() ?(int, int) { return 1,2 } fn fn_variadic_a(arg_a int, arg_b ...string) { fn_variadic_b(...arg_b) fn_variadic_b(...['a', 'b', 'c', 'd']) } fn fn_variadic_b(arg_a ...string) { println(arg_a) } fn fn_arg_struct_int_a(arg_a StructA, arg_b int) { println(arg_a) } fn (rec &StructA) method_a(arg_a string, arg_b int) int { println('StructA.method_a($arg_a, $arg_b)') return 1 } // TODO: operator overload (last missing parser feature, I think :D) pub fn (a StructA) == (b StructA) bool { return a.field_a == b.field_a } fn channel_test(arg_a chan string) { ch := chan int{cap: 20} ch <- 111 rec := <-ch } fn spawn_test() { t := spawn fn() { for i in 0..100 { println('$i...') } }() t.wait() } fn fn_result_a() !int { array_a := [1,2,3,4] return array_a[0]! } fn main_a() { a := 1 b, c := 1, 2 array_init_a := [1,2,3,4] array_init_b := [1,2,3,4]! array_init_c := [array_init_a] array_init_d := []string{len: 2, cap: 2} array_init_e := [][]string{} array_init_f := [2][]int{init:[1]} array_init_g := [2][][][][]int{} array_init_h := [2][][][][2]int{} // TODO: better error for missing `]` // array_init_i := [['a','b','c','d'] array_init_i := [['a','b','c','d']] array_init_j := []&StructA{} array_init_k := [fn(arg_a int) int { return 1 }] array_init_i := [fn() int { return 1 }()] array_init_thread_a := []thread int{cap: 16} expr_a expr_b // TODO: error ? expr_a; expr_b // TODO: error map_init_long_string_string := map[string]string{} map_init_long_string_array_string := map[string][]string{} mut map_init_short_string_string := {'key_a': 'value_a'} map_init_short_string_string = {} // test empty map_init_short_string_array_string := {'key_a': ['value_a', 'value_b']} map_init_short_ident_string := {key_a: 'value_a'} // unsupported key type mut map_init_short_enum_value_init_expr := map[EnumA]StructA{} // make sure we don't chain `StructA{field_a: 1}.value_b` as SelectorExpr map_init_short_enum_value_init_expr = { .value_a: StructA{ field_a: 1 } .value_b: StructA{ field_a: 1 } .value_c: StructA{ field_a: 1 } } struct_init_a := StructA{field_a: 1, field_b: 'v'} struct_init_b := foo.StructA{field_a: 1, field_b: 'v'} struct_init_c := StructA{1, 'v'} // NOTE: no longer supported. will error // assoc_old_a := {struct_a|field_a: 111} // assoc_old_b := { // ...struct_a // field_a: 1 // } assoc_current_a := StructA{ ...struct_a // field_a: 1 } string_literal_v_a := 'string literal a' string_literal_v_b := "string literal b" string_literal_c_a := c'c string literal a' string_literal_raw_a := r'string $literal raw a' thred_init_a := thread int{cap: 20} call_a := fn_a('string', 1) call_b := fn_b('string', 1, a, b) call_c := array_init_g[0](1) call_d := struct_a.method_a('string', 1) call_e := struct_a.field_c(1) call_f := array_init_k[0]() call_g := array_init_k[fn() { return 0 }()]() call_h := array_init_k[array_init_b[0]]() call_config_syntax_a := fn_arg_struct_int_a(field_a: 1, field_b: 'b', 2) call_lambda_expr_a := array_init_a.sorted(|x,y| x > y) call_lambda_expr_b := f(|| 1) call_selector_a := 'hello v world' .split(' v ') .join(' ') call_comptime_a := $fn_a('string', 1) // comptime call as expr stmt only $fn_a('string', 1) $compile_warn('compile warn') cast_a := u8(1) cast_b := &[]u8([1,2,3,4]) // the following casts should error later about not being // able to cast array types, unless it gets implemented. cast_c := []u8([1,2,3,4]) cast_d := [][][]u8([[[1,2,3,4]]]) cast_d := ?&?int(a) fn_literal_a := fn(param_a int, param_b int) int { return param_a+param_b } fn_literal_call_a := fn_literal_a(2, 4) fn_literal_direct_call_a := fn(param_a int, param_b int) int { return param_a+param_b }(2, 4) fn_literal_capturing_vars_a := fn [infix_a, infix_b] (param_a int, param_b int) int { return (infix_a+infix_b)*(param_a+param_b) } fn_literal_capturing_vars_direct_call_a := fn [infix_a, infix_b] (param_a int, param_b int) int { return (infix_a+infix_b)*(param_a+param_b) }(2, 4) index_a := array_init_a[0] index_a := array_init_a[a] index_b := struct_a.field_b[1] index_c := [StructA{}][0] // direct index after init index_d := [[1,2,3,4]][0][1] // unlimited chaining (add more examples) index_e := [fn() []StructA { return [fn() []StructA { return [StructA{}] }()][0] }()[0]][0] // more chaining index_f := fn() []string { return ['a', 'b'] }()[0] index_g := array_init_e[0] or { ['e', 'f'] }[0] index_range_a := array_init_a[0..2] index_range_b := array_init_a[2..] index_range_c := array_init_a[..2] index_range_d := array_init_a[1+2..1+2] index_range_e := array_init_a[1+2..] index_range_f := array_init_a[..1+2] index_range_g := array_init_a[1+2...1+2] index_range_h := array_init_a[1+2...] index_range_i := array_init_a[...1+2] index_range_j := [[1,2,3,4]][0][2..4] index_range_k := [[1,2,3,4]][0][2...4] index_or_a := array_init_a[0] or { 1 } index_or_b := array_init_c[0] or { [5,6,7,8] }[0] index_or_c := fn() []int { return [array_init_a[0] or { 1 }] }()[0] or { 1 } index_or_d := match index_a { int { array_init_a } else { [5,6,7,8] } }[0] or { 1 } infix_a := 1 * 2 infix_b := 1 + 2 * 3 / 4 + 5 infix_c := infix_a * 4 * 2 + 11 / 2 infix_d := a == b && c == d infix_and_paren_expr_a := ((((infix_b + 1) * 2) + 111) * 2) / 2 infix_and_paren_expr_b := (((((x * array_init_a[0] + array_init_a[1]) * x + array_init_a[2]) * x + array_init_a[3]) * x + array_init_a[4]) * x + array_init_a[5]) * x + array_init_a[6] prefix_a := &StructA{} prefix_b := &&StructA{} prefix_c := -infix_a + 2 prefix_optional_a := ?mod_a.StructA{} prefix_optional_b := ?mod_a.StructA(none) assert a == 1 assert a == 1, 'a does not equal 1' assert c <= 2, 'c is greater than 2' if val := array_init_a[0] { println(val) } if res_a := fn_optional_a() { println('if guard: $res_a') } if res_a, res_b := fn_multi_return_optional_a() { println('if guard: $res_a, $res_b') } if res_a, res_b := fn_optional_a(), fn_optional_b() { println('if guard: ${res_a}, ${res_b}') } if err == IError(MyError{}) { println('err == IError(MyError{})') } if struct_init_a == (StructA{}) { println('struct_init_a == (StructA{})') } // TODO: tricky // if struct_init_a == StructA{} { // println('struct_init_a == StructA{}') // } // if StructA{} == StructA{} { // println('StructA{} == StructA{}') // } // if struct_init_a is StructA { // println(1) // } if struct_init_a is []StructA { println(1) } if a == 1 { println('1 a == $s') } else if a == 2 { println('2 a == $s') } else { println('a == $s') } if (if a > 0 { 1 } else { 2 }) < 2 { println('if expr in if cond < 2') } if a > 0 { StructA{} } else { StructB{} }.method_a() $if linux { println('linux') } $else $if windows { println('windows') } $else { println('other') } $if option_a ? { println('custom option: `v -d option_a`') } $if T is $array { println('T is array') } $else $if T is $struct { println('T is struct') } $if T in [?int, ?int] { println('option int') } for val_a in array_init_a { println(val_a) } // TODO: error (unless first 2 are allowed? 0..10 and 0..infinity) // the third one definitely needs to error // for val_a in ..10 {} // for val_a in 0.. {} // for val_a in .. {} for val_a in 0..10 { println(val_a) } for key_a, val_a in array_init_a { println(key_a) println(val_a) } for key_a, mut val_a in array_init_a { println(key_a) println(val_a) } for idx_a in 0 .. a + 1 { println(idx_a) } for key, value in { 'a': 'apple' 'b': 'bananna' } { println('${key}: ${value}') } for mut left_node is ast.InfixExpr { if left_node.op == .and && mut left_node.right is ast.InfixExpr { if left_node.right.op == .key_is { println('xx') } } } for a:=0; a<=100; a++ { println(a) } for mut a:=0; a<=100; { a++ println(a) } for a, b := 0, 1; a < 4; a++ { println('$a - $b') } for a, b, c, d := 0, 1, 2, 3; a < 4; a++ { println('$a - $b') } // currently erroring in this case // for a := 1 {} for ; x < 100; { println(x) } for x < 100 { println(x) } for ; ; { println('infinite loop') } for { println('infinite loop') } $for x == 1 { println('comptime for') } $for field in U.fields { // TODO: parser needs to handle // currently just skipping past if val.$(field.name).str() != 'Option(none)' { fields_len++ } } for_label_a: for i := 4; true; i++ { println(i) for { if i < 7 { continue for_label_a } else { break for_label_a } } } // fn literals // capture list & generic params fn [a, b] [T] () { println('captured vars: ${a}, ${b}') }[int]() // capture list only fn [a, b] () { println('captured vars: ${a}, ${b}') }() // generic params only fn [T] () { println(typeof(T)) }[int]() sumtype_a := SumTypeA(111) as_cast_a := sumtype_a as int // NOTE: or for as is not currently supported // I may remove it unless supported is added as_cast_b := sumtype_a as int or { println('cast error') } match sumtype_a { StructA { println('StructA') } int { println('int') } string { println('string') } []string { println('[]string') } } mut ptr_a := &voidptr(0) unsafe { *ptr_a = 0 (*ptr_a) = *ptr_a - 1 ((*ptr_a)) = *ptr_a - 1 *(ptr_a) = *ptr_a - 1 *((ptr_a)) = *ptr_a - 1 (*(ptr_a)) = *ptr_a - 1 } mut ptr_b := &voidptr(0) unsafe { *ptr_b = 0 } unsafe_a := unsafe { mut d := 1 d++ d } unsafe_a := unsafe { mut d := 1; d++; d } unsafe_b := unsafe { mut d := 1 d++ d } shared array_int_shared_a := []int{} shared array_string_shared_a := []String{} lock { array_int_shared_a << 1 array_int_shared_a << 2 } lock array_string_shared_a { array_string_shared_a << 'a' array_string_shared_a << 'b' } lock array_int_shared; rlock array_string_shared { array_int_shared << 3 println(array_string_shared[0]) } lock a,b; rlock c,d; lock e,f; rlock g,h { println('silly lock test') } fn_a('string', unsafe {*ptr_a}) { block_test_a := 1 } ch_a := chan int{} _ = <-ch_a or { println('channel closed') } select { a := <-ch_a b := <-ch_a { b+=2 } c := <-ch_a or { panic('channel closed') } 500 * time.millisecond { eprintln('> more than 0.5s passed without a channel being ready') } } __asm { ldrex tmp, [addr] strex tmp, value, [addr] } sql := 'test_ident_named_sql' db_a := sqlite.connect('db_a') or { panic('could not connect to db: ${err}') } nr_items := sql db { select count from items } users := sql db { select from User where name == 'first${user_suffix}' } // TODO: REMOVE BELOW - TEMP TESTING OR MOVE TO APPROPRIATE PLACE ABOVE x.member.free() x.member.submember1.free() x.member.submember1.submember2.free() x.y = cmdline.option(current_args, arg, '10').int() x.y = cmdline.option(current_args, arg, '10').int() assert 'href="${url('/test')}"' == 'href="/test.html"' assert '"${show_info('abc')}"' == '"abc"' // TODO: confirm there are no cases where // there is ambiguity with `|` infix expr // lines_indents := lines // .filter(|line| !line.is_blank())`` // .map(|line| line.indent_width()) // TODO: for mut x is MyType { println(x) } ms := t.swatches[name].elapsed().microseconds() if !v.pref.is_bare && v.pref.build_mode != .build_module && v.pref.os in [.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] { } rng.shuffle[T](mut res, config_)! link_cmd := '${call(it.replace('.c', '.o')).join(' ')}' }