go back to `mut`. decisions, decisions...
parent
1bf094fbca
commit
ee2e83fef0
52
doc/docs.md
52
doc/docs.md
|
@ -126,16 +126,16 @@ Unlike most other languages, V only allows defining variables in functions.
|
|||
Global (module level) variables are not allowed. There's no global state in V.
|
||||
|
||||
```v
|
||||
var age := 20
|
||||
mut age := 20
|
||||
println(age)
|
||||
age = 21
|
||||
println(age)
|
||||
```
|
||||
|
||||
To change the value of the variable use `=`. In V, variables are
|
||||
immutable by default. To be able to change the value of the variable, you have to declare it with `var`.
|
||||
immutable by default. To be able to change the value of the variable, you have to declare it with `mut`.
|
||||
|
||||
Try compiling the program above after removing `var` from the first line.
|
||||
Try compiling the program above after removing `mut` from the first line.
|
||||
|
||||
Please note the difference between `:=` and `=`
|
||||
`:=` is used for declaring and initializing, `=` is used for assigning.
|
||||
|
@ -200,7 +200,7 @@ bobby := name + 'by' // + is used to concatenate strings
|
|||
println(bobby) // "Bobby"
|
||||
|
||||
println(bobby[1..3]) // "ob"
|
||||
var s := 'hello '
|
||||
mut s := 'hello '
|
||||
s += 'world' // `+=` is used to append to a string
|
||||
println(s) // "hello world"
|
||||
```
|
||||
|
@ -264,7 +264,7 @@ Modules can be imported using keyword `import`. When using types, functions, and
|
|||
## Arrays
|
||||
|
||||
```v
|
||||
var nums := [1, 2, 3]
|
||||
mut nums := [1, 2, 3]
|
||||
println(nums) // "[1, 2, 3]"
|
||||
println(nums[1]) // "2"
|
||||
|
||||
|
@ -274,7 +274,7 @@ println(nums) // "[1, 2, 3, 4]"
|
|||
nums << [5, 6, 7]
|
||||
println(nums) // "[1, 2, 3, 4, 5, 6, 7]"
|
||||
|
||||
var names := ['John']
|
||||
mut names := ['John']
|
||||
names << 'Peter'
|
||||
names << 'Sam'
|
||||
// names << 10 <-- This will not compile. `names` is an array of strings.
|
||||
|
@ -322,7 +322,7 @@ println(upper) // ['HELLO', 'WORLD']
|
|||
## Maps
|
||||
|
||||
```v
|
||||
var m := map[string]int // Only maps with string keys are allowed for now
|
||||
mut m := map[string]int // Only maps with string keys are allowed for now
|
||||
m['one'] = 1
|
||||
m['two'] = 2
|
||||
println(m['one']) // "1"
|
||||
|
@ -414,7 +414,7 @@ If an index is required, an alternative form `for index, value in` can be used.
|
|||
Note, that the value is read-only. If you need to modify the array while looping, you have to use indexing:
|
||||
|
||||
```v
|
||||
var numbers := [1, 2, 3, 4, 5]
|
||||
mut numbers := [1, 2, 3, 4, 5]
|
||||
for i, num in numbers {
|
||||
println(num)
|
||||
numbers[i] = 0
|
||||
|
@ -422,8 +422,8 @@ for i, num in numbers {
|
|||
```
|
||||
|
||||
```v
|
||||
var sum := 0
|
||||
var i := 0
|
||||
mut sum := 0
|
||||
mut i := 0
|
||||
for i <= 100 {
|
||||
sum += i
|
||||
i++
|
||||
|
@ -438,7 +438,7 @@ The loop will stop iterating once the boolean condition evaluates to false.
|
|||
Again, there are no parentheses surrounding the condition, and the braces are always required.
|
||||
|
||||
```v
|
||||
var num := 0
|
||||
mut num := 0
|
||||
for {
|
||||
num++
|
||||
if num >= 10 {
|
||||
|
@ -464,7 +464,7 @@ Finally, there's the traditional C style `for` loop. It's safer than the `while`
|
|||
because with the latter it's easy to forget to update the counter and get
|
||||
stuck in an infinite loop.
|
||||
|
||||
Here `i` doesn't need to be declared with `var` since it's always going to be mutable by definition.
|
||||
Here `i` doesn't need to be declared with `mut` since it's always going to be mutable by definition.
|
||||
|
||||
## Match
|
||||
|
||||
|
@ -557,7 +557,7 @@ button.widget.set_pos(x,y)
|
|||
|
||||
Struct fields are private and immutable by default (making structs immutable as well).
|
||||
Their access modifiers can be changed with
|
||||
`pub` and `var`. In total, there are 5 possible options:
|
||||
`pub` and `mut`. In total, there are 5 possible options:
|
||||
|
||||
```v
|
||||
struct Foo {
|
||||
|
@ -633,7 +633,7 @@ This is achieved by lack of global variables and all function arguments being im
|
|||
even when references are passed.
|
||||
|
||||
V is not a pure functional language however.
|
||||
It is possible to modify function arguments by using the same keyword `var`:
|
||||
It is possible to modify function arguments by using the same keyword `mut`:
|
||||
|
||||
```v
|
||||
struct User {
|
||||
|
@ -641,11 +641,11 @@ var:
|
|||
is_registered bool
|
||||
}
|
||||
|
||||
fn (var u User) register() {
|
||||
fn (mut u User) register() {
|
||||
u.is_registered = true
|
||||
}
|
||||
|
||||
var user := User{}
|
||||
mut user := User{}
|
||||
println(user.is_registered) // "false"
|
||||
user.register()
|
||||
println(user.is_registered) // "true"
|
||||
|
@ -655,18 +655,18 @@ In this example, the receiver (which is simply the first argument) is marked as
|
|||
so `register()` can change the user object. The same works with non-receiver arguments:
|
||||
|
||||
```v
|
||||
fn multiply_by_2(var arr []int) {
|
||||
fn multiply_by_2(mut arr []int) {
|
||||
for i in 0..arr.len {
|
||||
arr[i] *= 2
|
||||
}
|
||||
}
|
||||
|
||||
var nums := [1, 2, 3]
|
||||
multiply_by_2(var nums)
|
||||
mut nums := [1, 2, 3]
|
||||
multiply_by_2(mut nums)
|
||||
println(nums) // "[2, 4, 6]"
|
||||
```
|
||||
|
||||
Note, that you have to add `var` before `nums` when calling this function. This makes
|
||||
Note, that you have to add `mut` before `nums` when calling this function. This makes
|
||||
it clear that the function being called will modify the value.
|
||||
|
||||
It is preferable to return values instead of modifying arguments.
|
||||
|
@ -677,7 +677,7 @@ For this reason V doesn't allow to modify primitive args like integers, only
|
|||
complex types like arrays and maps.
|
||||
|
||||
Use `user.register()` or `user = register(user)`
|
||||
instead of `register(var user)`.
|
||||
instead of `register(mut user)`.
|
||||
|
||||
V makes it easy to return a modified version of an object:
|
||||
|
||||
|
@ -734,7 +734,7 @@ fn (foo &Foo) bar() {
|
|||
```
|
||||
|
||||
`foo` is still immutable and can't be changed. For that,
|
||||
`(var foo Foo)` has to be used.
|
||||
`(mut foo Foo)` has to be used.
|
||||
|
||||
In general, V references are similar to Go pointers and C++ references.
|
||||
For example, a tree structure definition would look like this:
|
||||
|
@ -917,7 +917,7 @@ enum Color {
|
|||
red green blue
|
||||
}
|
||||
|
||||
var color := Color.red
|
||||
mut color := Color.red
|
||||
// V knows that `color` is a `Color`. No need to use `color = Color.green` here.
|
||||
color = .green
|
||||
println(color) // "1" TODO: print "green"?
|
||||
|
@ -1385,7 +1385,7 @@ serializers for anything:
|
|||
```v
|
||||
// TODO: not implemented yet
|
||||
fn decode<T>(data string) T {
|
||||
var result := T{}
|
||||
mut result := T{}
|
||||
for field in T.fields {
|
||||
if field.typ == 'string' {
|
||||
result.$field = get_string(data, field.name)
|
||||
|
@ -1398,7 +1398,7 @@ fn decode<T>(data string) T {
|
|||
|
||||
// generates to:
|
||||
fn decode_User(data string) User {
|
||||
var result := User{}
|
||||
mut result := User{}
|
||||
result.name = get_string(data, 'name')
|
||||
result.age = get_int(data, 'age')
|
||||
return result
|
||||
|
@ -1492,7 +1492,7 @@ Run `v translate test.cpp` and V will generate `test.v`:
|
|||
|
||||
```v
|
||||
fn main {
|
||||
var s := []
|
||||
mut s := []
|
||||
s << 'V is '
|
||||
s << 'awesome'
|
||||
println(s.len)
|
||||
|
|
|
@ -8,14 +8,14 @@ import v.table
|
|||
import strings
|
||||
|
||||
pub fn (node &FnDecl) str(t &table.Table) string {
|
||||
var f := strings.new_builder(30)
|
||||
mut f := strings.new_builder(30)
|
||||
if node.is_pub {
|
||||
f.write('pub ')
|
||||
}
|
||||
var receiver := ''
|
||||
mut receiver := ''
|
||||
if node.is_method {
|
||||
var styp := t.type_to_str(node.receiver.typ)
|
||||
var m := if node.rec_mut { 'var ' } else { '' }
|
||||
mut styp := t.type_to_str(node.receiver.typ)
|
||||
mut m := if node.rec_mut { 'mut ' } else { '' }
|
||||
if node.rec_mut {
|
||||
styp = styp[1..] // remove &
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ pub fn (node &FnDecl) str(t &table.Table) string {
|
|||
receiver = '($node.receiver.name $m$name) '
|
||||
*/
|
||||
}
|
||||
var name := node.name.after('.')
|
||||
mut name := node.name.after('.')
|
||||
if node.is_c {
|
||||
name = 'C.$name'
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ pub fn (node &FnDecl) str(t &table.Table) string {
|
|||
should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ || (node.is_variadic &&
|
||||
i == node.args.len - 2)
|
||||
f.write(arg.name)
|
||||
var s := t.type_to_str(arg.typ)
|
||||
mut s := t.type_to_str(arg.typ)
|
||||
if arg.is_mut {
|
||||
f.write(' mut')
|
||||
if s.starts_with('&') {
|
||||
|
@ -161,7 +161,7 @@ pub fn (a CallArg) str() string {
|
|||
}
|
||||
|
||||
pub fn args2str(args []CallArg) string {
|
||||
var res := []string
|
||||
mut res := []string
|
||||
for a in args {
|
||||
res << a.str()
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ pub fn args2str(args []CallArg) string {
|
|||
pub fn (node Stmt) str() string {
|
||||
match node {
|
||||
AssignStmt {
|
||||
var out := ''
|
||||
mut out := ''
|
||||
for i, ident in it.left {
|
||||
var_info := ident.var_info()
|
||||
if var_info.is_mut {
|
||||
|
|
|
@ -31,7 +31,7 @@ mut:
|
|||
}
|
||||
|
||||
pub fn fmt(file ast.File, table &table.Table) string {
|
||||
var f := Fmt{
|
||||
mut f := Fmt{
|
||||
out: strings.new_builder(1000)
|
||||
out_imports: strings.new_builder(200)
|
||||
table: table
|
||||
|
@ -67,7 +67,7 @@ fn (f mut Fmt) find_comment(line_nr int) {
|
|||
}
|
||||
}
|
||||
*/
|
||||
pub fn (var f Fmt) write(s string) {
|
||||
pub fn (mut f Fmt) write(s string) {
|
||||
if f.indent > 0 && f.empty_line {
|
||||
f.out.write(tabs[f.indent])
|
||||
f.line_len += f.indent * 4
|
||||
|
@ -77,7 +77,7 @@ pub fn (var f Fmt) write(s string) {
|
|||
f.empty_line = false
|
||||
}
|
||||
|
||||
pub fn (var f Fmt) writeln(s string) {
|
||||
pub fn (mut f Fmt) writeln(s string) {
|
||||
if f.indent > 0 && f.empty_line {
|
||||
// println(f.indent.str() + s)
|
||||
f.out.write(tabs[f.indent])
|
||||
|
@ -87,7 +87,7 @@ pub fn (var f Fmt) writeln(s string) {
|
|||
f.line_len = 0
|
||||
}
|
||||
|
||||
fn (var f Fmt) mod(mod ast.Module) {
|
||||
fn (mut f Fmt) mod(mod ast.Module) {
|
||||
f.cur_mod = mod.name
|
||||
if mod.is_skipped {
|
||||
return
|
||||
|
@ -95,7 +95,7 @@ fn (var f Fmt) mod(mod ast.Module) {
|
|||
f.writeln('module $mod.name\n')
|
||||
}
|
||||
|
||||
fn (var f Fmt) imports(imports []ast.Import) {
|
||||
fn (mut f Fmt) imports(imports []ast.Import) {
|
||||
if f.did_imports || imports.len == 0 {
|
||||
return
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ fn (f Fmt) imp_stmt_str(imp ast.Import) string {
|
|||
return '${imp.mod}${imp_alias_suffix}'
|
||||
}
|
||||
|
||||
fn (var f Fmt) stmts(stmts []ast.Stmt) {
|
||||
fn (mut f Fmt) stmts(stmts []ast.Stmt) {
|
||||
f.indent++
|
||||
for stmt in stmts {
|
||||
f.stmt(stmt)
|
||||
|
@ -137,13 +137,13 @@ fn (var f Fmt) stmts(stmts []ast.Stmt) {
|
|||
f.indent--
|
||||
}
|
||||
|
||||
fn (var f Fmt) stmt(node ast.Stmt) {
|
||||
fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||
match node {
|
||||
ast.AssignStmt {
|
||||
for i, ident in it.left {
|
||||
var_info := ident.var_info()
|
||||
if var_info.is_mut {
|
||||
f.write('var ')
|
||||
f.write('mut ')
|
||||
}
|
||||
f.expr(ident)
|
||||
if i < it.left.len - 1 {
|
||||
|
@ -201,7 +201,7 @@ fn (var f Fmt) stmt(node ast.Stmt) {
|
|||
f.write('pub ')
|
||||
}
|
||||
f.writeln('const (')
|
||||
var max := 0
|
||||
mut max := 0
|
||||
for field in it.fields {
|
||||
if field.name.len > max {
|
||||
max = field.name.len
|
||||
|
@ -375,7 +375,7 @@ fn (var f Fmt) stmt(node ast.Stmt) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var f Fmt) type_decl(node ast.TypeDecl) {
|
||||
fn (mut f Fmt) type_decl(node ast.TypeDecl) {
|
||||
match node {
|
||||
ast.AliasTypeDecl {
|
||||
if it.is_pub {
|
||||
|
@ -389,7 +389,7 @@ fn (var f Fmt) type_decl(node ast.TypeDecl) {
|
|||
f.write('pub ')
|
||||
}
|
||||
f.write('type $it.name = ')
|
||||
var sum_type_names := []string
|
||||
mut sum_type_names := []string
|
||||
for t in it.sub_types {
|
||||
sum_type_names << f.type_to_str(t)
|
||||
}
|
||||
|
@ -402,13 +402,13 @@ fn (var f Fmt) type_decl(node ast.TypeDecl) {
|
|||
f.writeln('\n')
|
||||
}
|
||||
|
||||
fn (var f Fmt) struct_decl(node ast.StructDecl) {
|
||||
fn (mut f Fmt) struct_decl(node ast.StructDecl) {
|
||||
if node.is_pub {
|
||||
f.write('pub ')
|
||||
}
|
||||
name := node.name.after('.')
|
||||
f.writeln('struct $name {')
|
||||
var max := 0
|
||||
mut max := 0
|
||||
for field in node.fields {
|
||||
if field.name.len > max {
|
||||
max = field.name.len
|
||||
|
@ -449,7 +449,7 @@ fn (var f Fmt) struct_decl(node ast.StructDecl) {
|
|||
}
|
||||
|
||||
fn (f &Fmt) type_to_str(t table.Type) string {
|
||||
var res := f.table.type_to_str(t)
|
||||
mut res := f.table.type_to_str(t)
|
||||
// type_ptr => &type
|
||||
if res.ends_with('_ptr') {
|
||||
res = res[0..res.len - 4]
|
||||
|
@ -459,7 +459,7 @@ fn (f &Fmt) type_to_str(t table.Type) string {
|
|||
return res.replace(f.cur_mod + '.', '')
|
||||
}
|
||||
|
||||
fn (var f Fmt) expr(node ast.Expr) {
|
||||
fn (mut f Fmt) expr(node ast.Expr) {
|
||||
match node {
|
||||
ast.ArrayInit {
|
||||
if it.exprs.len == 0 && it.typ != 0 && it.typ != table.void_type {
|
||||
|
@ -469,8 +469,8 @@ fn (var f Fmt) expr(node ast.Expr) {
|
|||
// `[1,2,3]`
|
||||
// type_sym := f.table.get_type_symbol(it.typ)
|
||||
f.write('[')
|
||||
var inc_indent := false
|
||||
var line_nr := node.position().line_nr // to have the same newlines between array elements
|
||||
mut inc_indent := false
|
||||
mut line_nr := node.position().line_nr // to have the same newlines between array elements
|
||||
for i, expr in it.exprs {
|
||||
pos := expr.position()
|
||||
if i == 0 && line_nr < pos.line_nr {
|
||||
|
@ -663,7 +663,7 @@ fn (var f Fmt) expr(node ast.Expr) {
|
|||
ast.StructInit {
|
||||
type_sym := f.table.get_type_symbol(it.typ)
|
||||
// f.write('<old name: $type_sym.name>')
|
||||
var name := short_module(type_sym.name).replace(f.cur_mod + '.', '') // TODO f.type_to_str?
|
||||
mut name := short_module(type_sym.name).replace(f.cur_mod + '.', '') // TODO f.type_to_str?
|
||||
if name == 'void' {
|
||||
name = ''
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ fn (var f Fmt) expr(node ast.Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var f Fmt) wrap_long_line() {
|
||||
fn (mut f Fmt) wrap_long_line() {
|
||||
if f.line_len > max_len {
|
||||
if f.out.buf[f.out.buf.len - 1] == ` ` {
|
||||
f.out.go_back(1)
|
||||
|
@ -719,7 +719,7 @@ fn (var f Fmt) wrap_long_line() {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var f Fmt) call_args(args []ast.CallArg) {
|
||||
fn (mut f Fmt) call_args(args []ast.CallArg) {
|
||||
for i, arg in args {
|
||||
if arg.is_mut {
|
||||
f.write('mut ')
|
||||
|
@ -734,7 +734,7 @@ fn (var f Fmt) call_args(args []ast.CallArg) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var f Fmt) or_expr(or_block ast.OrExpr) {
|
||||
fn (mut f Fmt) or_expr(or_block ast.OrExpr) {
|
||||
if or_block.stmts.len > 0 {
|
||||
f.writeln(' or {')
|
||||
f.stmts(or_block.stmts)
|
||||
|
@ -742,10 +742,10 @@ fn (var f Fmt) or_expr(or_block ast.OrExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var f Fmt) comment(node ast.Comment) {
|
||||
fn (mut f Fmt) comment(node ast.Comment) {
|
||||
if !node.text.contains('\n') {
|
||||
is_separate_line := node.text.starts_with('|')
|
||||
var s := if is_separate_line { node.text[1..] } else { node.text }
|
||||
mut s := if is_separate_line { node.text[1..] } else { node.text }
|
||||
if s == '' {
|
||||
s = '//'
|
||||
} else {
|
||||
|
@ -779,7 +779,7 @@ fn short_module(name string) string {
|
|||
return vals[vals.len - 2] + '.' + vals[vals.len - 1]
|
||||
}
|
||||
|
||||
fn (var f Fmt) if_expr(it ast.IfExpr) {
|
||||
fn (mut f Fmt) if_expr(it ast.IfExpr) {
|
||||
single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == 1 &&
|
||||
it.branches[1].stmts.len == 1 && (it.is_expr || f.is_assign)
|
||||
f.single_line_if = single_line
|
||||
|
@ -812,7 +812,7 @@ fn (var f Fmt) if_expr(it ast.IfExpr) {
|
|||
f.single_line_if = false
|
||||
}
|
||||
|
||||
fn (var f Fmt) call_expr(node ast.CallExpr) {
|
||||
fn (mut f Fmt) call_expr(node ast.CallExpr) {
|
||||
if node.is_method {
|
||||
match node.left {
|
||||
ast.Ident {
|
||||
|
@ -849,15 +849,15 @@ fn (var f Fmt) call_expr(node ast.CallExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var f Fmt) match_expr(it ast.MatchExpr) {
|
||||
fn (mut f Fmt) match_expr(it ast.MatchExpr) {
|
||||
f.write('match ')
|
||||
if it.is_mut {
|
||||
f.write('var ')
|
||||
f.write('mut ')
|
||||
}
|
||||
f.expr(it.cond)
|
||||
f.writeln(' {')
|
||||
f.indent++
|
||||
var single_line := true
|
||||
mut single_line := true
|
||||
for i, branch in it.branches {
|
||||
if branch.stmts.len > 1 {
|
||||
single_line = false
|
||||
|
@ -913,8 +913,8 @@ fn (var f Fmt) match_expr(it ast.MatchExpr) {
|
|||
f.write('}')
|
||||
}
|
||||
|
||||
fn (var f Fmt) remove_new_line() {
|
||||
var i := 0
|
||||
fn (mut f Fmt) remove_new_line() {
|
||||
mut i := 0
|
||||
for i = f.out.len - 1; i >= 0; i-- {
|
||||
if !f.out.buf[i].is_space() { // != `\n` {
|
||||
break
|
||||
|
@ -925,13 +925,13 @@ fn (var f Fmt) remove_new_line() {
|
|||
// f.writeln('sdf')
|
||||
}
|
||||
|
||||
fn (var f Fmt) mark_types_module_as_used(typ table.Type) {
|
||||
fn (mut f Fmt) mark_types_module_as_used(typ table.Type) {
|
||||
sym := f.table.get_type_symbol(typ)
|
||||
f.mark_module_as_used(sym.name)
|
||||
}
|
||||
|
||||
// `name` is a function (`foo.bar()`) or type (`foo.Bar{}`)
|
||||
fn (var f Fmt) mark_module_as_used(name string) {
|
||||
fn (mut f Fmt) mark_module_as_used(name string) {
|
||||
if !name.contains('.') {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
} else {
|
||||
}
|
||||
// println('start cgen2')
|
||||
var g := Gen{
|
||||
mut g := Gen{
|
||||
out: strings.new_builder(1000)
|
||||
cheaders: strings.new_builder(8192)
|
||||
includes: strings.new_builder(100)
|
||||
|
@ -114,7 +114,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
}
|
||||
g.init()
|
||||
//
|
||||
var autofree_used := false
|
||||
mut autofree_used := false
|
||||
for file in files {
|
||||
g.file = file
|
||||
// println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len')
|
||||
|
@ -154,12 +154,12 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
|||
}
|
||||
|
||||
pub fn (g Gen) hashes() string {
|
||||
var res := c_commit_hash_default.replace('@@@', util.vhash())
|
||||
mut res := c_commit_hash_default.replace('@@@', util.vhash())
|
||||
res += c_current_commit_hash_default.replace('@@@', util.githash(g.pref.building_v))
|
||||
return res
|
||||
}
|
||||
|
||||
pub fn (var g Gen) init() {
|
||||
pub fn (mut g Gen) init() {
|
||||
g.cheaders.writeln('// Generated by the V compiler')
|
||||
g.cheaders.writeln('#include <inttypes.h>') // int64_t etc
|
||||
g.cheaders.writeln(c_builtin_types)
|
||||
|
@ -184,7 +184,7 @@ pub fn (var g Gen) init() {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (var g Gen) finish() {
|
||||
pub fn (mut g Gen) finish() {
|
||||
if g.pref.build_mode != .build_module {
|
||||
g.stringliterals.writeln('}')
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ pub fn (var g Gen) finish() {
|
|||
g.stringliterals.writeln('')
|
||||
}
|
||||
|
||||
pub fn (var g Gen) write_typeof_functions() {
|
||||
pub fn (mut g Gen) write_typeof_functions() {
|
||||
g.writeln('')
|
||||
g.writeln('// >> typeof() support for sum types')
|
||||
for typ in g.table.types {
|
||||
|
@ -216,10 +216,10 @@ pub fn (var g Gen) write_typeof_functions() {
|
|||
}
|
||||
|
||||
// V type to C type
|
||||
pub fn (var g Gen) typ(t table.Type) string {
|
||||
pub fn (mut g Gen) typ(t table.Type) string {
|
||||
nr_muls := table.type_nr_muls(t)
|
||||
sym := g.table.get_type_symbol(t)
|
||||
var styp := sym.name.replace('.', '__')
|
||||
mut styp := sym.name.replace('.', '__')
|
||||
if nr_muls > 0 {
|
||||
styp += strings.repeat(`*`, nr_muls)
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ pub fn (var g Gen) typ(t table.Type) string {
|
|||
}
|
||||
|
||||
//
|
||||
pub fn (var g Gen) write_typedef_types() {
|
||||
pub fn (mut g Gen) write_typedef_types() {
|
||||
for typ in g.table.types {
|
||||
match typ.kind {
|
||||
.alias {
|
||||
|
@ -294,7 +294,7 @@ pub fn (var g Gen) write_typedef_types() {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (var g Gen) write_multi_return_types() {
|
||||
pub fn (mut g Gen) write_multi_return_types() {
|
||||
g.definitions.writeln('// multi return structs')
|
||||
for typ in g.table.types {
|
||||
// sym := g.table.get_type_symbol(typ)
|
||||
|
@ -315,7 +315,7 @@ pub fn (var g Gen) write_multi_return_types() {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (var g Gen) write_variadic_types() {
|
||||
pub fn (mut g Gen) write_variadic_types() {
|
||||
if g.variadic_args.size > 0 {
|
||||
g.definitions.writeln('// variadic structs')
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ pub fn (var g Gen) write_variadic_types() {
|
|||
pub fn (g Gen) save() {
|
||||
}
|
||||
|
||||
pub fn (var g Gen) write(s string) {
|
||||
pub fn (mut g Gen) write(s string) {
|
||||
if g.indent > 0 && g.empty_line {
|
||||
g.out.write(tabs[g.indent])
|
||||
// g.line_len += g.indent * 4
|
||||
|
@ -343,7 +343,7 @@ pub fn (var g Gen) write(s string) {
|
|||
g.empty_line = false
|
||||
}
|
||||
|
||||
pub fn (var g Gen) writeln(s string) {
|
||||
pub fn (mut g Gen) writeln(s string) {
|
||||
if g.indent > 0 && g.empty_line {
|
||||
g.out.write(tabs[g.indent])
|
||||
}
|
||||
|
@ -351,16 +351,16 @@ pub fn (var g Gen) writeln(s string) {
|
|||
g.empty_line = true
|
||||
}
|
||||
|
||||
pub fn (var g Gen) new_tmp_var() string {
|
||||
pub fn (mut g Gen) new_tmp_var() string {
|
||||
g.tmp_count++
|
||||
return 'tmp$g.tmp_count'
|
||||
}
|
||||
|
||||
pub fn (var g Gen) reset_tmp_count() {
|
||||
pub fn (mut g Gen) reset_tmp_count() {
|
||||
g.tmp_count = 0
|
||||
}
|
||||
|
||||
fn (var g Gen) stmts(stmts []ast.Stmt) {
|
||||
fn (mut g Gen) stmts(stmts []ast.Stmt) {
|
||||
g.indent++
|
||||
if g.inside_ternary {
|
||||
g.write(' ( ')
|
||||
|
@ -377,7 +377,7 @@ fn (var g Gen) stmts(stmts []ast.Stmt) {
|
|||
g.indent--
|
||||
}
|
||||
|
||||
fn (var g Gen) stmt(node ast.Stmt) {
|
||||
fn (mut g Gen) stmt(node ast.Stmt) {
|
||||
g.stmt_start_pos = g.out.len
|
||||
// println('cgen.stmt()')
|
||||
// g.writeln('//// stmt start')
|
||||
|
@ -421,7 +421,7 @@ fn (var g Gen) stmt(node ast.Stmt) {
|
|||
g.comp_if(it)
|
||||
}
|
||||
ast.DeferStmt {
|
||||
var defer_stmt := *it
|
||||
mut defer_stmt := *it
|
||||
defer_stmt.ifdef = g.defer_ifdef
|
||||
g.defer_stmts << defer_stmt
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ fn (var g Gen) stmt(node ast.Stmt) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) write_defer_stmts() {
|
||||
fn (mut g Gen) write_defer_stmts() {
|
||||
for defer_stmt in g.defer_stmts {
|
||||
g.writeln('// defer')
|
||||
if defer_stmt.ifdef.len > 0 {
|
||||
|
@ -570,7 +570,7 @@ fn (var g Gen) write_defer_stmts() {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) for_in(it ast.ForInStmt) {
|
||||
fn (mut g Gen) for_in(it ast.ForInStmt) {
|
||||
if it.is_range {
|
||||
// `for x in 1..10 {`
|
||||
i := g.new_tmp_var()
|
||||
|
@ -650,7 +650,7 @@ fn (var g Gen) for_in(it ast.ForInStmt) {
|
|||
}
|
||||
|
||||
// use instead of expr() when you need to cast to sum type (can add other casts also)
|
||||
fn (var g Gen) expr_with_cast(expr ast.Expr, got_type, exp_type table.Type) {
|
||||
fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, exp_type table.Type) {
|
||||
// cast to sum type
|
||||
if exp_type != table.void_type {
|
||||
exp_sym := g.table.get_type_symbol(exp_type)
|
||||
|
@ -672,7 +672,7 @@ fn (var g Gen) expr_with_cast(expr ast.Expr, got_type, exp_type table.Type) {
|
|||
g.expr(expr)
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_assert_stmt(a ast.AssertStmt) {
|
||||
fn (mut g Gen) gen_assert_stmt(a ast.AssertStmt) {
|
||||
g.writeln('// assert')
|
||||
g.inside_ternary = true
|
||||
g.write('if (')
|
||||
|
@ -680,7 +680,7 @@ fn (var g Gen) gen_assert_stmt(a ast.AssertStmt) {
|
|||
g.write(')')
|
||||
g.inside_ternary = false
|
||||
s_assertion := a.expr.str().replace('"', "\'")
|
||||
var mod_path := g.file.path
|
||||
mut mod_path := g.file.path
|
||||
$if windows {
|
||||
mod_path = g.file.path.replace('\\', '\\\\')
|
||||
}
|
||||
|
@ -703,15 +703,15 @@ fn (var g Gen) gen_assert_stmt(a ast.AssertStmt) {
|
|||
g.writeln('}')
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
// g.write('/*assign_stmt*/')
|
||||
if assign_stmt.is_static {
|
||||
g.write('static ')
|
||||
}
|
||||
if assign_stmt.left.len > assign_stmt.right.len {
|
||||
// multi return
|
||||
var or_stmts := []ast.Stmt
|
||||
var return_type := table.void_type
|
||||
mut or_stmts := []ast.Stmt
|
||||
mut return_type := table.void_type
|
||||
match assign_stmt.right[0] {
|
||||
ast.CallExpr {
|
||||
or_stmts = it.or_block.stmts
|
||||
|
@ -753,9 +753,9 @@ fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
val := assign_stmt.right[i]
|
||||
ident_var_info := ident.var_info()
|
||||
styp := g.typ(ident_var_info.typ)
|
||||
var is_call := false
|
||||
var or_stmts := []ast.Stmt
|
||||
var return_type := table.void_type
|
||||
mut is_call := false
|
||||
mut or_stmts := []ast.Stmt
|
||||
mut return_type := table.void_type
|
||||
match val {
|
||||
ast.CallExpr {
|
||||
is_call = true
|
||||
|
@ -776,7 +776,7 @@ fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
}
|
||||
} else {
|
||||
right_sym := g.table.get_type_symbol(assign_stmt.right_types[i])
|
||||
var is_fixed_array_init := false
|
||||
mut is_fixed_array_init := false
|
||||
match val {
|
||||
ast.ArrayInit { is_fixed_array_init = it.is_fixed }
|
||||
else {}
|
||||
|
@ -814,8 +814,8 @@ fn (var g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool {
|
||||
var is_ident := false
|
||||
fn (mut g Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool {
|
||||
mut is_ident := false
|
||||
match val {
|
||||
ast.Ident { is_ident = true }
|
||||
ast.SelectorExpr { is_ident = true }
|
||||
|
@ -841,7 +841,7 @@ fn (var g Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, ad
|
|||
return true
|
||||
}
|
||||
|
||||
fn (var g Gen) free_scope_vars(pos int) {
|
||||
fn (mut g Gen) free_scope_vars(pos int) {
|
||||
scope := g.file.scope.innermost(pos)
|
||||
for _, obj in scope.objects {
|
||||
match obj {
|
||||
|
@ -882,7 +882,7 @@ fn (var g Gen) free_scope_vars(pos int) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) expr(node ast.Expr) {
|
||||
fn (mut g Gen) expr(node ast.Expr) {
|
||||
// println('cgen expr() line_nr=$node.pos.line_nr')
|
||||
match node {
|
||||
ast.ArrayInit {
|
||||
|
@ -1134,7 +1134,7 @@ fn (var g Gen) expr(node ast.Expr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) typeof_expr(node ast.TypeOf) {
|
||||
fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||
sym := g.table.get_type_symbol(node.expr_type)
|
||||
if sym.kind == .sum_type {
|
||||
// When encountering a .sum_type, typeof() should be done at runtime,
|
||||
|
@ -1150,7 +1150,7 @@ fn (var g Gen) typeof_expr(node ast.TypeOf) {
|
|||
} else if sym.kind == .function {
|
||||
info := sym.info as table.FnType
|
||||
fn_info := info.func
|
||||
var repr := 'fn ('
|
||||
mut repr := 'fn ('
|
||||
for i, arg in fn_info.args {
|
||||
if i > 0 {
|
||||
repr += ', '
|
||||
|
@ -1167,18 +1167,18 @@ fn (var g Gen) typeof_expr(node ast.TypeOf) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) enum_expr(node ast.Expr) {
|
||||
fn (mut g Gen) enum_expr(node ast.Expr) {
|
||||
match node {
|
||||
ast.EnumVal { g.write(it.val) }
|
||||
else { g.expr(node) }
|
||||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) assign_expr(node ast.AssignExpr) {
|
||||
fn (mut g Gen) assign_expr(node ast.AssignExpr) {
|
||||
// g.write('/*assign_expr*/')
|
||||
var is_call := false
|
||||
var or_stmts := []ast.Stmt
|
||||
var return_type := table.void_type
|
||||
mut is_call := false
|
||||
mut or_stmts := []ast.Stmt
|
||||
mut return_type := table.void_type
|
||||
match node.val {
|
||||
ast.CallExpr {
|
||||
is_call = true
|
||||
|
@ -1208,7 +1208,7 @@ fn (var g Gen) assign_expr(node ast.AssignExpr) {
|
|||
if table.type_is(node.right_type, .optional) {
|
||||
g.right_is_opt = true
|
||||
}
|
||||
var str_add := false
|
||||
mut str_add := false
|
||||
if node.left_type == table.string_type_idx && node.op == .plus_assign {
|
||||
// str += str2 => `str = string_add(str, str2)`
|
||||
g.expr(node.left)
|
||||
|
@ -1226,7 +1226,7 @@ fn (var g Gen) assign_expr(node ast.AssignExpr) {
|
|||
g.is_assign_lhs = false
|
||||
right_sym := g.table.get_type_symbol(node.right_type)
|
||||
// left_sym := g.table.get_type_symbol(node.left_type)
|
||||
var cloned := false
|
||||
mut cloned := false
|
||||
// !g.is_array_set
|
||||
if g.autofree && right_sym.kind in [.array, .string] {
|
||||
if g.gen_clone_assignment(node.val, right_sym, false) {
|
||||
|
@ -1250,7 +1250,7 @@ fn (var g Gen) assign_expr(node ast.AssignExpr) {
|
|||
g.is_assign_rhs = false
|
||||
}
|
||||
|
||||
fn (var g Gen) infix_expr(node ast.InfixExpr) {
|
||||
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
// println('infix_expr() op="$node.op.str()" line_nr=$node.pos.line_nr')
|
||||
// g.write('/*infix*/')
|
||||
// if it.left_type == table.string_type_idx {
|
||||
|
@ -1400,7 +1400,7 @@ fn (var g Gen) infix_expr(node ast.InfixExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) match_expr(node ast.MatchExpr) {
|
||||
fn (mut g Gen) match_expr(node ast.MatchExpr) {
|
||||
// println('match expr typ=$it.expr_type')
|
||||
// TODO
|
||||
if node.cond_type == 0 {
|
||||
|
@ -1414,7 +1414,7 @@ fn (var g Gen) match_expr(node ast.MatchExpr) {
|
|||
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')
|
||||
}
|
||||
type_sym := g.table.get_type_symbol(node.cond_type)
|
||||
var tmp := ''
|
||||
mut tmp := ''
|
||||
if type_sym.kind != .void {
|
||||
tmp = g.new_tmp_var()
|
||||
}
|
||||
|
@ -1504,7 +1504,7 @@ fn (var g Gen) match_expr(node ast.MatchExpr) {
|
|||
g.inside_ternary = was_inside_ternary
|
||||
}
|
||||
|
||||
fn (var g Gen) ident(node ast.Ident) {
|
||||
fn (mut g Gen) ident(node ast.Ident) {
|
||||
if node.name == 'lld' {
|
||||
return
|
||||
}
|
||||
|
@ -1536,13 +1536,13 @@ fn (var g Gen) ident(node ast.Ident) {
|
|||
g.write(name)
|
||||
}
|
||||
|
||||
fn (var g Gen) if_expr(node ast.IfExpr) {
|
||||
fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
// println('if_expr pos=$node.pos.line_nr')
|
||||
// g.writeln('/* if is_expr=$node.is_expr */')
|
||||
// If expression? Assign the value to a temp var.
|
||||
// Previously ?: was used, but it's too unreliable.
|
||||
type_sym := g.table.get_type_symbol(node.typ)
|
||||
var tmp := ''
|
||||
mut tmp := ''
|
||||
if type_sym.kind != .void {
|
||||
tmp = g.new_tmp_var()
|
||||
// g.writeln('$ti.name $tmp;')
|
||||
|
@ -1567,7 +1567,7 @@ fn (var g Gen) if_expr(node ast.IfExpr) {
|
|||
g.inside_ternary = false
|
||||
} else {
|
||||
guard_ok := g.new_tmp_var()
|
||||
var is_guard := false
|
||||
mut is_guard := false
|
||||
for i, branch in node.branches {
|
||||
if i == 0 {
|
||||
match branch.cond {
|
||||
|
@ -1608,9 +1608,9 @@ fn (var g Gen) if_expr(node ast.IfExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) index_expr(node ast.IndexExpr) {
|
||||
fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
||||
// TODO else doesn't work with sum types
|
||||
var is_range := false
|
||||
mut is_range := false
|
||||
match node.index {
|
||||
ast.RangeExpr {
|
||||
sym := g.table.get_type_symbol(node.left_type)
|
||||
|
@ -1677,7 +1677,7 @@ fn (var g Gen) index_expr(node ast.IndexExpr) {
|
|||
g.expr(node.left)
|
||||
g.write(', ')
|
||||
g.expr(node.index)
|
||||
var need_wrapper := true
|
||||
mut need_wrapper := true
|
||||
/*
|
||||
match node.right {
|
||||
ast.EnumVal, ast.Ident {
|
||||
|
@ -1772,7 +1772,7 @@ fn (var g Gen) index_expr(node ast.IndexExpr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) return_statement(node ast.Return) {
|
||||
fn (mut g Gen) return_statement(node ast.Return) {
|
||||
g.write('return')
|
||||
if g.fn_decl.name == 'main' {
|
||||
g.writeln(' 0;')
|
||||
|
@ -1784,10 +1784,10 @@ fn (var g Gen) return_statement(node ast.Return) {
|
|||
g.write(' ')
|
||||
typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
||||
mr_info := typ_sym.info as table.MultiReturn
|
||||
var styp := g.typ(g.fn_decl.return_type)
|
||||
mut styp := g.typ(g.fn_decl.return_type)
|
||||
if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] !=
|
||||
styp = styp[7..] // remove 'Option_'
|
||||
var x := styp
|
||||
mut x := styp
|
||||
if x.ends_with('_ptr') {
|
||||
x = x.replace('_ptr', '*')
|
||||
}
|
||||
|
@ -1812,8 +1812,8 @@ fn (var g Gen) return_statement(node ast.Return) {
|
|||
// `return opt_ok(expr)` for functions that expect an optional
|
||||
if fn_return_is_optional && !table.type_is(node.types[0], .optional) && return_sym.name !=
|
||||
'Option' {
|
||||
var is_none := false
|
||||
var is_error := false
|
||||
mut is_none := false
|
||||
mut is_error := false
|
||||
expr0 := node.exprs[0]
|
||||
match expr0 {
|
||||
ast.None {
|
||||
|
@ -1828,7 +1828,7 @@ fn (var g Gen) return_statement(node ast.Return) {
|
|||
}
|
||||
if !is_none && !is_error {
|
||||
styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_'
|
||||
var x := styp
|
||||
mut x := styp
|
||||
if x.ends_with('_ptr') {
|
||||
x = x.replace('_ptr', '*')
|
||||
}
|
||||
|
@ -1848,7 +1848,7 @@ fn (var g Gen) return_statement(node ast.Return) {
|
|||
g.writeln(';')
|
||||
}
|
||||
|
||||
fn (var g Gen) const_decl(node ast.ConstDecl) {
|
||||
fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||
for i, field in node.fields {
|
||||
name := c_name(field.name)
|
||||
// TODO hack. Cut the generated value and paste it into definitions.
|
||||
|
@ -1899,7 +1899,7 @@ fn (var g Gen) const_decl(node ast.ConstDecl) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) const_decl_simple_define(name, val string) {
|
||||
fn (mut g Gen) const_decl_simple_define(name, val string) {
|
||||
// Simple expressions should use a #define
|
||||
// so that we don't pollute the binary with unnecessary global vars
|
||||
// Do not do this when building a module, otherwise the consts
|
||||
|
@ -1908,9 +1908,9 @@ fn (var g Gen) const_decl_simple_define(name, val string) {
|
|||
g.definitions.writeln(val)
|
||||
}
|
||||
|
||||
fn (var g Gen) struct_init(struct_init ast.StructInit) {
|
||||
var info := table.Struct{}
|
||||
var is_struct := false
|
||||
fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
||||
mut info := table.Struct{}
|
||||
mut is_struct := false
|
||||
sym := g.table.get_type_symbol(struct_init.typ)
|
||||
if sym.kind == .struct_ {
|
||||
is_struct = true
|
||||
|
@ -1927,7 +1927,7 @@ fn (var g Gen) struct_init(struct_init ast.StructInit) {
|
|||
g.writeln('($styp){')
|
||||
}
|
||||
// var fields := []string
|
||||
var inited_fields := []string // TODO this is done in checker, move to ast node
|
||||
mut inited_fields := []string // TODO this is done in checker, move to ast node
|
||||
/*
|
||||
if struct_init.fields.len == 0 && struct_init.exprs.len > 0 {
|
||||
// Get fields for {a,b} short syntax. Fields array wasn't set in the parser.
|
||||
|
@ -1976,7 +1976,7 @@ fn (var g Gen) struct_init(struct_init ast.StructInit) {
|
|||
}
|
||||
|
||||
// { user | name: 'new name' }
|
||||
fn (var g Gen) assoc(node ast.Assoc) {
|
||||
fn (mut g Gen) assoc(node ast.Assoc) {
|
||||
g.writeln('// assoc')
|
||||
if node.typ == 0 {
|
||||
return
|
||||
|
@ -2005,7 +2005,7 @@ fn (var g Gen) assoc(node ast.Assoc) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &table.TypeSymbol) {
|
||||
fn (mut g Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &table.TypeSymbol) {
|
||||
g.array_fn_definitions << ptr_typ
|
||||
g.definitions.writeln('bool ${ptr_typ}_arr_eq(array_${ptr_typ} a, array_${ptr_typ} b) {')
|
||||
g.definitions.writeln('\tif (a.len != b.len) {')
|
||||
|
@ -2030,7 +2030,7 @@ fn verror(s string) {
|
|||
util.verror('cgen error', s)
|
||||
}
|
||||
|
||||
fn (var g Gen) write_init_function() {
|
||||
fn (mut g Gen) write_init_function() {
|
||||
g.writeln('void _vinit() {')
|
||||
g.writeln('\tbuiltin_init();')
|
||||
g.writeln('\tvinit_string_literals();')
|
||||
|
@ -2056,7 +2056,7 @@ fn (var g Gen) write_init_function() {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) write_str_fn_definitions() {
|
||||
fn (mut g Gen) write_str_fn_definitions() {
|
||||
// _STR function can't be defined in vlib
|
||||
g.writeln('
|
||||
string _STR(const char *fmt, ...) {
|
||||
|
@ -2097,8 +2097,8 @@ const (
|
|||
builtins = ['string', 'array', 'KeyValue', 'DenseArray', 'map', 'Option']
|
||||
)
|
||||
|
||||
fn (var g Gen) write_builtin_types() {
|
||||
var builtin_types := []table.TypeSymbol // builtin types
|
||||
fn (mut g Gen) write_builtin_types() {
|
||||
mut builtin_types := []table.TypeSymbol // builtin types
|
||||
// builtin types need to be on top
|
||||
// everything except builtin will get sorted
|
||||
for builtin_name in builtins {
|
||||
|
@ -2110,8 +2110,8 @@ fn (var g Gen) write_builtin_types() {
|
|||
// C struct definitions, ordered
|
||||
// Sort the types, make sure types that are referenced by other types
|
||||
// are added before them.
|
||||
fn (var g Gen) write_sorted_types() {
|
||||
var types := []table.TypeSymbol // structs that need to be sorted
|
||||
fn (mut g Gen) write_sorted_types() {
|
||||
mut types := []table.TypeSymbol // structs that need to be sorted
|
||||
for typ in g.table.types {
|
||||
if !(typ.name in builtins) {
|
||||
types << typ
|
||||
|
@ -2125,7 +2125,7 @@ fn (var g Gen) write_sorted_types() {
|
|||
g.write_types(types_sorted)
|
||||
}
|
||||
|
||||
fn (var g Gen) write_types(types []table.TypeSymbol) {
|
||||
fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
||||
for typ in types {
|
||||
if typ.name.starts_with('C.') {
|
||||
continue
|
||||
|
@ -2169,7 +2169,7 @@ int typ;
|
|||
// .array_fixed {
|
||||
styp := typ.name.replace('.', '__')
|
||||
// array_fixed_char_300 => char x[300]
|
||||
var fixed := styp[12..]
|
||||
mut fixed := styp[12..]
|
||||
len := styp.after('_')
|
||||
fixed = fixed[..fixed.len - len.len - 1]
|
||||
g.definitions.writeln('typedef $fixed $styp [$len];')
|
||||
|
@ -2182,16 +2182,16 @@ int typ;
|
|||
|
||||
// sort structs by dependant fields
|
||||
fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
||||
var dep_graph := depgraph.new_dep_graph()
|
||||
mut dep_graph := depgraph.new_dep_graph()
|
||||
// types name list
|
||||
var type_names := []string
|
||||
mut type_names := []string
|
||||
for typ in typesa {
|
||||
type_names << typ.name
|
||||
}
|
||||
// loop over types
|
||||
for t in typesa {
|
||||
// create list of deps
|
||||
var field_deps := []string
|
||||
mut field_deps := []string
|
||||
match t.info {
|
||||
table.ArrayFixed {
|
||||
dep := g.table.get_type_symbol(it.elem_type).name
|
||||
|
@ -2224,14 +2224,14 @@ fn (g Gen) sort_structs(typesa []table.TypeSymbol) []table.TypeSymbol {
|
|||
'\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro')
|
||||
}
|
||||
// sort types
|
||||
var types_sorted := []table.TypeSymbol
|
||||
mut types_sorted := []table.TypeSymbol
|
||||
for node in dep_graph_sorted.nodes {
|
||||
types_sorted << g.table.types[g.table.type_idxs[node.name]]
|
||||
}
|
||||
return types_sorted
|
||||
}
|
||||
|
||||
fn (var g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||
fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||
g.write('_STR("')
|
||||
// Build the string with %
|
||||
for i, val in node.vals {
|
||||
|
@ -2353,7 +2353,7 @@ fn (var g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
|||
}
|
||||
|
||||
// `nums.filter(it % 2 == 0)`
|
||||
fn (var g Gen) gen_filter(node ast.CallExpr) {
|
||||
fn (mut g Gen) gen_filter(node ast.CallExpr) {
|
||||
tmp := g.new_tmp_var()
|
||||
s := g.out.after(g.stmt_start_pos) // the already generated part of current statement
|
||||
g.out.go_back(s.len)
|
||||
|
@ -2381,7 +2381,7 @@ fn (var g Gen) gen_filter(node ast.CallExpr) {
|
|||
g.write(tmp)
|
||||
}
|
||||
|
||||
fn (var g Gen) insert_before(s string) {
|
||||
fn (mut g Gen) insert_before(s string) {
|
||||
cur_line := g.out.after(g.stmt_start_pos)
|
||||
g.out.go_back(cur_line.len)
|
||||
g.writeln(s)
|
||||
|
@ -2392,7 +2392,7 @@ fn (var g Gen) insert_before(s string) {
|
|||
// If the user is not using the optional return value. We need to pass a temp var
|
||||
// to access its fields (`.ok`, `.error` etc)
|
||||
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }`
|
||||
fn (var g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) {
|
||||
fn (mut g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) {
|
||||
mr_styp := g.typ(return_type)
|
||||
mr_styp2 := mr_styp[7..] // remove Option_
|
||||
g.writeln(';') // or')
|
||||
|
@ -2415,9 +2415,9 @@ fn (var g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Typ
|
|||
g.write('}')
|
||||
}
|
||||
|
||||
fn (var g Gen) type_of_last_statement(stmts []ast.Stmt) (string, string) {
|
||||
var last_type := ''
|
||||
var last_expr_result_type := ''
|
||||
fn (mut g Gen) type_of_last_statement(stmts []ast.Stmt) (string, string) {
|
||||
mut last_type := ''
|
||||
mut last_expr_result_type := ''
|
||||
if stmts.len > 0 {
|
||||
last_stmt := stmts[stmts.len - 1]
|
||||
last_type = typeof(last_stmt)
|
||||
|
@ -2443,7 +2443,7 @@ fn (var g Gen) type_of_last_statement(stmts []ast.Stmt) (string, string) {
|
|||
return last_type, last_expr_result_type
|
||||
}
|
||||
|
||||
fn (var g Gen) type_of_call_expr(node ast.Expr) string {
|
||||
fn (mut g Gen) type_of_call_expr(node ast.Expr) string {
|
||||
match node {
|
||||
ast.CallExpr { return g.typ(it.return_type) }
|
||||
else { return typeof(node) }
|
||||
|
@ -2452,7 +2452,7 @@ fn (var g Gen) type_of_call_expr(node ast.Expr) string {
|
|||
}
|
||||
|
||||
// `a in [1,2,3]` => `a == 1 || a == 2 || a == 3`
|
||||
fn (var g Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
|
||||
fn (mut g Gen) in_optimization(left ast.Expr, right ast.ArrayInit) {
|
||||
is_str := right.elem_type == table.string_type
|
||||
for i, array_expr in right.exprs {
|
||||
if is_str {
|
||||
|
@ -2599,7 +2599,7 @@ fn (g Gen) type_default(typ table.Type) string {
|
|||
*/
|
||||
}
|
||||
|
||||
pub fn (var g Gen) write_tests_main() {
|
||||
pub fn (mut g Gen) write_tests_main() {
|
||||
g.definitions.writeln('int g_test_oks = 0;')
|
||||
g.definitions.writeln('int g_test_fails = 0;')
|
||||
$if windows {
|
||||
|
@ -2636,9 +2636,9 @@ pub fn (var g Gen) write_tests_main() {
|
|||
}
|
||||
|
||||
fn (g Gen) get_all_test_function_names() []string {
|
||||
var tfuncs := []string
|
||||
var tsuite_begin := ''
|
||||
var tsuite_end := ''
|
||||
mut tfuncs := []string
|
||||
mut tsuite_begin := ''
|
||||
mut tsuite_end := ''
|
||||
for _, f in g.table.fns {
|
||||
if f.name == 'testsuite_begin' {
|
||||
tsuite_begin = f.name
|
||||
|
@ -2667,7 +2667,7 @@ fn (g Gen) get_all_test_function_names() []string {
|
|||
continue
|
||||
}
|
||||
}
|
||||
var all_tfuncs := []string
|
||||
mut all_tfuncs := []string
|
||||
if tsuite_begin.len > 0 {
|
||||
all_tfuncs << tsuite_begin
|
||||
}
|
||||
|
@ -2675,7 +2675,7 @@ fn (g Gen) get_all_test_function_names() []string {
|
|||
if tsuite_end.len > 0 {
|
||||
all_tfuncs << tsuite_end
|
||||
}
|
||||
var all_tfuncs_c := []string
|
||||
mut all_tfuncs_c := []string
|
||||
for f in all_tfuncs {
|
||||
all_tfuncs_c << f.replace('.', '__')
|
||||
}
|
||||
|
@ -2686,7 +2686,7 @@ fn (g Gen) is_importing_os() bool {
|
|||
return 'os' in g.table.imports
|
||||
}
|
||||
|
||||
fn (var g Gen) comp_if(it ast.CompIf) {
|
||||
fn (mut g Gen) comp_if(it ast.CompIf) {
|
||||
ifdef := comp_if_to_ifdef(it.val)
|
||||
if it.is_not {
|
||||
g.writeln('\n#ifndef ' + ifdef)
|
||||
|
@ -2718,12 +2718,12 @@ fn (var g Gen) comp_if(it ast.CompIf) {
|
|||
g.writeln('\n#endif')
|
||||
}
|
||||
|
||||
fn (var g Gen) go_stmt(node ast.GoStmt) {
|
||||
fn (mut g Gen) go_stmt(node ast.GoStmt) {
|
||||
tmp := g.new_tmp_var()
|
||||
// x := node.call_expr as ast.CallEpxr // TODO
|
||||
match node.call_expr {
|
||||
ast.CallExpr {
|
||||
var name := it.name.replace('.', '__')
|
||||
mut name := it.name.replace('.', '__')
|
||||
if it.is_method {
|
||||
receiver_sym := g.table.get_type_symbol(it.receiver_type)
|
||||
name = receiver_sym.name + '_' + name
|
||||
|
@ -2788,14 +2788,14 @@ fn (var g Gen) go_stmt(node ast.GoStmt) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) is_expr(node ast.InfixExpr) {
|
||||
fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||
g.expr(node.left)
|
||||
g.write('.typ == ')
|
||||
g.expr(node.right)
|
||||
}
|
||||
|
||||
// already generated styp, reuse it
|
||||
fn (var g Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
|
||||
fn (mut g Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
|
||||
if sym.has_method('str') || styp in g.str_types {
|
||||
return
|
||||
}
|
||||
|
@ -2809,9 +2809,9 @@ fn (var g Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_str_default(sym table.TypeSymbol, styp string) {
|
||||
var convertor := ''
|
||||
var typename := ''
|
||||
fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string) {
|
||||
mut convertor := ''
|
||||
mut typename := ''
|
||||
if sym.parent_idx in table.integer_type_idxs {
|
||||
convertor = 'int'
|
||||
typename = 'int'
|
||||
|
@ -2839,7 +2839,7 @@ fn (var g Gen) gen_str_default(sym table.TypeSymbol, styp string) {
|
|||
g.definitions.writeln('}')
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_str_for_enum(info table.Enum, styp string) {
|
||||
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string) {
|
||||
s := styp.replace('.', '__')
|
||||
g.definitions.write('string ${s}_str($styp it) {\n\tswitch(it) {\n')
|
||||
for i, val in info.vals {
|
||||
|
@ -2848,7 +2848,7 @@ fn (var g Gen) gen_str_for_enum(info table.Enum, styp string) {
|
|||
g.definitions.write('\t\tdefault: return tos3("unknown enum value"); } }\n')
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_str_for_struct(info table.Struct, styp string) {
|
||||
fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string) {
|
||||
// TODO: short it if possible
|
||||
// generates all definitions of substructs
|
||||
for i, field in info.fields {
|
||||
|
@ -2892,7 +2892,7 @@ fn (var g Gen) gen_str_for_struct(info table.Struct, styp string) {
|
|||
g.definitions.writeln(', indents.len, indents.str);\n}')
|
||||
}
|
||||
|
||||
fn (var g Gen) gen_str_for_array(info table.Array, styp string) {
|
||||
fn (mut g Gen) gen_str_for_array(info table.Array, styp string) {
|
||||
s := styp.replace('.', '__')
|
||||
sym := g.table.get_type_symbol(info.elem_type)
|
||||
field_styp := g.typ(info.elem_type)
|
||||
|
|
|
@ -9,7 +9,7 @@ import v.scanner
|
|||
import v.token
|
||||
import v.util
|
||||
|
||||
pub fn (var p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
||||
pub fn (mut p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
||||
first_pos := p.tok.position()
|
||||
tok := p.tok
|
||||
name := p.check_name()
|
||||
|
@ -31,8 +31,8 @@ pub fn (var p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
|||
pos: first_pos.pos
|
||||
len: last_pos.pos - first_pos.pos + last_pos.len
|
||||
}
|
||||
var or_stmts := []ast.Stmt
|
||||
var is_or_block_used := false
|
||||
mut or_stmts := []ast.Stmt
|
||||
mut is_or_block_used := false
|
||||
if p.tok.kind == .key_orelse {
|
||||
p.next()
|
||||
p.open_scope()
|
||||
|
@ -63,10 +63,10 @@ pub fn (var p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
|||
return node
|
||||
}
|
||||
|
||||
pub fn (var p Parser) call_args() []ast.CallArg {
|
||||
var args := []ast.CallArg
|
||||
pub fn (mut p Parser) call_args() []ast.CallArg {
|
||||
mut args := []ast.CallArg
|
||||
for p.tok.kind != .rpar {
|
||||
var is_mut := false
|
||||
mut is_mut := false
|
||||
if p.tok.kind == .key_mut {
|
||||
p.check(.key_mut)
|
||||
is_mut = true
|
||||
|
@ -83,7 +83,7 @@ pub fn (var p Parser) call_args() []ast.CallArg {
|
|||
return args
|
||||
}
|
||||
|
||||
fn (var p Parser) fn_decl() ast.FnDecl {
|
||||
fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
// p.table.clear_vars()
|
||||
start_pos := p.tok.position()
|
||||
p.open_scope()
|
||||
|
@ -101,11 +101,11 @@ fn (var p Parser) fn_decl() ast.FnDecl {
|
|||
p.check(.dot)
|
||||
}
|
||||
// Receiver?
|
||||
var rec_name := ''
|
||||
var is_method := false
|
||||
var rec_type := table.void_type
|
||||
var rec_mut := false
|
||||
var args := []table.Arg
|
||||
mut rec_name := ''
|
||||
mut is_method := false
|
||||
mut rec_type := table.void_type
|
||||
mut rec_mut := false
|
||||
mut args := []table.Arg
|
||||
if p.tok.kind == .lpar {
|
||||
p.next() // (
|
||||
is_method = true
|
||||
|
@ -134,7 +134,7 @@ fn (var p Parser) fn_decl() ast.FnDecl {
|
|||
}
|
||||
p.check(.rpar)
|
||||
}
|
||||
var name := ''
|
||||
mut name := ''
|
||||
if p.tok.kind == .name {
|
||||
// TODO high order fn
|
||||
name = p.check_name()
|
||||
|
@ -165,16 +165,16 @@ fn (var p Parser) fn_decl() ast.FnDecl {
|
|||
typ: arg.typ
|
||||
})
|
||||
}
|
||||
var end_pos := p.prev_tok.position()
|
||||
mut end_pos := p.prev_tok.position()
|
||||
// Return type
|
||||
var return_type := table.void_type
|
||||
mut return_type := table.void_type
|
||||
if p.tok.kind.is_start_of_type() {
|
||||
end_pos = p.tok.position()
|
||||
return_type = p.parse_type()
|
||||
}
|
||||
// Register
|
||||
if is_method {
|
||||
var type_sym := p.table.get_type_symbol(rec_type)
|
||||
mut type_sym := p.table.get_type_symbol(rec_type)
|
||||
// p.warn('reg method $type_sym.name . $name ()')
|
||||
type_sym.register_method(table.Fn{
|
||||
name: name
|
||||
|
@ -207,7 +207,7 @@ fn (var p Parser) fn_decl() ast.FnDecl {
|
|||
})
|
||||
}
|
||||
// Body
|
||||
var stmts := []ast.Stmt
|
||||
mut stmts := []ast.Stmt
|
||||
no_body := p.tok.kind != .lcbr
|
||||
if p.tok.kind == .lcbr {
|
||||
stmts = p.parse_block()
|
||||
|
@ -236,7 +236,7 @@ fn (var p Parser) fn_decl() ast.FnDecl {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) anon_fn() ast.AnonFn {
|
||||
fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||
pos := p.tok.position()
|
||||
p.open_scope()
|
||||
p.check(.key_fn)
|
||||
|
@ -248,11 +248,11 @@ fn (var p Parser) anon_fn() ast.AnonFn {
|
|||
typ: arg.typ
|
||||
})
|
||||
}
|
||||
var return_type := table.void_type
|
||||
mut return_type := table.void_type
|
||||
if p.tok.kind.is_start_of_type() {
|
||||
return_type = p.parse_type()
|
||||
}
|
||||
var stmts := []ast.Stmt
|
||||
mut stmts := []ast.Stmt
|
||||
no_body := p.tok.kind != .lcbr
|
||||
if p.tok.kind == .lcbr {
|
||||
stmts = p.parse_block()
|
||||
|
@ -282,16 +282,16 @@ fn (var p Parser) anon_fn() ast.AnonFn {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) fn_args() ([]table.Arg, bool) {
|
||||
fn (mut p Parser) fn_args() ([]table.Arg, bool) {
|
||||
p.check(.lpar)
|
||||
var args := []table.Arg
|
||||
var is_variadic := false
|
||||
mut args := []table.Arg
|
||||
mut is_variadic := false
|
||||
// `int, int, string` (no names, just types)
|
||||
types_only := p.tok.kind in [.amp, .and] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) ||
|
||||
p.peek_tok.kind == .rpar
|
||||
if types_only {
|
||||
// p.warn('types only')
|
||||
var arg_no := 1
|
||||
mut arg_no := 1
|
||||
for p.tok.kind != .rpar {
|
||||
arg_name := 'arg_$arg_no'
|
||||
is_mut := p.tok.kind == .key_mut
|
||||
|
@ -302,7 +302,7 @@ fn (var p Parser) fn_args() ([]table.Arg, bool) {
|
|||
p.check(.ellipsis)
|
||||
is_variadic = true
|
||||
}
|
||||
var arg_type := p.parse_type()
|
||||
mut arg_type := p.parse_type()
|
||||
if is_variadic {
|
||||
arg_type = table.type_set(arg_type, .variadic)
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ fn (var p Parser) fn_args() ([]table.Arg, bool) {
|
|||
}
|
||||
} else {
|
||||
for p.tok.kind != .rpar {
|
||||
var arg_names := [p.check_name()]
|
||||
mut arg_names := [p.check_name()]
|
||||
// `a, b, c int`
|
||||
for p.tok.kind == .comma {
|
||||
p.check(.comma)
|
||||
|
@ -335,7 +335,7 @@ fn (var p Parser) fn_args() ([]table.Arg, bool) {
|
|||
p.check(.ellipsis)
|
||||
is_variadic = true
|
||||
}
|
||||
var typ := p.parse_type()
|
||||
mut typ := p.parse_type()
|
||||
if is_variadic {
|
||||
typ = table.type_set(typ, .variadic)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ mut:
|
|||
// for tests
|
||||
pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
|
||||
s := scanner.new_scanner(text, .skip_comments)
|
||||
var p := Parser{
|
||||
mut p := Parser{
|
||||
scanner: s
|
||||
table: table
|
||||
pref: &pref.Preferences{}
|
||||
|
@ -66,8 +66,8 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
|
|||
// text := os.read_file(path) or {
|
||||
// panic(err)
|
||||
// }
|
||||
var stmts := []ast.Stmt
|
||||
var p := Parser{
|
||||
mut stmts := []ast.Stmt
|
||||
mut p := Parser{
|
||||
scanner: scanner.new_scanner_file(path, comments_mode)
|
||||
table: table
|
||||
file_name: path
|
||||
|
@ -82,12 +82,12 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
|
|||
// comments_mode: comments_mode
|
||||
p.read_first_token()
|
||||
for p.tok.kind == .comment {
|
||||
var stmt := ast.Stmt{} // TODO sum type << bug
|
||||
mut stmt := ast.Stmt{} // TODO sum type << bug
|
||||
com := p.comment()
|
||||
stmt = com
|
||||
stmts << stmt
|
||||
}
|
||||
var mstmt := ast.Stmt{}
|
||||
mut mstmt := ast.Stmt{}
|
||||
module_decl := p.module_decl()
|
||||
mstmt = module_decl
|
||||
stmts << mstmt
|
||||
|
@ -164,7 +164,7 @@ pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, g
|
|||
return q.parsed_ast_files
|
||||
*/
|
||||
// ///////////////
|
||||
var files := []ast.File
|
||||
mut files := []ast.File
|
||||
for path in paths {
|
||||
// println('parse_files $path')
|
||||
files << parse_file(path, table, .skip_comments, pref, global_scope)
|
||||
|
@ -178,26 +178,26 @@ pub fn (p &Parser) init_parse_fns() {
|
|||
println('')
|
||||
}
|
||||
|
||||
pub fn (var p Parser) read_first_token() {
|
||||
pub fn (mut p Parser) read_first_token() {
|
||||
// need to call next() twice to get peek token and current token
|
||||
p.next()
|
||||
p.next()
|
||||
}
|
||||
|
||||
pub fn (var p Parser) open_scope() {
|
||||
pub fn (mut p Parser) open_scope() {
|
||||
p.scope = &ast.Scope{
|
||||
parent: p.scope
|
||||
start_pos: p.tok.pos
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (var p Parser) close_scope() {
|
||||
pub fn (mut p Parser) close_scope() {
|
||||
p.scope.end_pos = p.tok.pos
|
||||
p.scope.parent.children << p.scope
|
||||
p.scope = p.scope.parent
|
||||
}
|
||||
|
||||
pub fn (var p Parser) parse_block() []ast.Stmt {
|
||||
pub fn (mut p Parser) parse_block() []ast.Stmt {
|
||||
p.open_scope()
|
||||
// println('parse block')
|
||||
stmts := p.parse_block_no_scope()
|
||||
|
@ -206,9 +206,9 @@ pub fn (var p Parser) parse_block() []ast.Stmt {
|
|||
return stmts
|
||||
}
|
||||
|
||||
pub fn (var p Parser) parse_block_no_scope() []ast.Stmt {
|
||||
pub fn (mut p Parser) parse_block_no_scope() []ast.Stmt {
|
||||
p.check(.lcbr)
|
||||
var stmts := []ast.Stmt
|
||||
mut stmts := []ast.Stmt
|
||||
if p.tok.kind != .rcbr {
|
||||
for {
|
||||
stmts << p.stmt()
|
||||
|
@ -228,7 +228,7 @@ fn (p mut Parser) next_with_comment() {
|
|||
p.peek_tok = p.scanner.scan()
|
||||
}
|
||||
*/
|
||||
fn (var p Parser) next() {
|
||||
fn (mut p Parser) next() {
|
||||
p.prev_tok = p.tok
|
||||
p.tok = p.peek_tok
|
||||
p.peek_tok = p.scanner.scan()
|
||||
|
@ -240,7 +240,7 @@ fn (var p Parser) next() {
|
|||
*/
|
||||
}
|
||||
|
||||
fn (var p Parser) check(expected token.Kind) {
|
||||
fn (mut p Parser) check(expected token.Kind) {
|
||||
// for p.tok.kind in [.line_comment, .mline_comment] {
|
||||
// p.next()
|
||||
// }
|
||||
|
@ -250,13 +250,13 @@ fn (var p Parser) check(expected token.Kind) {
|
|||
p.next()
|
||||
}
|
||||
|
||||
fn (var p Parser) check_name() string {
|
||||
fn (mut p Parser) check_name() string {
|
||||
name := p.tok.lit
|
||||
p.check(.name)
|
||||
return name
|
||||
}
|
||||
|
||||
pub fn (var p Parser) top_stmt() ast.Stmt {
|
||||
pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||
match p.tok.kind {
|
||||
.key_pub {
|
||||
match p.peek_tok.kind {
|
||||
|
@ -339,14 +339,14 @@ pub fn (var p Parser) top_stmt() ast.Stmt {
|
|||
}
|
||||
|
||||
// TODO [if vfmt]
|
||||
pub fn (var p Parser) check_comment() ast.Comment {
|
||||
pub fn (mut p Parser) check_comment() ast.Comment {
|
||||
if p.tok.kind == .comment {
|
||||
return p.comment()
|
||||
}
|
||||
return ast.Comment{}
|
||||
}
|
||||
|
||||
pub fn (var p Parser) comment() ast.Comment {
|
||||
pub fn (mut p Parser) comment() ast.Comment {
|
||||
pos := p.tok.position()
|
||||
text := p.tok.lit
|
||||
p.next()
|
||||
|
@ -357,7 +357,7 @@ pub fn (var p Parser) comment() ast.Comment {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (var p Parser) stmt() ast.Stmt {
|
||||
pub fn (mut p Parser) stmt() ast.Stmt {
|
||||
p.is_stmt_ident = p.tok.kind == .name
|
||||
match p.tok.kind {
|
||||
.lcbr {
|
||||
|
@ -456,12 +456,12 @@ pub fn (var p Parser) stmt() ast.Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) attribute() ast.Attr {
|
||||
fn (mut p Parser) attribute() ast.Attr {
|
||||
p.check(.lsbr)
|
||||
if p.tok.kind == .key_if {
|
||||
p.next()
|
||||
}
|
||||
var name := p.check_name()
|
||||
mut name := p.check_name()
|
||||
if p.tok.kind == .colon {
|
||||
p.next()
|
||||
if p.tok.kind == .name {
|
||||
|
@ -508,7 +508,7 @@ pub fn (p &Parser) warn(s string) {
|
|||
}
|
||||
|
||||
pub fn (p &Parser) error_with_pos(s string, pos token.Position) {
|
||||
var kind := 'error:'
|
||||
mut kind := 'error:'
|
||||
if p.pref.is_verbose {
|
||||
print_backtrace()
|
||||
kind = 'parser error:'
|
||||
|
@ -523,10 +523,10 @@ pub fn (p &Parser) warn_with_pos(s string, pos token.Position) {
|
|||
eprintln(ferror)
|
||||
}
|
||||
|
||||
pub fn (var p Parser) parse_ident(is_c, is_js bool) ast.Ident {
|
||||
pub fn (mut p Parser) parse_ident(is_c, is_js bool) ast.Ident {
|
||||
// p.warn('name ')
|
||||
pos := p.tok.position()
|
||||
var name := p.check_name()
|
||||
mut name := p.check_name()
|
||||
if name == '_' {
|
||||
return ast.Ident{
|
||||
name: '_'
|
||||
|
@ -537,7 +537,7 @@ pub fn (var p Parser) parse_ident(is_c, is_js bool) ast.Ident {
|
|||
if p.expr_mod.len > 0 {
|
||||
name = '${p.expr_mod}.$name'
|
||||
}
|
||||
var ident := ast.Ident{
|
||||
mut ident := ast.Ident{
|
||||
kind: .unresolved
|
||||
name: name
|
||||
is_c: is_c
|
||||
|
@ -548,8 +548,8 @@ pub fn (var p Parser) parse_ident(is_c, is_js bool) ast.Ident {
|
|||
return ident
|
||||
}
|
||||
|
||||
pub fn (var p Parser) name_expr() ast.Expr {
|
||||
var node := ast.Expr{}
|
||||
pub fn (mut p Parser) name_expr() ast.Expr {
|
||||
mut node := ast.Expr{}
|
||||
if p.inside_is {
|
||||
p.inside_is = false
|
||||
// get type position before moving to next
|
||||
|
@ -561,7 +561,7 @@ pub fn (var p Parser) name_expr() ast.Expr {
|
|||
}
|
||||
is_c := p.tok.lit == 'C'
|
||||
is_js := p.tok.lit == 'JS'
|
||||
var mod := ''
|
||||
mut mod := ''
|
||||
// p.warn('resetting')
|
||||
p.expr_mod = ''
|
||||
// `map[string]int` initialization
|
||||
|
@ -593,7 +593,7 @@ pub fn (var p Parser) name_expr() ast.Expr {
|
|||
// p.warn('name expr $p.tok.lit $p.peek_tok.str()')
|
||||
// fn call or type cast
|
||||
if p.peek_tok.kind == .lpar {
|
||||
var name := p.tok.lit
|
||||
mut name := p.tok.lit
|
||||
if mod.len > 0 {
|
||||
name = '${mod}.$name'
|
||||
}
|
||||
|
@ -604,15 +604,15 @@ pub fn (var p Parser) name_expr() ast.Expr {
|
|||
'C.sigaction'
|
||||
]) {
|
||||
// TODO handle C.stat()
|
||||
var to_typ := p.parse_type()
|
||||
mut to_typ := p.parse_type()
|
||||
if p.is_amp {
|
||||
// Handle `&Foo(0)`
|
||||
to_typ = table.type_to_ptr(to_typ)
|
||||
}
|
||||
p.check(.lpar)
|
||||
var expr := ast.Expr{}
|
||||
var arg := ast.Expr{}
|
||||
var has_arg := false
|
||||
mut expr := ast.Expr{}
|
||||
mut arg := ast.Expr{}
|
||||
mut has_arg := false
|
||||
expr = p.expr(0)
|
||||
// TODO, string(b, len)
|
||||
if p.tok.kind == .comma && table.type_idx(to_typ) == table.string_type_idx {
|
||||
|
@ -640,7 +640,7 @@ pub fn (var p Parser) name_expr() ast.Expr {
|
|||
return p.struct_init(false) // short_syntax: false
|
||||
} else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) {
|
||||
// `Color.green`
|
||||
var enum_name := p.check_name()
|
||||
mut enum_name := p.check_name()
|
||||
if mod != '' {
|
||||
enum_name = mod + '.' + enum_name
|
||||
} else {
|
||||
|
@ -658,7 +658,7 @@ pub fn (var p Parser) name_expr() ast.Expr {
|
|||
mod: mod
|
||||
}
|
||||
} else {
|
||||
var ident := ast.Ident{}
|
||||
mut ident := ast.Ident{}
|
||||
ident = p.parse_ident(is_c, is_js)
|
||||
node = ident
|
||||
}
|
||||
|
@ -666,10 +666,10 @@ pub fn (var p Parser) name_expr() ast.Expr {
|
|||
return node
|
||||
}
|
||||
|
||||
fn (var p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||
fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||
// left == `a` in `a[0]`
|
||||
p.next() // [
|
||||
var has_low := true
|
||||
mut has_low := true
|
||||
if p.tok.kind == .dotdot {
|
||||
has_low = false
|
||||
// [..end]
|
||||
|
@ -687,11 +687,11 @@ fn (var p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
|||
}
|
||||
}
|
||||
expr := p.expr(0) // `[expr]` or `[expr..]`
|
||||
var has_high := false
|
||||
mut has_high := false
|
||||
if p.tok.kind == .dotdot {
|
||||
// [start..end] or [start..]
|
||||
p.check(.dotdot)
|
||||
var high := ast.Expr{}
|
||||
mut high := ast.Expr{}
|
||||
if p.tok.kind != .rsbr {
|
||||
has_high = true
|
||||
high = p.expr(0)
|
||||
|
@ -717,15 +717,15 @@ fn (var p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) filter() {
|
||||
fn (mut p Parser) filter() {
|
||||
p.scope.register('it', ast.Var{
|
||||
name: 'it'
|
||||
})
|
||||
}
|
||||
|
||||
fn (var p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||
fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||
p.next()
|
||||
var name_pos := p.tok.position()
|
||||
mut name_pos := p.tok.position()
|
||||
field_name := p.check_name()
|
||||
is_filter := field_name in ['filter', 'map']
|
||||
if is_filter {
|
||||
|
@ -742,8 +742,8 @@ fn (var p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||
p.next()
|
||||
args := p.call_args()
|
||||
p.check(.rpar)
|
||||
var or_stmts := []ast.Stmt
|
||||
var is_or_block_used := false
|
||||
mut or_stmts := []ast.Stmt
|
||||
mut is_or_block_used := false
|
||||
if p.tok.kind == .key_orelse {
|
||||
p.next()
|
||||
p.open_scope()
|
||||
|
@ -776,7 +776,7 @@ fn (var p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||
is_used: is_or_block_used
|
||||
}
|
||||
}
|
||||
var node := ast.Expr{}
|
||||
mut node := ast.Expr{}
|
||||
node = mcall_expr
|
||||
if is_filter {
|
||||
p.close_scope()
|
||||
|
@ -788,7 +788,7 @@ fn (var p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||
field: field_name
|
||||
pos: name_pos
|
||||
}
|
||||
var node := ast.Expr{}
|
||||
mut node := ast.Expr{}
|
||||
node = sel_expr
|
||||
if is_filter {
|
||||
p.close_scope()
|
||||
|
@ -798,7 +798,7 @@ fn (var p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||
|
||||
// `.green`
|
||||
// `pref.BuildMode.default_mode`
|
||||
fn (var p Parser) enum_val() ast.EnumVal {
|
||||
fn (mut p Parser) enum_val() ast.EnumVal {
|
||||
p.check(.dot)
|
||||
val := p.check_name()
|
||||
return ast.EnumVal{
|
||||
|
@ -807,13 +807,13 @@ fn (var p Parser) enum_val() ast.EnumVal {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) string_expr() ast.Expr {
|
||||
fn (mut p Parser) string_expr() ast.Expr {
|
||||
is_raw := p.tok.kind == .name && p.tok.lit == 'r'
|
||||
is_cstr := p.tok.kind == .name && p.tok.lit == 'c'
|
||||
if is_raw || is_cstr {
|
||||
p.next()
|
||||
}
|
||||
var node := ast.Expr{}
|
||||
mut node := ast.Expr{}
|
||||
val := p.tok.lit
|
||||
pos := p.tok.position()
|
||||
if p.peek_tok.kind != .str_dollar {
|
||||
|
@ -826,9 +826,9 @@ fn (var p Parser) string_expr() ast.Expr {
|
|||
}
|
||||
return node
|
||||
}
|
||||
var exprs := []ast.Expr
|
||||
var vals := []string
|
||||
var efmts := []string
|
||||
mut exprs := []ast.Expr
|
||||
mut vals := []string
|
||||
mut efmts := []string
|
||||
// Handle $ interpolation
|
||||
for p.tok.kind == .string {
|
||||
vals << p.tok.lit
|
||||
|
@ -838,7 +838,7 @@ fn (var p Parser) string_expr() ast.Expr {
|
|||
}
|
||||
p.check(.str_dollar)
|
||||
exprs << p.expr(0)
|
||||
var efmt := []string
|
||||
mut efmt := []string
|
||||
if p.tok.kind == .colon {
|
||||
efmt << ':'
|
||||
p.next()
|
||||
|
@ -868,10 +868,10 @@ fn (var p Parser) string_expr() ast.Expr {
|
|||
return node
|
||||
}
|
||||
|
||||
fn (var p Parser) parse_number_literal() ast.Expr {
|
||||
fn (mut p Parser) parse_number_literal() ast.Expr {
|
||||
lit := p.tok.lit
|
||||
pos := p.tok.position()
|
||||
var node := ast.Expr{}
|
||||
mut node := ast.Expr{}
|
||||
if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] {
|
||||
node = ast.FloatLiteral{
|
||||
val: lit
|
||||
|
@ -887,8 +887,8 @@ fn (var p Parser) parse_number_literal() ast.Expr {
|
|||
return node
|
||||
}
|
||||
|
||||
fn (var p Parser) module_decl() ast.Module {
|
||||
var name := 'main'
|
||||
fn (mut p Parser) module_decl() ast.Module {
|
||||
mut name := 'main'
|
||||
is_skipped := p.tok.kind != .key_module
|
||||
if !is_skipped {
|
||||
p.check(.key_module)
|
||||
|
@ -903,10 +903,10 @@ fn (var p Parser) module_decl() ast.Module {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) parse_import() ast.Import {
|
||||
fn (mut p Parser) parse_import() ast.Import {
|
||||
pos := p.tok.position()
|
||||
var mod_name := p.check_name()
|
||||
var mod_alias := mod_name
|
||||
mut mod_name := p.check_name()
|
||||
mut mod_alias := mod_name
|
||||
for p.tok.kind == .dot {
|
||||
p.check(.dot)
|
||||
submod_name := p.check_name()
|
||||
|
@ -926,9 +926,9 @@ fn (var p Parser) parse_import() ast.Import {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) import_stmt() []ast.Import {
|
||||
fn (mut p Parser) import_stmt() []ast.Import {
|
||||
p.check(.key_import)
|
||||
var imports := []ast.Import
|
||||
mut imports := []ast.Import
|
||||
if p.tok.kind == .lpar {
|
||||
p.check(.lpar)
|
||||
for p.tok.kind != .rpar {
|
||||
|
@ -945,7 +945,7 @@ fn (var p Parser) import_stmt() []ast.Import {
|
|||
return imports
|
||||
}
|
||||
|
||||
fn (var p Parser) const_decl() ast.ConstDecl {
|
||||
fn (mut p Parser) const_decl() ast.ConstDecl {
|
||||
start_pos := p.tok.position()
|
||||
is_pub := p.tok.kind == .key_pub
|
||||
if is_pub {
|
||||
|
@ -957,7 +957,7 @@ fn (var p Parser) const_decl() ast.ConstDecl {
|
|||
p.error('consts must be grouped, e.g.\nconst (\n\ta = 1\n)')
|
||||
}
|
||||
p.next() // (
|
||||
var fields := []ast.ConstField
|
||||
mut fields := []ast.ConstField
|
||||
for p.tok.kind != .rpar {
|
||||
if p.tok.kind == .comment {
|
||||
p.comment()
|
||||
|
@ -983,11 +983,11 @@ fn (var p Parser) const_decl() ast.ConstDecl {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) return_stmt() ast.Return {
|
||||
fn (mut p Parser) return_stmt() ast.Return {
|
||||
first_pos := p.tok.position()
|
||||
p.next()
|
||||
// return expressions
|
||||
var exprs := []ast.Expr
|
||||
mut exprs := []ast.Expr
|
||||
if p.tok.kind == .rcbr {
|
||||
return ast.Return{
|
||||
pos: first_pos
|
||||
|
@ -1010,7 +1010,7 @@ fn (var p Parser) return_stmt() ast.Return {
|
|||
}
|
||||
|
||||
// left hand side of `=` or `:=` in `a,b,c := 1,2,3`
|
||||
fn (var p Parser) global_decl() ast.GlobalDecl {
|
||||
fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||
if !p.pref.translated && !p.pref.is_live && !p.builtin_mod && !p.pref.building_v && p.mod !=
|
||||
'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals {
|
||||
p.error('use `v --enable-globals ...` to enable globals')
|
||||
|
@ -1019,7 +1019,7 @@ fn (var p Parser) global_decl() ast.GlobalDecl {
|
|||
name := p.check_name()
|
||||
// println(name)
|
||||
typ := p.parse_type()
|
||||
var expr := ast.Expr{}
|
||||
mut expr := ast.Expr{}
|
||||
has_expr := p.tok.kind == .assign
|
||||
if has_expr {
|
||||
p.next()
|
||||
|
@ -1050,7 +1050,7 @@ fn (var p Parser) global_decl() ast.GlobalDecl {
|
|||
return glob
|
||||
}
|
||||
|
||||
fn (var p Parser) enum_decl() ast.EnumDecl {
|
||||
fn (mut p Parser) enum_decl() ast.EnumDecl {
|
||||
is_pub := p.tok.kind == .key_pub
|
||||
start_pos := p.tok.position()
|
||||
if is_pub {
|
||||
|
@ -1060,15 +1060,15 @@ fn (var p Parser) enum_decl() ast.EnumDecl {
|
|||
end_pos := p.tok.position()
|
||||
name := p.prepend_mod(p.check_name())
|
||||
p.check(.lcbr)
|
||||
var vals := []string
|
||||
mut vals := []string
|
||||
// mut default_exprs := []ast.Expr
|
||||
var fields := []ast.EnumField
|
||||
mut fields := []ast.EnumField
|
||||
for p.tok.kind != .eof && p.tok.kind != .rcbr {
|
||||
pos := p.tok.position()
|
||||
val := p.check_name()
|
||||
vals << val
|
||||
var expr := ast.Expr{}
|
||||
var has_expr := false
|
||||
mut expr := ast.Expr{}
|
||||
mut has_expr := false
|
||||
// p.warn('enum val $val')
|
||||
if p.tok.kind == .assign {
|
||||
p.next()
|
||||
|
@ -1105,7 +1105,7 @@ fn (var p Parser) enum_decl() ast.EnumDecl {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) type_decl() ast.TypeDecl {
|
||||
fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||
start_pos := p.tok.position()
|
||||
is_pub := p.tok.kind == .key_pub
|
||||
if is_pub {
|
||||
|
@ -1115,7 +1115,7 @@ fn (var p Parser) type_decl() ast.TypeDecl {
|
|||
end_pos := p.tok.position()
|
||||
decl_pos := start_pos.extend(end_pos)
|
||||
name := p.check_name()
|
||||
var sum_variants := []table.Type
|
||||
mut sum_variants := []table.Type
|
||||
if p.tok.kind == .assign {
|
||||
p.next() // TODO require `=`
|
||||
}
|
||||
|
@ -1176,7 +1176,7 @@ fn (var p Parser) type_decl() ast.TypeDecl {
|
|||
}
|
||||
}
|
||||
|
||||
fn (var p Parser) assoc() ast.Assoc {
|
||||
fn (mut p Parser) assoc() ast.Assoc {
|
||||
var_name := p.check_name()
|
||||
pos := p.tok.position()
|
||||
v := p.scope.find_var(var_name) or {
|
||||
|
@ -1184,8 +1184,8 @@ fn (var p Parser) assoc() ast.Assoc {
|
|||
return ast.Assoc{}
|
||||
}
|
||||
// println('assoc var $name typ=$var.typ')
|
||||
var fields := []string
|
||||
var vals := []ast.Expr
|
||||
mut fields := []string
|
||||
mut vals := []ast.Expr
|
||||
p.check(.pipe)
|
||||
for {
|
||||
fields << p.check_name()
|
||||
|
|
|
@ -7,10 +7,10 @@ import v.ast
|
|||
import v.table
|
||||
import v.token
|
||||
|
||||
pub fn (var p Parser) expr(precedence int) ast.Expr {
|
||||
pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||
// println('\n\nparser.expr()')
|
||||
var typ := table.void_type
|
||||
var node := ast.Expr{}
|
||||
mut typ := table.void_type
|
||||
mut node := ast.Expr{}
|
||||
is_stmt_ident := p.is_stmt_ident
|
||||
p.is_stmt_ident = false
|
||||
// Prefix
|
||||
|
@ -175,19 +175,19 @@ pub fn (var p Parser) expr(precedence int) ast.Expr {
|
|||
return node
|
||||
}
|
||||
|
||||
fn (var p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
|
||||
op := p.tok.kind
|
||||
// mut typ := p.
|
||||
// println('infix op=$op.str()')
|
||||
precedence := p.tok.precedence()
|
||||
pos := p.tok.position()
|
||||
p.next()
|
||||
var right := ast.Expr{}
|
||||
mut right := ast.Expr{}
|
||||
if op == .key_is {
|
||||
p.inside_is = true
|
||||
}
|
||||
right = p.expr(precedence)
|
||||
var expr := ast.Expr{}
|
||||
mut expr := ast.Expr{}
|
||||
expr = ast.InfixExpr{
|
||||
left: left
|
||||
right: right
|
||||
|
@ -197,7 +197,7 @@ fn (var p Parser) infix_expr(left ast.Expr) ast.Expr {
|
|||
return expr
|
||||
}
|
||||
|
||||
fn (var p Parser) prefix_expr() ast.PrefixExpr {
|
||||
fn (mut p Parser) prefix_expr() ast.PrefixExpr {
|
||||
pos := p.tok.position()
|
||||
op := p.tok.kind
|
||||
if op == .amp {
|
||||
|
|
Loading…
Reference in New Issue