v / vlib / v2 / tests / syntax.v_
670 lines · 612 sloc · 15.07 KB · 2332ecff4811b8c97dfda8e825170e9397962519
Raw
1// this file is just to test the scanner & parser so there may
2// be a bunch of stuff in here that does not really make sense
3/* multi
4 line
5 comment */
6/*// nested comment a */
7/* // nested comment b */
8/*/* nested comment c */*/
9[has_globals]
10module main
11
12import mod_a
13import mod_b.submod_a
14import mod_c { sym_a, TypeA, TypeB[T] }
15
16#include <header_a.h>
17#flag -L lib_a
18__global (
19 global_a string
20 global_b = 'global_b_value'
21)
22
23const (
24 const_a = 1
25 const_b = 'two'
26)
27// we don't want this parsed as `TypeA[unsafe]`
28__global global_before_fn_with_attr_a TypeA
29
30[unsafe]
31pub fn fn_with_attr_after_global_a() {}
32
33type AliasA = int
34type SumTypeA = StructA | int | string | []string
35
36pub type OptionalA = ?int
37
38pub type DatabasePool[T] = fn (tid int) T
39
40pub type C.BOOL = bool
41
42// we don't want this to be parsed as:
43// `type FnA = fn() fn...`
44type FnA = fn()
45fn fn_after_type_fn_a() int {}
46// we don't want this to be parsed as:
47// `type FnA = fn() ?fn...`
48type FnB = fn() ?
49fn fn_after_type_fn_b() int {}
50
51pub const const_array_followed_by_attribute_a = ['a', 'b']
52[attribute_after_array_init]
53fn fn_with_attribute_after_array_init() { println('v') }
54
55[attribute_a]
56@[attribute_b]
57enum EnumA {
58 value_a [json: 'ValueA']
59 value_b @[json: 'ValueB']
60 // NOTE: will not work with old attribute syntax due to ambiguity
61 value_c = 2 @[json: 'ValueC']
62}
63
64enum EnumB as u16 {
65 value_a
66 value_b
67}
68
69[attribute_a: 'attribute_a_val'; attribute_b]
70@[attribute_c: 'attribute_c_val']
71@[attribute_d]
72['/product/edit'; post]
73struct StructA {
74 field_a int
75 field_b string
76 field_c fn(int) int
77 field_d string = 'foo'
78 field_e int = 1 + 2 + (4*4)
79 // NOTE: will not work with old attribute syntax due to ambiguity
80 field_f string = 'bar' @[attribute_a; attribute_b]
81 field_g int = 111 @[attribute_a; attribute_b]
82 field_h int = field_h_default() @[attribute_a]
83}
84
85fn StructA.static_method_a() int {
86 return 1
87}
88
89// TODO: modifiers
90struct StructB {
91 StructA // embedded
92mut:
93 field_a int [attribute_a: 'value_a']
94 field_b string @[attribute_b: 'value_b']
95 field_c struct {
96 field_a string
97 field_b int = 1
98 }
99}
100
101struct StructC {
102 StructA
103 foo.StructA
104mut: // TODO: modifiers
105 field_a int
106 field_b string
107}
108
109struct StructD {
110 field_a shared int
111 field_b shared []int = [0]
112}
113
114struct StructD {
115 field_a ?&StructD
116}
117
118struct C.StructA {}
119
120interface InterfaceA {
121 field_a string
122 method_a() string
123 method_b(string) string
124}
125
126// TODO: modifiers
127interface InterfaceB {
128 InterfaceA // embedded
129mut:
130 method_a(string) string
131}
132
133interface InterfaceGenericA[T] {
134 field_a T
135}
136
137fn C.external_fn_a(arg_a int) int
138
139__global total_m = 0
140[unsafe]
141fn fn_with_comment_and_attribute_a() {}
142
143[attribute_a: 'attribute_a_val'; attribute_b]
144[attribute_c: 'attribute_c_val']
145[attribute_d]
146fn fn_a(arg_a string, arg_b int) int {
147 println('fn_a(${arg_a}, ${arg_b})')
148 return 1
149}
150
151// TODO: error on missing name/type
152// fn fn_b(arg_a string, arg_b, arg_c, arg_d int) int {
153fn fn_b(arg_a string, arg_b int, arg_c int, arg_d int) int {
154 println('fn_b(${arg_a}, ${arg_b}, ${arg_c}, ${arg_d})')
155 return 1
156}
157
158fn fn_c(arg_a [][]StructA, arg_b [4]StructA) [][]StructA {
159 println('fn_b(${arg_a}, ${arg_b})')
160 return arg_a
161}
162
163fn fn_d(arg_a GenericStructA[int], arg_b moda.GenericStructA[int]) {
164 println('fn_d(${arg_a}, ${arg_b})')
165}
166
167fn C.fn_d(GenericStructA[int], moda.GenericStructA[int])
168
169fn fn_optional_a() ?int {
170 return 1
171}
172
173fn fn_optional_b() ?int {
174 return fn_optional_a()?
175}
176
177fn fn_optional_c() ?&StructD {
178 a := StructD{
179 field_a: &StructD{}
180 }
181 dump(a.field_a)
182 dump(a.field_a?.field_a)
183 assert a.field_a?.field_a == none
184 return a.field_a?
185}
186
187fn fn_opt_c() ?int {
188 return fn_optional_a()!
189}
190
191fn fn_result_a() ! {
192 return 1
193}
194
195fn fn_result_b() !int {
196 return 1
197}
198
199
200fn fn_multi_return_a() (int, int) {
201 return 1,2
202}
203
204fn fn_multi_return_optional_a() ?(int, int) {
205 return 1,2
206}
207
208fn fn_variadic_a(arg_a int, arg_b ...string) {
209 fn_variadic_b(...arg_b)
210 fn_variadic_b(...['a', 'b', 'c', 'd'])
211}
212
213fn fn_variadic_b(arg_a ...string) {
214 println(arg_a)
215}
216
217fn fn_arg_struct_int_a(arg_a StructA, arg_b int) {
218 println(arg_a)
219}
220
221fn (rec &StructA) method_a(arg_a string, arg_b int) int {
222 println('StructA.method_a(${arg_a}, ${arg_b})')
223 return 1
224}
225
226// TODO: operator overload (last missing parser feature, I think :D)
227pub fn (a StructA) == (b StructA) bool {
228 return a.field_a == b.field_a
229}
230
231fn channel_test(arg_a chan string) {
232 ch := chan int{cap: 20}
233 ch <- 111
234 rec := <-ch
235}
236
237fn spawn_test() {
238 t := spawn fn() {
239 for i in 0..100 {
240 println('${i}...')
241 }
242 }()
243 t.wait()
244}
245
246fn fn_result_a() !int {
247 array_a := [1,2,3,4]
248 return array_a[0]!
249}
250
251fn main_a() {
252 a := 1
253 b, c := 1, 2
254 array_init_a := [1,2,3,4]
255 array_init_b := [1,2,3,4]!
256 array_init_c := [array_init_a]
257 array_init_d := []string{len: 2, cap: 2}
258 array_init_e := [][]string{}
259 array_init_f := [2][]int{init:[1]}
260 array_init_g := [2][][][][]int{}
261 array_init_h := [2][][][][2]int{}
262 // TODO: better error for missing `]`
263 // array_init_i := [['a','b','c','d']
264 array_init_i := [['a','b','c','d']]
265 array_init_j := []&StructA{}
266 array_init_k := [fn(arg_a int) int { return 1 }]
267 array_init_i := [fn() int { return 1 }()]
268 array_init_thread_a := []thread int{cap: 16}
269 expr_a expr_b // TODO: error ?
270 expr_a; expr_b // TODO: error
271 map_init_long_string_string := map[string]string{}
272 map_init_long_string_array_string := map[string][]string{}
273 mut map_init_short_string_string := {'key_a': 'value_a'}
274 map_init_short_string_string = {} // test empty
275 map_init_short_string_array_string := {'key_a': ['value_a', 'value_b']}
276 map_init_short_ident_string := {key_a: 'value_a'} // unsupported key type
277 mut map_init_short_enum_value_init_expr := map[EnumA]StructA{}
278 // make sure we don't chain `StructA{field_a: 1}.value_b` as SelectorExpr
279 map_init_short_enum_value_init_expr = {
280 .value_a: StructA{
281 field_a: 1
282 }
283 .value_b: StructA{
284 field_a: 1
285 }
286 .value_c: StructA{
287 field_a: 1
288 }
289 }
290 struct_init_a := StructA{field_a: 1, field_b: 'v'}
291 struct_init_b := foo.StructA{field_a: 1, field_b: 'v'}
292 struct_init_c := StructA{1, 'v'}
293 // NOTE: no longer supported. will error
294 // assoc_old_a := {struct_a|field_a: 111}
295 // assoc_old_b := {
296 // ...struct_a
297 // field_a: 1
298 // }
299 assoc_current_a := StructA{
300 ...struct_a
301 // field_a: 1
302 }
303 string_literal_v_a := 'string literal a'
304 string_literal_v_b := "string literal b"
305 string_literal_c_a := c'c string literal a'
306 string_literal_raw_a := r'string $literal raw a'
307 thred_init_a := thread int{cap: 20}
308 call_a := fn_a('string', 1)
309 call_b := fn_b('string', 1, a, b)
310 call_c := array_init_g[0](1)
311 call_d := struct_a.method_a('string', 1)
312 call_e := struct_a.field_c(1)
313 call_f := array_init_k[0]()
314 call_g := array_init_k[fn() { return 0 }()]()
315 call_h := array_init_k[array_init_b[0]]()
316 call_config_syntax_a := fn_arg_struct_int_a(field_a: 1, field_b: 'b', 2)
317 call_lambda_expr_a := array_init_a.sorted(|x,y| x > y)
318 call_lambda_expr_b := f(|| 1)
319 call_selector_a := 'hello v world'
320 .split(' v ')
321 .join(' ')
322 call_comptime_a := $fn_a('string', 1)
323 // comptime call as expr stmt only
324 $fn_a('string', 1)
325 $compile_warn('compile warn')
326 cast_a := u8(1)
327 cast_b := &[]u8([1,2,3,4])
328 // the following casts should error later about not being
329 // able to cast array types, unless it gets implemented.
330 cast_c := []u8([1,2,3,4])
331 cast_d := [][][]u8([[[1,2,3,4]]])
332 cast_d := ?&?int(a)
333 fn_literal_a := fn(param_a int, param_b int) int {
334 return param_a+param_b
335 }
336 fn_literal_call_a := fn_literal_a(2, 4)
337 fn_literal_direct_call_a := fn(param_a int, param_b int) int {
338 return param_a+param_b
339 }(2, 4)
340 fn_literal_capturing_vars_a := fn [infix_a, infix_b] (param_a int, param_b int) int {
341 return (infix_a+infix_b)*(param_a+param_b)
342 }
343 fn_literal_capturing_vars_direct_call_a := fn [infix_a, infix_b] (param_a int, param_b int) int {
344 return (infix_a+infix_b)*(param_a+param_b)
345 }(2, 4)
346 index_a := array_init_a[0]
347 index_a := array_init_a[a]
348 index_b := struct_a.field_b[1]
349 index_c := [StructA{}][0] // direct index after init
350 index_d := [[1,2,3,4]][0][1] // unlimited chaining (add more examples)
351 index_e := [fn() []StructA { return [fn() []StructA { return [StructA{}] }()][0] }()[0]][0] // more chaining
352 index_f := fn() []string { return ['a', 'b'] }()[0]
353 index_g := array_init_e[0] or { ['e', 'f'] }[0]
354 index_range_a := array_init_a[0..2]
355 index_range_b := array_init_a[2..]
356 index_range_c := array_init_a[..2]
357 index_range_d := array_init_a[1+2..1+2]
358 index_range_e := array_init_a[1+2..]
359 index_range_f := array_init_a[..1+2]
360 index_range_g := array_init_a[1+2...1+2]
361 index_range_h := array_init_a[1+2...]
362 index_range_i := array_init_a[...1+2]
363 index_range_j := [[1,2,3,4]][0][2..4]
364 index_range_k := [[1,2,3,4]][0][2...4]
365 index_or_a := array_init_a[0] or { 1 }
366 index_or_b := array_init_c[0] or { [5,6,7,8] }[0]
367 index_or_c := fn() []int { return [array_init_a[0] or { 1 }] }()[0] or { 1 }
368 index_or_d := match index_a {
369 int { array_init_a }
370 else { [5,6,7,8] }
371 }[0] or { 1 }
372 infix_a := 1 * 2
373 infix_b := 1 + 2 * 3 / 4 + 5
374 infix_c := infix_a * 4 * 2 + 11 / 2
375 infix_d := a == b && c == d
376 infix_and_paren_expr_a := ((((infix_b + 1) * 2) + 111) * 2) / 2
377 infix_and_paren_expr_b := (((((x * array_init_a[0] +
378 array_init_a[1]) * x + array_init_a[2]) * x + array_init_a[3]) * x +
379 array_init_a[4]) * x + array_init_a[5]) * x + array_init_a[6]
380 prefix_a := &StructA{}
381 prefix_b := &&StructA{}
382 prefix_c := -infix_a + 2
383 prefix_optional_a := ?mod_a.StructA{}
384 prefix_optional_b := ?mod_a.StructA(none)
385 assert a == 1
386 assert a == 1, 'a does not equal 1'
387 assert c <= 2, 'c is greater than 2'
388 if val := array_init_a[0] {
389 println(val)
390 }
391 if res_a := fn_optional_a() {
392 println('if guard: ${res_a}')
393 }
394 if res_a, res_b := fn_multi_return_optional_a() {
395 println('if guard: ${res_a}, ${res_b}')
396 }
397 if res_a, res_b := fn_optional_a(), fn_optional_b() {
398 println('if guard: ${res_a}, ${res_b}')
399 }
400 if err == IError(MyError{}) {
401 println('err == IError(MyError{})')
402 }
403 if struct_init_a == (StructA{}) {
404 println('struct_init_a == (StructA{})')
405 }
406 // TODO: tricky
407 // if struct_init_a == StructA{} {
408 // println('struct_init_a == StructA{}')
409 // }
410 // if StructA{} == StructA{} {
411 // println('StructA{} == StructA{}')
412 // }
413 // if struct_init_a is StructA {
414 // println(1)
415 // }
416 if struct_init_a is []StructA {
417 println(1)
418 }
419 if a == 1 {
420 println('1 a == ${s}')
421 }
422 else if a == 2 {
423 println('2 a == ${s}')
424 }
425 else {
426 println('a == ${s}')
427 }
428 if (if a > 0 {
429 1
430 } else {
431 2
432 }) < 2 {
433 println('if expr in if cond < 2')
434 }
435 if a > 0 { StructA{} } else { StructB{} }.method_a()
436 $if linux {
437 println('linux')
438 }
439 $else $if windows {
440 println('windows')
441 }
442 $else {
443 println('other')
444 }
445 $if option_a ? {
446 println('custom option: `v -d option_a`')
447 }
448 $if T is $array {
449 println('T is array')
450 }
451 $else $if T is $struct {
452 println('T is struct')
453 }
454 $if T in [?int, ?int] {
455 println('option int')
456 }
457 for val_a in array_init_a {
458 println(val_a)
459 }
460 // TODO: error (unless first 2 are allowed? 0..10 and 0..infinity)
461 // the third one definitely needs to error
462 // for val_a in ..10 {}
463 // for val_a in 0.. {}
464 // for val_a in .. {}
465 for val_a in 0..10 {
466 println(val_a)
467 }
468 for key_a, val_a in array_init_a {
469 println(key_a)
470 println(val_a)
471 }
472 for key_a, mut val_a in array_init_a {
473 println(key_a)
474 println(val_a)
475 }
476 for idx_a in 0 .. a + 1 {
477 println(idx_a)
478 }
479 for key, value in {
480 'a': 'apple'
481 'b': 'bananna'
482 } {
483 println('${key}: ${value}')
484 }
485 for mut left_node is ast.InfixExpr {
486 if left_node.op == .and && mut left_node.right is ast.InfixExpr {
487 if left_node.right.op == .key_is {
488 println('xx')
489 }
490 }
491 }
492 for a:=0; a<=100; a++ {
493 println(a)
494 }
495 for mut a:=0; a<=100; {
496 a++
497 println(a)
498 }
499 for a, b := 0, 1; a < 4; a++ {
500 println('${a} - ${b}')
501 }
502 for a, b, c, d := 0, 1, 2, 3; a < 4; a++ {
503 println('${a} - ${b}')
504 }
505 // currently erroring in this case
506 // for a := 1 {}
507 for ; x < 100; {
508 println(x)
509 }
510 for x < 100 {
511 println(x)
512 }
513 for ; ; {
514 println('infinite loop')
515 }
516 for {
517 println('infinite loop')
518 }
519 $for x == 1 {
520 println('comptime for')
521 }
522 $for field in U.fields {
523 // TODO: parser needs to handle
524 // currently just skipping past
525 if val.$(field.name).str() != 'Option(none)' {
526 fields_len++
527 }
528 }
529 for_label_a: for i := 4; true; i++ {
530 println(i)
531 for {
532 if i < 7 {
533 continue for_label_a
534 } else {
535 break for_label_a
536 }
537 }
538 }
539 // fn literals
540 // capture list & generic params
541 fn [a, b] [T] () {
542 println('captured vars: ${a}, ${b}')
543 }[int]()
544 // capture list only
545 fn [a, b] () {
546 println('captured vars: ${a}, ${b}')
547 }()
548 // generic params only
549 fn [T] () {
550 println(typeof(T))
551 }[int]()
552 sumtype_a := SumTypeA(111)
553 as_cast_a := sumtype_a as int
554 // NOTE: or for as is not currently supported
555 // I may remove it unless supported is added
556 as_cast_b := sumtype_a as int or {
557 println('cast error')
558 }
559 match sumtype_a {
560 StructA { println('StructA') }
561 int { println('int') }
562 string { println('string') }
563 []string { println('[]string') }
564 }
565 mut ptr_a := &voidptr(0)
566 unsafe {
567 *ptr_a = 0
568 (*ptr_a) = *ptr_a - 1
569 ((*ptr_a)) = *ptr_a - 1
570 *(ptr_a) = *ptr_a - 1
571 *((ptr_a)) = *ptr_a - 1
572 (*(ptr_a)) = *ptr_a - 1
573 }
574 mut ptr_b := &voidptr(0)
575 unsafe {
576 *ptr_b = 0
577 }
578 unsafe_a := unsafe { mut d := 1 d++ d }
579 unsafe_a := unsafe { mut d := 1; d++; d }
580 unsafe_b := unsafe {
581 mut d := 1
582 d++
583 d
584 }
585 shared array_int_shared_a := []int{}
586 shared array_string_shared_a := []String{}
587 lock {
588 array_int_shared_a << 1
589 array_int_shared_a << 2
590 }
591 lock array_string_shared_a {
592 array_string_shared_a << 'a'
593 array_string_shared_a << 'b'
594 }
595 lock array_int_shared; rlock array_string_shared {
596 array_int_shared << 3
597 println(array_string_shared[0])
598 }
599 lock a,b; rlock c,d; lock e,f; rlock g,h {
600 println('silly lock test')
601 }
602 fn_a('string', unsafe {*ptr_a})
603 {
604 block_test_a := 1
605 }
606
607 ch_a := chan int{}
608 _ = <-ch_a or {
609 println('channel closed')
610 }
611 select {
612 a := <-ch_a
613 b := <-ch_a { b+=2 }
614 c := <-ch_a or {
615 panic('channel closed')
616 }
617 500 * time.millisecond {
618 eprintln('> more than 0.5s passed without a channel being ready')
619 }
620 }
621 __asm {
622 ldrex tmp, [addr]
623 strex tmp, value, [addr]
624 }
625 sql := 'test_ident_named_sql'
626 db_a := sqlite.connect('db_a') or {
627 panic('could not connect to db: ${err}')
628 }
629 nr_items := sql db {
630 select count from items
631 }
632 users := sql db {
633 select from User where name == 'first${user_suffix}'
634 }
635
636 // TODO: REMOVE BELOW - TEMP TESTING OR MOVE TO APPROPRIATE PLACE ABOVE
637
638 x.member.free()
639 x.member.submember1.free()
640 x.member.submember1.submember2.free()
641 x.y = cmdline.option(current_args, arg, '10').int()
642 x.y = cmdline.option(current_args, arg,
643 '10').int()
644
645 assert 'href="${url('/test')}"' == 'href="/test.html"'
646 assert '"${show_info('abc')}"' == '"abc"'
647
648 // TODO: confirm there are no cases where
649 // there is ambiguity with `|` infix expr
650 // lines_indents := lines
651 // .filter(|line| !line.is_blank())``
652 // .map(|line| line.indent_width())
653
654 // TODO:
655 for mut x is MyType {
656 println(x)
657 }
658
659 ms := t.swatches[name].elapsed().microseconds()
660
661 if !v.pref.is_bare && v.pref.build_mode != .build_module &&
662 v.pref.os in [.linux, .freebsd, .openbsd, .netbsd, .dragonfly, .solaris, .haiku] {
663 }
664
665 rng.shuffle[T](mut res, config_)!
666
667
668 link_cmd := '${call(it.replace('.c',
669 '.o')).join(' ')}'
670}
671