mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
all: optimize scope usage in checker & parser. store scope in ast nodes (#7281)
This commit is contained in:
parent
eb48208599
commit
0aa9f5a007
@ -112,6 +112,7 @@ pub mut:
|
|||||||
expr_type table.Type // type of `Foo` in `Foo.bar`
|
expr_type table.Type // type of `Foo` in `Foo.bar`
|
||||||
typ table.Type // type of the entire thing (`Foo.bar`)
|
typ table.Type // type of the entire thing (`Foo.bar`)
|
||||||
name_type table.Type // T in `T.name` or typeof in `typeof(expr).name`
|
name_type table.Type // T in `T.name` or typeof in `typeof(expr).name`
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
// root_ident returns the origin ident where the selector started.
|
// root_ident returns the origin ident where the selector started.
|
||||||
@ -287,6 +288,7 @@ pub mut:
|
|||||||
return_type table.Type
|
return_type table.Type
|
||||||
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
|
||||||
source_file &File = 0
|
source_file &File = 0
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
// break, continue
|
// break, continue
|
||||||
@ -317,6 +319,7 @@ pub mut:
|
|||||||
generic_type table.Type // TODO array, to support multiple types
|
generic_type table.Type // TODO array, to support multiple types
|
||||||
generic_list_pos token.Position
|
generic_list_pos token.Position
|
||||||
free_receiver bool // true if the receiver expression needs to be freed
|
free_receiver bool // true if the receiver expression needs to be freed
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -460,6 +463,7 @@ pub:
|
|||||||
pos token.Position
|
pos token.Position
|
||||||
mut_pos token.Position
|
mut_pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
|
scope &Scope
|
||||||
obj ScopeObject
|
obj ScopeObject
|
||||||
mod string
|
mod string
|
||||||
name string
|
name string
|
||||||
@ -548,6 +552,7 @@ pub:
|
|||||||
pub mut:
|
pub mut:
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
smartcast bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
|
smartcast bool // true when cond is `x is SumType`, set in checker.if_expr // no longer needed with union sum types TODO: remove
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnsafeExpr {
|
pub struct UnsafeExpr {
|
||||||
@ -590,6 +595,8 @@ pub:
|
|||||||
comments []Comment // comment above `xxx {`
|
comments []Comment // comment above `xxx {`
|
||||||
is_else bool
|
is_else bool
|
||||||
post_comments []Comment
|
post_comments []Comment
|
||||||
|
pub mut:
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SelectExpr {
|
pub struct SelectExpr {
|
||||||
@ -637,6 +644,7 @@ pub:
|
|||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
label string // `label: for {`
|
label string // `label: for {`
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForInStmt {
|
pub struct ForInStmt {
|
||||||
@ -656,6 +664,7 @@ pub mut:
|
|||||||
cond_type table.Type
|
cond_type table.Type
|
||||||
kind table.Kind // array/map/string
|
kind table.Kind // array/map/string
|
||||||
label string // `label: for {`
|
label string // `label: for {`
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForCStmt {
|
pub struct ForCStmt {
|
||||||
@ -670,6 +679,7 @@ pub:
|
|||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
label string // `label: for {`
|
label string // `label: for {`
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
// #include etc
|
// #include etc
|
||||||
@ -942,6 +952,7 @@ pub:
|
|||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
|
scope &Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SizeOf {
|
pub struct SizeOf {
|
||||||
|
@ -147,6 +147,9 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
|||||||
mod: 'main'
|
mod: 'main'
|
||||||
file: first_main_file.path
|
file: first_main_file.path
|
||||||
return_type: table.void_type
|
return_type: table.void_type
|
||||||
|
scope: &ast.Scope{
|
||||||
|
parent: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
has_main_fn = true
|
has_main_fn = true
|
||||||
}
|
}
|
||||||
@ -1141,15 +1144,13 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||||||
is_sort := method_name == 'sort'
|
is_sort := method_name == 'sort'
|
||||||
if is_filter_map || is_sort {
|
if is_filter_map || is_sort {
|
||||||
array_info := left_type_sym.info as table.Array
|
array_info := left_type_sym.info as table.Array
|
||||||
args_pos := call_expr.pos.pos + call_expr.name.len
|
|
||||||
mut scope := c.file.scope.innermost(args_pos)
|
|
||||||
if is_filter_map {
|
if is_filter_map {
|
||||||
// position of `it` doesn't matter
|
// position of `it` doesn't matter
|
||||||
scope_register_it(mut scope, call_expr.pos, array_info.elem_type)
|
scope_register_it(mut call_expr.scope, call_expr.pos, array_info.elem_type)
|
||||||
} else if is_sort {
|
} else if is_sort {
|
||||||
c.fail_if_immutable(call_expr.left)
|
c.fail_if_immutable(call_expr.left)
|
||||||
// position of `a` and `b` doesn't matter, they're the same
|
// position of `a` and `b` doesn't matter, they're the same
|
||||||
scope_register_ab(mut scope, call_expr.pos, array_info.elem_type)
|
scope_register_ab(mut call_expr.scope, call_expr.pos, array_info.elem_type)
|
||||||
// Verify `.sort(a < b)`
|
// Verify `.sort(a < b)`
|
||||||
if call_expr.args.len > 0 {
|
if call_expr.args.len > 0 {
|
||||||
if call_expr.args[0].expr !is ast.InfixExpr {
|
if call_expr.args[0].expr !is ast.InfixExpr {
|
||||||
@ -1450,8 +1451,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||||||
}
|
}
|
||||||
// check for arg (var) of fn type
|
// check for arg (var) of fn type
|
||||||
if !found {
|
if !found {
|
||||||
scope := c.file.scope.innermost(call_expr.pos.pos)
|
if v := call_expr.scope.find_var(fn_name) {
|
||||||
if v := scope.find_var(fn_name) {
|
|
||||||
if v.typ != 0 {
|
if v.typ != 0 {
|
||||||
vts := c.table.get_type_symbol(v.typ)
|
vts := c.table.get_type_symbol(v.typ)
|
||||||
if vts.kind == .function {
|
if vts.kind == .function {
|
||||||
@ -1468,8 +1468,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
if !found_in_args {
|
if !found_in_args {
|
||||||
scope := c.file.scope.innermost(call_expr.pos.pos)
|
if _ := call_expr.scope.find_var(fn_name) {
|
||||||
if _ := scope.find_var(fn_name) {
|
|
||||||
c.error('ambiguous call to: `$fn_name`, may refer to fn `$fn_name` or variable `$fn_name`',
|
c.error('ambiguous call to: `$fn_name`, may refer to fn `$fn_name` or variable `$fn_name`',
|
||||||
call_expr.pos)
|
call_expr.pos)
|
||||||
}
|
}
|
||||||
@ -1825,8 +1824,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
|
|||||||
field_sym := c.table.get_type_symbol(field.typ)
|
field_sym := c.table.get_type_symbol(field.typ)
|
||||||
if field_sym.kind == .sum_type {
|
if field_sym.kind == .sum_type {
|
||||||
if !prevent_sum_type_unwrapping_once {
|
if !prevent_sum_type_unwrapping_once {
|
||||||
scope := c.file.scope.innermost(selector_expr.pos.pos)
|
if scope_field := selector_expr.scope.find_struct_field(utyp, field_name) {
|
||||||
if scope_field := scope.find_struct_field(utyp, field_name) {
|
|
||||||
return scope_field.sum_type_casts.last()
|
return scope_field.sum_type_casts.last()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2052,38 +2050,6 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Check `x := &y` and `mut x := <-ch`
|
|
||||||
if right_first is ast.PrefixExpr {
|
|
||||||
node := right_first
|
|
||||||
left_first := assign_stmt.left[0]
|
|
||||||
if left_first is ast.Ident {
|
|
||||||
assigned_var := left_first
|
|
||||||
if node.right is ast.Ident {
|
|
||||||
scope := c.file.scope.innermost(node.pos.pos)
|
|
||||||
if v := scope.find_var(node.right.name) {
|
|
||||||
right_type0 = v.typ
|
|
||||||
if node.op == .amp {
|
|
||||||
if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe {
|
|
||||||
c.error('`$node.right.name` is immutable, cannot have a mutable reference to it',
|
|
||||||
node.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if node.op == .arrow {
|
|
||||||
if assigned_var.is_mut {
|
|
||||||
right_sym := c.table.get_type_symbol(right_type0)
|
|
||||||
if right_sym.kind == .chan {
|
|
||||||
chan_info := right_sym.chan_info()
|
|
||||||
if chan_info.elem_type.is_ptr() && !chan_info.is_mut {
|
|
||||||
c.error('cannot have a mutable reference to object from `$right_sym.name`',
|
|
||||||
node.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
//
|
||||||
is_decl := assign_stmt.op == .decl_assign
|
is_decl := assign_stmt.op == .decl_assign
|
||||||
for i, left in assign_stmt.left {
|
for i, left in assign_stmt.left {
|
||||||
@ -2284,6 +2250,40 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// this needs to run after the assign stmt left exprs have been run through checker so that ident.obj is set
|
||||||
|
// Check `x := &y` and `mut x := <-ch`
|
||||||
|
if right_first is ast.PrefixExpr {
|
||||||
|
node := right_first
|
||||||
|
left_first := assign_stmt.left[0]
|
||||||
|
if left_first is ast.Ident {
|
||||||
|
assigned_var := left_first
|
||||||
|
c.expr(node.right)
|
||||||
|
if node.right is ast.Ident {
|
||||||
|
if node.right.obj is ast.Var {
|
||||||
|
v := node.right.obj
|
||||||
|
right_type0 = v.typ
|
||||||
|
if node.op == .amp {
|
||||||
|
if !v.is_mut && assigned_var.is_mut && !c.inside_unsafe {
|
||||||
|
c.error('`$node.right.name` is immutable, cannot have a mutable reference to it',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.op == .arrow {
|
||||||
|
if assigned_var.is_mut {
|
||||||
|
right_sym := c.table.get_type_symbol(right_type0)
|
||||||
|
if right_sym.kind == .chan {
|
||||||
|
chan_info := right_sym.chan_info()
|
||||||
|
if chan_info.elem_type.is_ptr() && !chan_info.is_mut {
|
||||||
|
c.error('cannot have a mutable reference to object from `$right_sym.name`',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scope_register_it(mut s ast.Scope, pos token.Position, typ table.Type) {
|
fn scope_register_it(mut s ast.Scope, pos token.Position, typ table.Type) {
|
||||||
@ -2422,25 +2422,18 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
|||||||
// [50]byte
|
// [50]byte
|
||||||
mut fixed_size := 1
|
mut fixed_size := 1
|
||||||
init_expr := array_init.exprs[0]
|
init_expr := array_init.exprs[0]
|
||||||
|
c.expr(init_expr)
|
||||||
match init_expr {
|
match init_expr {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
fixed_size = init_expr.val.int()
|
fixed_size = init_expr.val.int()
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
// if obj := c.file.global_scope.find_const(init_expr.name) {
|
if init_expr.obj is ast.ConstField {
|
||||||
// if obj := scope.find(init_expr.name) {
|
if cint := const_int_value(init_expr.obj) {
|
||||||
// scope := c.file.scope.innermost(array_init.pos.pos)
|
|
||||||
// eprintln('scope: ${scope.str()}')
|
|
||||||
// scope.find(init_expr.name) or {
|
|
||||||
// c.error('undefined ident: `$init_expr.name`', array_init.pos)
|
|
||||||
// }
|
|
||||||
mut full_const_name := init_expr.mod + '.' + init_expr.name
|
|
||||||
if obj := c.file.global_scope.find_const(full_const_name) {
|
|
||||||
if cint := const_int_value(obj) {
|
|
||||||
fixed_size = cint
|
fixed_size = cint
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.error('non existent integer const $full_const_name while initializing the size of a static array',
|
c.error('non existent integer const $init_expr.name while initializing the size of a static array',
|
||||||
array_init.pos)
|
array_init.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2584,7 +2577,6 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||||||
c.error('range type can not be string', node.cond.position())
|
c.error('range type can not be string', node.cond.position())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mut scope := c.file.scope.innermost(node.pos.pos)
|
|
||||||
sym := c.table.get_type_symbol(typ)
|
sym := c.table.get_type_symbol(typ)
|
||||||
if sym.kind == .map && !(node.key_var.len > 0 && node.val_var.len > 0) {
|
if sym.kind == .map && !(node.key_var.len > 0 && node.val_var.len > 0) {
|
||||||
c.error('declare a key and a value variable when ranging a map: `for key, val in map {`\n' +
|
c.error('declare a key and a value variable when ranging a map: `for key, val in map {`\n' +
|
||||||
@ -2596,7 +2588,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||||||
else { table.int_type }
|
else { table.int_type }
|
||||||
}
|
}
|
||||||
node.key_type = key_type
|
node.key_type = key_type
|
||||||
scope.update_var_type(node.key_var, key_type)
|
node.scope.update_var_type(node.key_var, key_type)
|
||||||
}
|
}
|
||||||
mut value_type := c.table.value_type(typ)
|
mut value_type := c.table.value_type(typ)
|
||||||
if value_type == table.void_type || typ.has_flag(.optional) {
|
if value_type == table.void_type || typ.has_flag(.optional) {
|
||||||
@ -2611,7 +2603,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
|||||||
node.cond_type = typ
|
node.cond_type = typ
|
||||||
node.kind = sym.kind
|
node.kind = sym.kind
|
||||||
node.val_type = value_type
|
node.val_type = value_type
|
||||||
scope.update_var_type(node.val_var, value_type)
|
node.scope.update_var_type(node.val_var, value_type)
|
||||||
}
|
}
|
||||||
c.check_loop_label(node.label, node.pos)
|
c.check_loop_label(node.label, node.pos)
|
||||||
c.stmts(node.stmts)
|
c.stmts(node.stmts)
|
||||||
@ -2873,8 +2865,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
|||||||
return node.typ.to_ptr()
|
return node.typ.to_ptr()
|
||||||
}
|
}
|
||||||
ast.Assoc {
|
ast.Assoc {
|
||||||
scope := c.file.scope.innermost(node.pos.pos)
|
v := node.scope.find_var(node.var_name) or { panic(err) }
|
||||||
v := scope.find_var(node.var_name) or { panic(err) }
|
|
||||||
for i, _ in node.fields {
|
for i, _ in node.fields {
|
||||||
c.expr(node.exprs[i])
|
c.expr(node.exprs[i])
|
||||||
}
|
}
|
||||||
@ -3270,8 +3261,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
|||||||
if ident.tok_kind == .assign && ident.is_mut {
|
if ident.tok_kind == .assign && ident.is_mut {
|
||||||
c.error('`mut` not allowed with `=` (use `:=` to declare a variable)', ident.pos)
|
c.error('`mut` not allowed with `=` (use `:=` to declare a variable)', ident.pos)
|
||||||
}
|
}
|
||||||
start_scope := c.file.scope.innermost(ident.pos.pos)
|
if obj := ident.scope.find(ident.name) {
|
||||||
if obj := start_scope.find(ident.name) {
|
|
||||||
match mut obj {
|
match mut obj {
|
||||||
ast.GlobalField {
|
ast.GlobalField {
|
||||||
ident.kind = .global
|
ident.kind = .global
|
||||||
@ -3509,7 +3499,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||||||
// an expr was used in the match
|
// an expr was used in the match
|
||||||
mut branch_exprs := map[string]int{}
|
mut branch_exprs := map[string]int{}
|
||||||
cond_type_sym := c.table.get_type_symbol(node.cond_type)
|
cond_type_sym := c.table.get_type_symbol(node.cond_type)
|
||||||
for branch in node.branches {
|
for branch_i, _ in node.branches {
|
||||||
|
mut branch := node.branches[branch_i]
|
||||||
mut expr_types := []ast.Type{}
|
mut expr_types := []ast.Type{}
|
||||||
for expr in branch.exprs {
|
for expr in branch.exprs {
|
||||||
mut key := ''
|
mut key := ''
|
||||||
@ -3623,7 +3614,6 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||||||
} else {
|
} else {
|
||||||
expr_type = expr_types[0].typ
|
expr_type = expr_types[0].typ
|
||||||
}
|
}
|
||||||
mut scope := c.file.scope.innermost(branch.pos.pos)
|
|
||||||
match mut node.cond {
|
match mut node.cond {
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
@ -3632,18 +3622,19 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||||||
if field := c.table.struct_find_field(expr_sym, node.cond.field_name) {
|
if field := c.table.struct_find_field(expr_sym, node.cond.field_name) {
|
||||||
if field.is_mut {
|
if field.is_mut {
|
||||||
root_ident := node.cond.root_ident()
|
root_ident := node.cond.root_ident()
|
||||||
if v := scope.find_var(root_ident.name) {
|
if v := branch.scope.find_var(root_ident.name) {
|
||||||
is_mut = v.is_mut
|
is_mut = v.is_mut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field := scope.find_struct_field(node.cond.expr_type, node.cond.field_name) {
|
if field := branch.scope.find_struct_field(node.cond.expr_type,
|
||||||
|
node.cond.field_name) {
|
||||||
sum_type_casts << field.sum_type_casts
|
sum_type_casts << field.sum_type_casts
|
||||||
}
|
}
|
||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||||
if !is_mut || node.cond.is_mut {
|
if !is_mut || node.cond.is_mut {
|
||||||
sum_type_casts << expr_type
|
sum_type_casts << expr_type
|
||||||
scope.register_struct_field(ast.ScopeStructField{
|
branch.scope.register_struct_field(ast.ScopeStructField{
|
||||||
struct_type: node.cond.expr_type
|
struct_type: node.cond.expr_type
|
||||||
name: node.cond.field_name
|
name: node.cond.field_name
|
||||||
typ: node.cond_type
|
typ: node.cond_type
|
||||||
@ -3656,7 +3647,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
mut sum_type_casts := []table.Type{}
|
mut sum_type_casts := []table.Type{}
|
||||||
mut is_already_casted := false
|
mut is_already_casted := false
|
||||||
if v := scope.find_var(node.cond.name) {
|
if node.cond.obj is ast.Var {
|
||||||
|
v := node.cond.obj as ast.Var
|
||||||
is_mut = v.is_mut
|
is_mut = v.is_mut
|
||||||
sum_type_casts << v.sum_type_casts
|
sum_type_casts << v.sum_type_casts
|
||||||
is_already_casted = v.pos.pos == node.cond.pos.pos
|
is_already_casted = v.pos.pos == node.cond.pos.pos
|
||||||
@ -3664,7 +3656,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
|||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||||
if (!is_mut || node.cond.is_mut) && !is_already_casted {
|
if (!is_mut || node.cond.is_mut) && !is_already_casted {
|
||||||
sum_type_casts << expr_type
|
sum_type_casts << expr_type
|
||||||
scope.register(ast.Var{
|
branch.scope.register(ast.Var{
|
||||||
name: node.cond.name
|
name: node.cond.name
|
||||||
typ: node.cond_type
|
typ: node.cond_type
|
||||||
pos: node.cond.pos
|
pos: node.cond.pos
|
||||||
@ -3891,10 +3883,9 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
|||||||
// TODO: merge this code with match_expr because it has the same logic implemented
|
// TODO: merge this code with match_expr because it has the same logic implemented
|
||||||
if left_sym.kind in [.interface_, .sum_type] {
|
if left_sym.kind in [.interface_, .sum_type] {
|
||||||
mut is_mut := false
|
mut is_mut := false
|
||||||
mut scope := c.file.scope.innermost(branch.body_pos.pos)
|
|
||||||
if mut infix.left is ast.Ident {
|
if mut infix.left is ast.Ident {
|
||||||
mut sum_type_casts := []table.Type{}
|
mut sum_type_casts := []table.Type{}
|
||||||
if v := scope.find_var(infix.left.name) {
|
if v := branch.scope.find_var(infix.left.name) {
|
||||||
is_mut = v.is_mut
|
is_mut = v.is_mut
|
||||||
sum_type_casts << v.sum_type_casts
|
sum_type_casts << v.sum_type_casts
|
||||||
}
|
}
|
||||||
@ -3902,7 +3893,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
|||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||||
if !is_mut || infix.left.is_mut {
|
if !is_mut || infix.left.is_mut {
|
||||||
sum_type_casts << right_expr.typ
|
sum_type_casts << right_expr.typ
|
||||||
scope.register(ast.Var{
|
branch.scope.register(ast.Var{
|
||||||
name: infix.left.name
|
name: infix.left.name
|
||||||
typ: infix.left_type
|
typ: infix.left_type
|
||||||
sum_type_casts: sum_type_casts
|
sum_type_casts: sum_type_casts
|
||||||
@ -3912,7 +3903,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if left_sym.kind == .interface_ {
|
} else if left_sym.kind == .interface_ {
|
||||||
scope.register(ast.Var{
|
branch.scope.register(ast.Var{
|
||||||
name: infix.left.name
|
name: infix.left.name
|
||||||
typ: right_expr.typ.to_ptr()
|
typ: right_expr.typ.to_ptr()
|
||||||
sum_type_casts: sum_type_casts
|
sum_type_casts: sum_type_casts
|
||||||
@ -3929,19 +3920,19 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
|||||||
if field := c.table.struct_find_field(expr_sym, infix.left.field_name) {
|
if field := c.table.struct_find_field(expr_sym, infix.left.field_name) {
|
||||||
if field.is_mut {
|
if field.is_mut {
|
||||||
root_ident := infix.left.root_ident()
|
root_ident := infix.left.root_ident()
|
||||||
if v := scope.find_var(root_ident.name) {
|
if root_ident.obj is ast.Var {
|
||||||
is_mut = v.is_mut
|
is_mut = root_ident.obj.is_mut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field := scope.find_struct_field(infix.left.expr_type,
|
if field := branch.scope.find_struct_field(infix.left.expr_type,
|
||||||
infix.left.field_name) {
|
infix.left.field_name) {
|
||||||
sum_type_casts << field.sum_type_casts
|
sum_type_casts << field.sum_type_casts
|
||||||
}
|
}
|
||||||
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
// smartcast either if the value is immutable or if the mut argument is explicitly given
|
||||||
if (!is_mut || infix.left.is_mut) && left_sym.kind == .sum_type {
|
if (!is_mut || infix.left.is_mut) && left_sym.kind == .sum_type {
|
||||||
sum_type_casts << right_expr.typ
|
sum_type_casts << right_expr.typ
|
||||||
scope.register_struct_field(ast.ScopeStructField{
|
branch.scope.register_struct_field(ast.ScopeStructField{
|
||||||
struct_type: infix.left.expr_type
|
struct_type: infix.left.expr_type
|
||||||
name: infix.left.field_name
|
name: infix.left.field_name
|
||||||
typ: infix.left_type
|
typ: infix.left_type
|
||||||
@ -4159,12 +4150,12 @@ fn (mut c Checker) comp_if_branch(cond ast.Expr, pos token.Position) bool {
|
|||||||
} else if cond.name !in c.pref.compile_defines_all {
|
} else if cond.name !in c.pref.compile_defines_all {
|
||||||
// `$if some_var {}`
|
// `$if some_var {}`
|
||||||
typ := c.expr(cond)
|
typ := c.expr(cond)
|
||||||
scope := c.file.scope.innermost(pos.pos)
|
if cond.obj !is ast.Var &&
|
||||||
obj := scope.find(cond.name) or {
|
cond.obj !is ast.ConstField && cond.obj !is ast.GlobalField {
|
||||||
c.error('unknown var: `$cond.name`', pos)
|
c.error('unknown var: `$cond.name`', pos)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
expr := c.find_obj_definition(obj) or {
|
expr := c.find_obj_definition(cond.obj) or {
|
||||||
c.error(err, cond.pos)
|
c.error(err, cond.pos)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -4285,8 +4276,8 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) table.Type {
|
|||||||
if !c.inside_unsafe && (typ.is_ptr() || typ.is_pointer()) {
|
if !c.inside_unsafe && (typ.is_ptr() || typ.is_pointer()) {
|
||||||
mut is_ok := false
|
mut is_ok := false
|
||||||
if mut node.left is ast.Ident {
|
if mut node.left is ast.Ident {
|
||||||
scope := c.file.scope.innermost(node.left.pos.pos)
|
if node.left.obj is ast.Var {
|
||||||
if v := scope.find_var(node.left.name) {
|
v := node.left.obj as ast.Var
|
||||||
// `mut param []T` function parameter
|
// `mut param []T` function parameter
|
||||||
is_ok = v.is_mut && v.is_arg && !typ.deref().is_ptr()
|
is_ok = v.is_mut && v.is_arg && !typ.deref().is_ptr()
|
||||||
}
|
}
|
||||||
|
@ -1735,7 +1735,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||||||
val := assign_stmt.right[i]
|
val := assign_stmt.right[i]
|
||||||
mut is_call := false
|
mut is_call := false
|
||||||
mut blank_assign := false
|
mut blank_assign := false
|
||||||
mut ident := ast.Ident{}
|
mut ident := ast.Ident{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
if left is ast.Ident {
|
if left is ast.Ident {
|
||||||
ident = left
|
ident = left
|
||||||
// id_info := ident.var_info()
|
// id_info := ident.var_info()
|
||||||
|
@ -126,7 +126,8 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
|
|||||||
for stmt in file.stmts {
|
for stmt in file.stmts {
|
||||||
if stmt is ast.FnDecl {
|
if stmt is ast.FnDecl {
|
||||||
if stmt.name == 'main.vweb_tmpl_$tmp_fn_name' {
|
if stmt.name == 'main.vweb_tmpl_$tmp_fn_name' {
|
||||||
mut tmpl_scope := file.scope.innermost(stmt.body_pos.pos)
|
// mut tmpl_scope := file.scope.innermost(stmt.body_pos.pos)
|
||||||
|
mut tmpl_scope := stmt.scope
|
||||||
for _, obj in p.scope.objects {
|
for _, obj in p.scope.objects {
|
||||||
if obj is ast.Var {
|
if obj is ast.Var {
|
||||||
mut v := obj
|
mut v := obj
|
||||||
|
@ -101,6 +101,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
|
|||||||
kind: or_kind
|
kind: or_kind
|
||||||
pos: or_pos
|
pos: or_pos
|
||||||
}
|
}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,12 +202,16 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||||||
rec_type = p.parse_type_with_mut(rec_mut)
|
rec_type = p.parse_type_with_mut(rec_mut)
|
||||||
if rec_type.idx() == 0 {
|
if rec_type.idx() == 0 {
|
||||||
// error is set in parse_type
|
// error is set in parse_type
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rec_type_pos = rec_type_pos.extend(p.prev_tok.position())
|
rec_type_pos = rec_type_pos.extend(p.prev_tok.position())
|
||||||
if is_amp && rec_mut {
|
if is_amp && rec_mut {
|
||||||
p.error('use `(mut f Foo)` or `(f &Foo)` instead of `(mut f &Foo)`')
|
p.error('use `(mut f Foo)` or `(f &Foo)` instead of `(mut f &Foo)`')
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if is_shared {
|
if is_shared {
|
||||||
rec_type = rec_type.set_flag(.shared_f)
|
rec_type = rec_type.set_flag(.shared_f)
|
||||||
@ -228,13 +233,17 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||||||
name = if language == .js { p.check_js_name() } else { p.check_name() }
|
name = if language == .js { p.check_js_name() } else { p.check_name() }
|
||||||
if language == .v && !p.pref.translated && util.contains_capital(name) && p.mod != 'builtin' {
|
if language == .v && !p.pref.translated && util.contains_capital(name) && p.mod != 'builtin' {
|
||||||
p.error('function names cannot contain uppercase letters, use snake_case instead')
|
p.error('function names cannot contain uppercase letters, use snake_case instead')
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
type_sym := p.table.get_type_symbol(rec_type)
|
type_sym := p.table.get_type_symbol(rec_type)
|
||||||
// interfaces are handled in the checker, methods can not be defined on them this way
|
// interfaces are handled in the checker, methods can not be defined on them this way
|
||||||
if is_method && (type_sym.has_method(name) && type_sym.kind != .interface_) {
|
if is_method && (type_sym.has_method(name) && type_sym.kind != .interface_) {
|
||||||
p.error('duplicate method `$name`')
|
p.error('duplicate method `$name`')
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.tok.kind in [.plus, .minus, .mul, .div, .mod] {
|
if p.tok.kind in [.plus, .minus, .mul, .div, .mod] {
|
||||||
@ -255,7 +264,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||||||
for param in params {
|
for param in params {
|
||||||
if p.scope.known_var(param.name) {
|
if p.scope.known_var(param.name) {
|
||||||
p.error_with_pos('redefinition of parameter `$param.name`', param.pos)
|
p.error_with_pos('redefinition of parameter `$param.name`', param.pos)
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
name: param.name
|
name: param.name
|
||||||
@ -291,7 +302,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||||||
if is_non_local {
|
if is_non_local {
|
||||||
p.error_with_pos('cannot define new methods on non-local type $type_sym.name',
|
p.error_with_pos('cannot define new methods on non-local type $type_sym.name',
|
||||||
rec_type_pos)
|
rec_type_pos)
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// p.warn('reg method $type_sym.name . $name ()')
|
// p.warn('reg method $type_sym.name . $name ()')
|
||||||
type_sym_method_idx = type_sym.register_method(table.Fn{
|
type_sym_method_idx = type_sym.register_method(table.Fn{
|
||||||
@ -341,12 +354,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||||||
if p.tok.kind == .lcbr {
|
if p.tok.kind == .lcbr {
|
||||||
stmts = p.parse_block_no_scope(true)
|
stmts = p.parse_block_no_scope(true)
|
||||||
}
|
}
|
||||||
p.close_scope()
|
|
||||||
if !no_body && are_args_type_only {
|
if !no_body && are_args_type_only {
|
||||||
p.error_with_pos('functions with type only args can not have bodies', body_start_pos)
|
p.error_with_pos('functions with type only args can not have bodies', body_start_pos)
|
||||||
return ast.FnDecl{}
|
return ast.FnDecl{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ast.FnDecl{
|
fn_decl := ast.FnDecl{
|
||||||
name: name
|
name: name
|
||||||
mod: p.mod
|
mod: p.mod
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
@ -373,7 +387,10 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||||||
file: p.file_name
|
file: p.file_name
|
||||||
is_builtin: p.builtin_mod || p.mod in util.builtin_module_parts
|
is_builtin: p.builtin_mod || p.mod in util.builtin_module_parts
|
||||||
attrs: p.attrs
|
attrs: p.attrs
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
|
p.close_scope()
|
||||||
|
return fn_decl
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut p Parser) anon_fn() ast.AnonFn {
|
fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||||
@ -425,6 +442,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
|||||||
no_body: no_body
|
no_body: no_body
|
||||||
pos: pos
|
pos: pos
|
||||||
file: p.file_name
|
file: p.file_name
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
typ: typ
|
typ: typ
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,15 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
|||||||
// Infinite loop
|
// Infinite loop
|
||||||
if p.tok.kind == .lcbr {
|
if p.tok.kind == .lcbr {
|
||||||
p.inside_for = false
|
p.inside_for = false
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block_no_scope(false)
|
||||||
p.close_scope()
|
for_stmt := ast.ForStmt{
|
||||||
return ast.ForStmt{
|
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
pos: pos
|
pos: pos
|
||||||
is_inf: true
|
is_inf: true
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
|
p.close_scope()
|
||||||
|
return for_stmt
|
||||||
} else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon {
|
} else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon {
|
||||||
// `for i := 0; i < 10; i++ {`
|
// `for i := 0; i < 10; i++ {`
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
@ -60,9 +62,8 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
|||||||
has_inc = true
|
has_inc = true
|
||||||
}
|
}
|
||||||
p.inside_for = false
|
p.inside_for = false
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block_no_scope(false)
|
||||||
p.close_scope()
|
for_c_stmt := ast.ForCStmt{
|
||||||
return ast.ForCStmt{
|
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
has_init: has_init
|
has_init: has_init
|
||||||
has_cond: has_cond
|
has_cond: has_cond
|
||||||
@ -71,7 +72,10 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
|||||||
cond: cond
|
cond: cond
|
||||||
inc: inc
|
inc: inc
|
||||||
pos: pos
|
pos: pos
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
|
p.close_scope()
|
||||||
|
return for_c_stmt
|
||||||
} else if p.peek_tok.kind in [.key_in, .comma] ||
|
} else if p.peek_tok.kind in [.key_in, .comma] ||
|
||||||
(p.tok.kind == .key_mut && p.peek_tok2.kind in [.key_in, .comma]) {
|
(p.tok.kind == .key_mut && p.peek_tok2.kind in [.key_in, .comma]) {
|
||||||
// `for i in vals`, `for i in start .. end`
|
// `for i in vals`, `for i in start .. end`
|
||||||
@ -146,10 +150,9 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
p.inside_for = false
|
p.inside_for = false
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block_no_scope(false)
|
||||||
// println('nr stmts=$stmts.len')
|
// println('nr stmts=$stmts.len')
|
||||||
p.close_scope()
|
for_in_stmt := ast.ForInStmt{
|
||||||
return ast.ForInStmt{
|
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
cond: cond
|
cond: cond
|
||||||
key_var: key_var_name
|
key_var: key_var_name
|
||||||
@ -158,16 +161,21 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
|||||||
is_range: is_range
|
is_range: is_range
|
||||||
pos: pos
|
pos: pos
|
||||||
val_is_mut: val_is_mut
|
val_is_mut: val_is_mut
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
|
p.close_scope()
|
||||||
|
return for_in_stmt
|
||||||
}
|
}
|
||||||
// `for cond {`
|
// `for cond {`
|
||||||
cond := p.expr(0)
|
cond := p.expr(0)
|
||||||
p.inside_for = false
|
p.inside_for = false
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block_no_scope(false)
|
||||||
p.close_scope()
|
for_stmt := ast.ForStmt{
|
||||||
return ast.ForStmt{
|
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
pos: pos
|
pos: pos
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
|
p.close_scope()
|
||||||
|
return for_stmt
|
||||||
}
|
}
|
||||||
|
@ -43,9 +43,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
p.inside_if = false
|
p.inside_if = false
|
||||||
end_pos := p.prev_tok.position()
|
end_pos := p.prev_tok.position()
|
||||||
body_pos := p.tok.position()
|
body_pos := p.tok.position()
|
||||||
|
p.open_scope()
|
||||||
// only declare `err` if previous branch was an `if` guard
|
// only declare `err` if previous branch was an `if` guard
|
||||||
if prev_guard {
|
if prev_guard {
|
||||||
p.open_scope()
|
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
name: 'errcode'
|
name: 'errcode'
|
||||||
typ: table.int_type
|
typ: table.int_type
|
||||||
@ -60,18 +60,13 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
branches << ast.IfBranch{
|
branches << ast.IfBranch{
|
||||||
stmts: if prev_guard {
|
stmts: p.parse_block_no_scope(false)
|
||||||
p.parse_block_no_scope(false)
|
|
||||||
} else {
|
|
||||||
p.parse_block()
|
|
||||||
}
|
|
||||||
pos: start_pos.extend(end_pos)
|
pos: start_pos.extend(end_pos)
|
||||||
body_pos: body_pos.extend(p.tok.position())
|
body_pos: body_pos.extend(p.tok.position())
|
||||||
comments: comments
|
comments: comments
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
if prev_guard {
|
p.close_scope()
|
||||||
p.close_scope()
|
|
||||||
}
|
|
||||||
comments = []
|
comments = []
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -116,16 +111,19 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
|
|||||||
end_pos := p.prev_tok.position()
|
end_pos := p.prev_tok.position()
|
||||||
body_pos := p.tok.position()
|
body_pos := p.tok.position()
|
||||||
p.inside_if = false
|
p.inside_if = false
|
||||||
stmts := p.parse_block()
|
p.open_scope()
|
||||||
if is_guard {
|
stmts := p.parse_block_no_scope(false)
|
||||||
p.close_scope()
|
|
||||||
}
|
|
||||||
branches << ast.IfBranch{
|
branches << ast.IfBranch{
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
pos: start_pos.extend(end_pos)
|
pos: start_pos.extend(end_pos)
|
||||||
body_pos: body_pos.extend(p.prev_tok.position())
|
body_pos: body_pos.extend(p.prev_tok.position())
|
||||||
comments: comments
|
comments: comments
|
||||||
|
scope: p.scope
|
||||||
|
}
|
||||||
|
p.close_scope()
|
||||||
|
if is_guard {
|
||||||
|
p.close_scope()
|
||||||
}
|
}
|
||||||
comments = p.eat_comments()
|
comments = p.eat_comments()
|
||||||
if is_comptime {
|
if is_comptime {
|
||||||
@ -226,6 +224,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
|||||||
// p.warn('match block')
|
// p.warn('match block')
|
||||||
p.inside_match_body = true
|
p.inside_match_body = true
|
||||||
stmts := p.parse_block_no_scope(false)
|
stmts := p.parse_block_no_scope(false)
|
||||||
|
branch_scope := p.scope
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
p.inside_match_body = false
|
p.inside_match_body = false
|
||||||
pos := token.Position{
|
pos := token.Position{
|
||||||
@ -242,6 +241,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
|||||||
comments: comments
|
comments: comments
|
||||||
is_else: is_else
|
is_else: is_else
|
||||||
post_comments: post_comments
|
post_comments: post_comments
|
||||||
|
scope: branch_scope
|
||||||
}
|
}
|
||||||
if p.tok.kind == .rcbr || (is_else && no_lcbr) {
|
if p.tok.kind == .rcbr || (is_else && no_lcbr) {
|
||||||
break
|
break
|
||||||
|
@ -18,6 +18,7 @@ fn (mut p Parser) lock_expr() ast.LockExpr {
|
|||||||
name: p.tok.lit
|
name: p.tok.lit
|
||||||
is_mut: true
|
is_mut: true
|
||||||
info: ast.IdentVar{}
|
info: ast.IdentVar{}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok.kind == .lcbr {
|
if p.tok.kind == .lcbr {
|
||||||
|
@ -521,6 +521,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
|||||||
stmts: stmts
|
stmts: stmts
|
||||||
file: p.file_name
|
file: p.file_name
|
||||||
return_type: table.void_type
|
return_type: table.void_type
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
} else if p.pref.is_fmt {
|
} else if p.pref.is_fmt {
|
||||||
return p.stmt(false)
|
return p.stmt(false)
|
||||||
@ -995,6 +996,7 @@ pub fn (mut p Parser) parse_ident(language table.Language) ast.Ident {
|
|||||||
is_mut: false
|
is_mut: false
|
||||||
is_static: false
|
is_static: false
|
||||||
}
|
}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.inside_match_body && name == 'it' {
|
if p.inside_match_body && name == 'it' {
|
||||||
@ -1017,12 +1019,17 @@ pub fn (mut p Parser) parse_ident(language table.Language) ast.Ident {
|
|||||||
is_static: is_static
|
is_static: is_static
|
||||||
share: table.sharetype_from_flags(is_shared, is_atomic)
|
share: table.sharetype_from_flags(is_shared, is_atomic)
|
||||||
}
|
}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.error('unexpected token `$p.tok.lit`')
|
p.error('unexpected token `$p.tok.lit`')
|
||||||
return ast.Ident{}
|
return ast.Ident{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ast.Ident{
|
||||||
|
scope: 0
|
||||||
}
|
}
|
||||||
return ast.Ident{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) name_expr() ast.Expr {
|
pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
@ -1230,9 +1237,11 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||||||
return ast.SelectorExpr{
|
return ast.SelectorExpr{
|
||||||
expr: ast.Ident{
|
expr: ast.Ident{
|
||||||
name: name
|
name: name
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
field_name: field
|
field_name: field
|
||||||
pos: pos
|
pos: pos
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `Color.green`
|
// `Color.green`
|
||||||
@ -1413,6 +1422,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||||||
kind: or_kind
|
kind: or_kind
|
||||||
pos: or_pos
|
pos: or_pos
|
||||||
}
|
}
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
if is_filter || field_name == 'sort' {
|
if is_filter || field_name == 'sort' {
|
||||||
p.close_scope()
|
p.close_scope()
|
||||||
@ -1436,6 +1446,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
|||||||
pos: name_pos
|
pos: name_pos
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
mut_pos: mut_pos
|
mut_pos: mut_pos
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = sel_expr
|
node = sel_expr
|
||||||
@ -2095,7 +2106,9 @@ fn (mut p Parser) assoc() ast.Assoc {
|
|||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
mut v := p.scope.find_var(var_name) or {
|
mut v := p.scope.find_var(var_name) or {
|
||||||
p.error('unknown variable `$var_name`')
|
p.error('unknown variable `$var_name`')
|
||||||
return ast.Assoc{}
|
return ast.Assoc{
|
||||||
|
scope: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
v.is_used = true
|
v.is_used = true
|
||||||
// println('assoc var $name typ=$var.typ')
|
// println('assoc var $name typ=$var.typ')
|
||||||
@ -2119,6 +2132,7 @@ fn (mut p Parser) assoc() ast.Assoc {
|
|||||||
fields: fields
|
fields: fields
|
||||||
exprs: vals
|
exprs: vals
|
||||||
pos: pos
|
pos: pos
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
|||||||
left: node
|
left: node
|
||||||
args: args
|
args: args
|
||||||
pos: pos
|
pos: pos
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
|
@ -439,6 +439,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
|
|||||||
return_type: table.void_type
|
return_type: table.void_type
|
||||||
is_pub: true
|
is_pub: true
|
||||||
pos: method_start_pos.extend(p.prev_tok.position())
|
pos: method_start_pos.extend(p.prev_tok.position())
|
||||||
|
scope: p.scope
|
||||||
}
|
}
|
||||||
if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr {
|
if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr {
|
||||||
method.return_type = p.parse_type()
|
method.return_type = p.parse_type()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user