/
ast.v
2460 lines (2288 loc) · 56.3 KB
/
ast.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (c) 2019-2023 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module ast
import v.token
import v.errors
import v.pref
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
pub type Expr = AnonFn
| ArrayDecompose
| ArrayInit
| AsCast
| Assoc
| AtExpr
| BoolLiteral
| CTempVar
| CallExpr
| CastExpr
| ChanInit
| CharLiteral
| Comment
| ComptimeCall
| ComptimeSelector
| ComptimeType
| ConcatExpr
| DumpExpr
| EmptyExpr
| EnumVal
| FloatLiteral
| GoExpr
| Ident
| IfExpr
| IfGuardExpr
| IndexExpr
| InfixExpr
| IntegerLiteral
| IsRefType
| Likely
| LockExpr
| MapInit
| MatchExpr
| Nil
| NodeError
| None
| OffsetOf
| OrExpr
| ParExpr
| PostfixExpr
| PrefixExpr
| RangeExpr
| SelectExpr
| SelectorExpr
| SizeOf
| SpawnExpr
| SqlExpr
| StringInterLiteral
| StringLiteral
| StructInit
| TypeNode
| TypeOf
| UnsafeExpr
pub type Stmt = AsmStmt
| AssertStmt
| AssignStmt
| Block
| BranchStmt
| ComptimeFor
| ConstDecl
| DeferStmt
| EmptyStmt
| EnumDecl
| ExprStmt
| FnDecl
| ForCStmt
| ForInStmt
| ForStmt
| GlobalDecl
| GotoLabel
| GotoStmt
| HashStmt
| Import
| InterfaceDecl
| Module
| NodeError
| Return
| SqlStmt
| StructDecl
| TypeDecl
pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var
// TODO: replace Param
pub type Node = CallArg
| ConstField
| EmptyNode
| EnumField
| Expr
| File
| GlobalField
| IfBranch
| MatchBranch
| NodeError
| Param
| ScopeObject
| SelectBranch
| Stmt
| StructField
| StructInitField
pub struct TypeNode {
pub:
pos token.Pos
pub mut:
typ Type
end_comments []Comment // comments that after current type node
}
pub enum ComptimeTypeKind {
map_
int
float
struct_
iface
array
sum_type
enum_
alias
function
option
}
pub struct ComptimeType {
pub:
kind ComptimeTypeKind
pos token.Pos
}
pub fn (cty ComptimeType) str() string {
return match cty.kind {
.map_ { '\$map' }
.int { '\$int' }
.float { '\$float' }
.struct_ { '\$struct' }
.iface { '\$interface' }
.array { '\$array' }
.sum_type { '\$sumtype' }
.enum_ { '\$enum' }
.alias { '\$alias' }
.function { '\$function' }
.option { '\$option' }
}
}
pub type EmptyExpr = u8
pub struct EmptyStmt {
pub:
pos token.Pos
}
pub struct EmptyNode {
pub:
pos token.Pos
}
pub const (
empty_expr = Expr(EmptyExpr(0))
empty_stmt = Stmt(EmptyStmt{})
empty_node = Node(EmptyNode{})
)
// `{stmts}` or `unsafe {stmts}`
pub struct Block {
pub:
is_unsafe bool
pos token.Pos
pub mut:
stmts []Stmt
}
// | IncDecStmt k
// Stand-alone expression in a statement list.
pub struct ExprStmt {
pub:
pos token.Pos
comments []Comment
pub mut:
expr Expr
is_expr bool
typ Type
}
pub struct IntegerLiteral {
pub:
val string
pos token.Pos
}
pub struct FloatLiteral {
pub:
val string
pos token.Pos
}
[minify]
pub struct StringLiteral {
pub:
val string
is_raw bool
language Language
pos token.Pos
}
// 'name: $name'
pub struct StringInterLiteral {
pub:
vals []string
fwidths []int
precisions []int
pluss []bool
fills []bool
fmt_poss []token.Pos
pos token.Pos
pub mut:
exprs []Expr
expr_types []Type
fmts []u8
need_fmts []bool // an explicit non-default fmt required, e.g. `x`
}
pub struct CharLiteral {
pub:
val string
pos token.Pos
}
pub struct BoolLiteral {
pub:
val bool
pos token.Pos
}
pub struct Nil {
pub:
pos token.Pos
}
pub enum GenericKindField {
unknown
name
typ
}
// `foo.bar`
[minify]
pub struct SelectorExpr {
pub:
pos token.Pos
field_name string
is_mut bool // is used for the case `if mut ident.selector is MyType {`, it indicates if the root ident is mutable
mut_pos token.Pos
next_token token.Kind
pub mut:
expr Expr // expr.field_name
expr_type Type // type of `Foo` in `Foo.bar`
typ Type // type of the entire thing (`Foo.bar`)
name_type Type // T in `T.name` or typeof in `typeof(expr).name`
or_block OrExpr
gkind_field GenericKindField // `T.name` => ast.GenericKindField.name, `T.typ` => ast.GenericKindField.typ, or .unknown
scope &Scope = unsafe { nil }
from_embed_types []Type // holds the type of the embed that the method is called from
has_hidden_receiver bool
}
// root_ident returns the origin ident where the selector started.
pub fn (e &SelectorExpr) root_ident() ?Ident {
mut root := e.expr
for mut root is SelectorExpr {
root = root.expr
}
if mut root is Ident {
return root
}
return none
}
// module declaration
pub struct Module {
pub:
name string // encoding.base64
short_name string // base64
attrs []Attr
pos token.Pos
name_pos token.Pos // `name` in import name
is_skipped bool // module main can be skipped in single file programs
}
[minify]
pub struct StructField {
pub:
pos token.Pos
type_pos token.Pos
option_pos token.Pos
comments []Comment
i int
has_default_expr bool
attrs []Attr
is_pub bool
default_val string
is_mut bool
is_global bool
is_volatile bool
is_deprecated bool
pub mut:
is_recursive bool
default_expr Expr
default_expr_typ Type
name string
typ Type
unaliased_typ Type
anon_struct_decl StructDecl // only if the field is an anonymous struct
}
pub fn (f &StructField) equals(o &StructField) bool {
// TODO: f.is_mut == o.is_mut was removed here to allow read only access
// to (mut/not mut), but otherwise equal fields; some other new checks are needed:
// - if node is declared mut, and we mutate node.stmts, all stmts fields must be mutable
// - same goes for pub and global, if we call the field from another module
return f.name == o.name && f.typ == o.typ && f.is_pub == o.is_pub && f.is_global == o.is_global
}
// const field in const declaration group
pub struct ConstField {
pub:
mod string
name string
is_pub bool
is_markused bool // an explicit `[markused]` tag; the const will NOT be removed by `-skip-unused`, no matter what
pos token.Pos
pub mut:
expr Expr // the value expr of field; everything after `=`
typ Type // the type of the const field, it can be any type in V
comments []Comment // comments before current const field
end_comments []Comment // comments that after const field
// the comptime_expr_value field is filled by the checker, when it has enough
// info to evaluate the constant at compile time
comptime_expr_value ComptTimeConstValue = empty_comptime_const_expr()
}
// const declaration
[minify]
pub struct ConstDecl {
pub:
is_pub bool
pos token.Pos
attrs []Attr // tags like `[markused]`, valid for all the consts in the list
pub mut:
fields []ConstField // all the const fields in the `const (...)` block
end_comments []Comment // comments that after last const field
is_block bool // const() block
}
[minify]
pub struct StructDecl {
pub:
pos token.Pos
name string
generic_types []Type
is_pub bool
// _pos fields for vfmt
mut_pos int // mut:
pub_pos int // pub:
pub_mut_pos int // pub mut:
global_pos int // __global:
module_pos int // module:
language Language
is_union bool
attrs []Attr
pre_comments []Comment
end_comments []Comment
embeds []Embed
pub mut:
fields []StructField
}
pub struct Embed {
pub:
typ Type
pos token.Pos
comments []Comment
}
pub struct InterfaceEmbedding {
pub:
name string
typ Type
pos token.Pos
comments []Comment
}
[minify]
pub struct InterfaceDecl {
pub:
name string
typ Type
name_pos token.Pos
language Language
field_names []string
is_pub bool
mut_pos int // mut:
pos token.Pos
pre_comments []Comment
generic_types []Type
attrs []Attr
pub mut:
methods []FnDecl
fields []StructField
embeds []InterfaceEmbedding
are_embeds_expanded bool
}
// `field1: val1`
pub struct StructInitField {
pub:
pos token.Pos
name_pos token.Pos
comments []Comment
next_comments []Comment
pub mut:
expr Expr // `val1`
name string // 'field1'
typ Type // the type of this field
expected_type Type
parent_type Type
}
// `s := Foo{
// ...a
// field1: 'hello'
// }`
[minify]
pub struct StructInit {
pub:
pos token.Pos
name_pos token.Pos
no_keys bool // `Foo{val1, val2}`
is_short_syntax bool // `foo(field1: val1, field2: val2)`
is_anon bool // `x: struct{ foo: bar }`
pub mut:
unresolved bool
pre_comments []Comment
typ_str string // 'Foo'
typ Type // the type of this struct
update_expr Expr // `a` in `...a`
update_expr_type Type
update_expr_pos token.Pos
update_expr_comments []Comment
is_update_embed bool
has_update_expr bool // has `...a`
init_fields []StructInitField
generic_types []Type
}
pub enum StructInitKind {
normal
short_syntax
anon
}
// import statement
pub struct Import {
pub:
mod string // the module name of the import
alias string // the `x` in `import xxx as x`
pos token.Pos
mod_pos token.Pos
alias_pos token.Pos
syms_pos token.Pos
pub mut:
syms []ImportSymbol // the list of symbols in `import {symbol1, symbol2}`
comments []Comment
next_comments []Comment
}
// import symbol,for import {symbol} syntax
pub struct ImportSymbol {
pub:
pos token.Pos
name string
}
// anonymous function
pub struct AnonFn {
pub mut:
decl FnDecl
inherited_vars []Param
typ Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
has_gen map[string]bool // has been generated
}
// function or method declaration
[minify]
pub struct FnDecl {
pub:
name string // 'math.bits.normalize'
short_name string // 'normalize'
mod string // 'math.bits'
is_deprecated bool
is_pub bool
is_variadic bool
is_anon bool
is_noreturn bool // true, when [noreturn] is used on a fn
is_manualfree bool // true, when [manualfree] is used on a fn
is_main bool // true for `fn main()`
is_test bool // true for `fn test_abcde() {}`, false for `fn test_abc(x int) {}`, or for fns that do not start with test_
is_conditional bool // true for `[if abc] fn abc(){}`
is_exported bool // true for `[export: 'exact_C_name']`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
is_unsafe bool // true, when [unsafe] is used on a fn
is_markused bool // true, when an explicit `[markused]` tag was put on a fn; `-skip-unused` will not remove that fn
is_file_translated bool // true, when the file it resides in is `[translated]`
receiver StructField // TODO this is not a struct field
receiver_pos token.Pos // `(u User)` in `fn (u User) name()` position
is_method bool
is_static_type_method bool // true for `fn Foo.bar() {}`
method_type_pos token.Pos // `User` in ` fn (u User)` position
method_idx int
rec_mut bool // is receiver mutable
rec_share ShareType
language Language // V, C, JS
file_mode Language // whether *the file*, where a function was a '.c.v', '.js.v' etc.
no_body bool // just a definition `fn C.malloc()`
is_builtin bool // this function is defined in builtin/strconv
name_pos token.Pos
body_pos token.Pos // function bodys position
file string
generic_names []string
is_direct_arr bool // direct array access
attrs []Attr
ctdefine_idx int = -1 // the index in fn.attrs of `[if xyz]`, when such attribute exists
pub mut:
idx int // index in an external container; can be used to refer to the function in a more efficient way, just by its integer index
params []Param
stmts []Stmt
defer_stmts []DeferStmt
return_type Type
return_type_pos token.Pos // `string` in `fn (u User) name() string` position
has_return bool
should_be_skipped bool // true, when -skip-unused could not find any usages of that function, starting from main + other known used functions
ninstances int // 0 for generic functions with no concrete instances
has_await bool // 'true' if this function uses JS.await
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
end_comments []Comment // comments *after* header declarations. E.g.: `fn C.C_func(x int) int // Comment`
next_comments []Comment // comments that are one line after the decl; used for InterfaceDecl
source_file &File = unsafe { nil }
scope &Scope = unsafe { nil }
label_names []string
pos token.Pos // function declaration position
}
pub fn (f &FnDecl) new_method_with_receiver_type(new_type Type) FnDecl {
unsafe {
mut new_method := f
new_method.params = f.params.clone()
for i in 1 .. new_method.params.len {
if new_method.params[i].typ == new_method.params[0].typ {
new_method.params[i].typ = new_type
}
}
new_method.params[0].typ = new_type
return *new_method
}
}
[minify]
pub struct Fn {
pub:
is_variadic bool
language Language
is_pub bool
is_ctor_new bool // `[use_new] fn JS.Array.prototype.constructor()`
is_deprecated bool // `[deprecated] fn abc(){}`
is_noreturn bool // `[noreturn] fn abc(){}`
is_unsafe bool // `[unsafe] fn abc(){}`
is_placeholder bool
is_main bool // `fn main(){}`
is_test bool // `fn test_abc(){}`
is_keep_alive bool // passed memory must not be freed (by GC) before function returns
is_method bool // true for `fn (x T) name()`, and for interface declarations (which are also for methods)
is_static_type_method bool // true for `fn Foo.bar() {}`
no_body bool // a pure declaration like `fn abc(x int)`; used in .vh files, C./JS. fns.
is_file_translated bool // true, when the file it resides in is `[translated]`
mod string
file string
file_mode Language
pos token.Pos
return_type_pos token.Pos
pub mut:
return_type Type
receiver_type Type // != 0, when .is_method == true
name string
params []Param
source_fn voidptr // set in the checker, while processing fn declarations // TODO get rid of voidptr
usages int
generic_names []string
dep_names []string // globals or consts dependent names
attrs []Attr // all fn attributes
is_conditional bool // true for `[if abc]fn(){}`
ctdefine_idx int // the index of the attribute, containing the compile time define [if mytag]
}
fn (f &Fn) method_equals(o &Fn) bool {
return f.params[1..].equals(o.params[1..]) && f.return_type == o.return_type
&& f.is_variadic == o.is_variadic && f.language == o.language
&& f.generic_names == o.generic_names && f.is_pub == o.is_pub && f.mod == o.mod
&& f.name == o.name
}
[minify]
pub struct Param {
pub:
pos token.Pos
name string
is_mut bool
is_shared bool
is_atomic bool
is_auto_rec bool
type_pos token.Pos
is_hidden bool // interface first arg
pub mut:
typ Type
comments []Comment
}
pub fn (p &Param) specifier() string {
if p.is_shared {
return 'shared'
} else if p.is_atomic {
return 'atomic'
} else if p.is_mut {
return 'mut'
} else {
return ''
}
}
pub fn (f &Fn) new_method_with_receiver_type(new_type Type) Fn {
unsafe {
mut new_method := f
new_method.params = f.params.clone()
for i in 1 .. new_method.params.len {
if new_method.params[i].typ == new_method.params[0].typ {
new_method.params[i].typ = new_type
}
}
new_method.params[0].typ = new_type
return *new_method
}
}
fn (p &Param) equals(o &Param) bool {
return p.name == o.name && p.is_mut == o.is_mut && p.typ == o.typ && p.is_hidden == o.is_hidden
}
fn (p []Param) equals(o []Param) bool {
if p.len != o.len {
return false
}
for i in 0 .. p.len {
if !p[i].equals(o[i]) {
return false
}
}
return true
}
// break, continue
[minify]
pub struct BranchStmt {
pub:
kind token.Kind
label string
pos token.Pos
}
// function or method call expr
[minify]
pub struct CallExpr {
pub:
pos token.Pos
name_pos token.Pos
mod string
pub mut:
name string // left.name()
is_method bool
is_field bool // temp hack, remove ASAP when re-impl CallExpr / Selector (joe)
is_fn_var bool // fn variable, `a := fn() {}`, then: `a()`
is_fn_a_const bool // fn const, `const c = abc`, where `abc` is a function, then: `c()`
is_keep_alive bool // GC must not free arguments before fn returns
is_noreturn bool // whether the function/method is marked as [noreturn]
is_ctor_new bool // if JS ctor calls requires `new` before call, marked as `[use_new]` in V
is_file_translated bool // true, when the file it resides in is `[translated]`
args []CallArg
expected_arg_types []Type
comptime_ret_val bool
language Language
or_block OrExpr
left Expr // `user` in `user.register()`
left_type Type // type of `user`
receiver_type Type // User
return_type Type
fn_var_type Type // the fn type, when `is_fn_a_const` or `is_fn_var` is true
const_name string // the fully qualified name of the const, i.e. `main.c`, given `const c = abc`, and callexpr: `c()`
should_be_skipped bool // true for calls to `[if someflag?]` functions, when there is no `-d someflag`
concrete_types []Type // concrete types, e.g. <int, string>
concrete_list_pos token.Pos
raw_concrete_types []Type
free_receiver bool // true if the receiver expression needs to be freed
scope &Scope = unsafe { nil }
from_embed_types []Type // holds the type of the embed that the method is called from
comments []Comment
}
/*
pub struct AutofreeArgVar {
name string
idx int
}
*/
// function call argument: `f(callarg)`
[minify]
pub struct CallArg {
pub:
is_mut bool
share ShareType
comments []Comment
pub mut:
expr Expr
typ Type
is_tmp_autofree bool // this tells cgen that a tmp variable has to be used for the arg expression in order to free it after the call
pos token.Pos
// tmp_name string // for autofree
}
// function return statement
pub struct Return {
pub:
pos token.Pos
comments []Comment
pub mut:
exprs []Expr
types []Type
}
pub enum ComptimeVarKind {
no_comptime // it is not a comptime var
key_var // map key from `for k,v in t.$(field.name)`
value_var // map value from `for k,v in t.$(field.name)`
field_var // comptime field var `a := t.$(field.name)`
generic_param // generic fn parameter
}
[minify]
pub struct Var {
pub:
name string
share ShareType
is_mut bool
is_autofree_tmp bool
is_arg bool // fn args should not be autofreed
is_auto_deref bool
is_inherited bool
has_inherited bool
pub mut:
expr Expr
typ Type
orig_type Type // original sumtype type; 0 if it's not a sumtype
smartcasts []Type // nested sum types require nested smart casting, for that a list of types is needed
// TODO: move this to a real docs site later
// 10 <- original type (orig_type)
// [11, 12, 13] <- cast order (smartcasts)
// 12 <- the current casted type (typ)
pos token.Pos
is_used bool // whether the local variable was used in other expressions
is_changed bool // to detect mutable vars that are never changed
ct_type_var ComptimeVarKind // comptime variable type
// (for setting the position after the or block for autofree)
is_or bool // `x := foo() or { ... }`
is_tmp bool // for tmp for loop vars, so that autofree can skip them
is_auto_heap bool // value whose address goes out of scope
is_stack_obj bool // may be pointer to stack value (`mut` or `&` arg and not [heap] struct)
}
// used for smartcasting only
// struct fields change type in scopes
[minify]
pub struct ScopeStructField {
pub:
struct_type Type // type of struct
name string
pos token.Pos
typ Type
smartcasts []Type // nested sum types require nested smart casting, for that a list of types is needed
orig_type Type // original sumtype type; 0 if it's not a sumtype
// TODO: move this to a real docs site later
// 10 <- original type (orig_type)
// [11, 12, 13] <- cast order (smartcasts)
// 12 <- the current casted type (typ)
}
[minify]
pub struct GlobalField {
pub:
name string
has_expr bool
pos token.Pos
typ_pos token.Pos
is_markused bool // an explicit `[markused]` tag; the global will NOT be removed by `-skip-unused`
is_volatile bool
pub mut:
expr Expr
typ Type
comments []Comment
}
pub struct GlobalDecl {
pub:
mod string
pos token.Pos
is_block bool // __global() block
attrs []Attr // tags like `[markused]`, valid for all the globals in the list
pub mut:
fields []GlobalField
end_comments []Comment
}
[minify]
pub struct EmbeddedFile {
pub:
compression_type string
pub mut:
rpath string // used in the source code, as an ID/key to the embed
apath string // absolute path during compilation to the resource
// these are set by gen_embed_file_init in v/gen/c/embed
is_compressed bool
bytes []u8
len int
}
// Each V source file is represented by one File structure.
// When the V compiler runs, the parser will fill an []File.
// That array is then passed to V's checker.
[heap]
pub struct File {
pub:
nr_lines int // number of source code lines in the file (including newlines and comments)
nr_bytes int // number of processed source code bytes
mod Module // the module of the source file (from `module xyz` at the top)
global_scope &Scope = unsafe { nil }
is_test bool // true for _test.v files
is_generated bool // true for `[generated] module xyz` files; turn off notices
is_translated bool // true for `[translated] module xyz` files; turn off some checks
pub mut:
idx int // index in an external container; can be used to refer to the file in a more efficient way, just by its integer index
path string // absolute path of the source file - '/projects/v/file.v'
path_base string // file name - 'file.v' (useful for tracing)
scope &Scope = unsafe { nil }
stmts []Stmt // all the statements in the source file
imports []Import // all the imports
auto_imports []string // imports that were implicitly added
embedded_files []EmbeddedFile // list of files to embed in the binary
imported_symbols map[string]string // used for `import {symbol}`, it maps symbol => module.symbol
errors []errors.Error // all the checker errors in the file
warnings []errors.Warning // all the checker warnings in the file
notices []errors.Notice // all the checker notices in the file
generic_fns []&FnDecl
global_labels []string // from `asm { .globl labelname }`
template_paths []string // all the .html/.md files that were processed with $tmpl
}
[unsafe]
pub fn (f &File) free() {
unsafe {
f.path.free()
f.path_base.free()
f.scope.free()
f.stmts.free()
f.imports.free()
f.auto_imports.free()
f.embedded_files.free()
f.imported_symbols.free()
f.errors.free()
f.warnings.free()
f.notices.free()
f.global_labels.free()
}
}
pub struct IdentFn {
pub mut:
typ Type
}
// TODO: (joe) remove completely, use ident.obj
// instead which points to the scope object
[minify]
pub struct IdentVar {
pub mut:
typ Type
is_mut bool
is_static bool
is_volatile bool
is_option bool
share ShareType
}
pub type IdentInfo = IdentFn | IdentVar
pub enum IdentKind {
unresolved
blank_ident
variable
constant
global
function
}
// A single identifier
[minify]
pub struct Ident {
pub:
language Language
tok_kind token.Kind
pos token.Pos
mut_pos token.Pos
comptime bool
pub mut:
scope &Scope = unsafe { nil }
obj ScopeObject
mod string
name string
kind IdentKind
info IdentInfo
is_mut bool // if mut *token* is before name. Use `is_mut()` to lookup mut variable
or_expr OrExpr
concrete_types []Type
}
pub fn (i &Ident) is_auto_heap() bool {
match i.obj {
Var {
return i.obj.is_auto_heap
}
else {
return false
}
}
}
pub fn (i &Ident) is_mut() bool {
match i.obj {
Var {
return i.obj.is_mut
}
ConstField {
return false
}
AsmRegister, GlobalField {
return true
}
}
}
pub fn (i &Ident) var_info() IdentVar {
match i.info {
IdentVar {
return i.info
}
else {
panic('Ident.var_info(): info is not IdentVar variant')
}
}
}
// left op right
// See: token.Kind.is_infix
[minify]
pub struct InfixExpr {
pub:
op token.Kind
pos token.Pos