parser: simplify unused vars & add loop/if vars etc
parent
e67bf674e3
commit
9f76a7b250
|
@ -832,7 +832,7 @@ fn (ar []string) contains(val string) bool {
|
||||||
|
|
||||||
// TODO generic
|
// TODO generic
|
||||||
fn (ar []int) contains(val int) bool {
|
fn (ar []int) contains(val int) bool {
|
||||||
for i, s in ar {
|
for s in ar {
|
||||||
if s == val {
|
if s == val {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -1206,7 +1206,7 @@ pub fn (a []string) join(del string) string {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
mut len := 0
|
mut len := 0
|
||||||
for i, val in a {
|
for val in a {
|
||||||
len += val.len + del.len
|
len += val.len + del.len
|
||||||
}
|
}
|
||||||
len -= del.len
|
len -= del.len
|
||||||
|
|
|
@ -1061,7 +1061,7 @@ pub fn walk_ext(path, ext string) []string {
|
||||||
}
|
}
|
||||||
mut res := []string{}
|
mut res := []string{}
|
||||||
separator := if path.ends_with(os.path_separator) { '' } else { os.path_separator }
|
separator := if path.ends_with(os.path_separator) { '' } else { os.path_separator }
|
||||||
for i, file in files {
|
for file in files {
|
||||||
if file.starts_with('.') {
|
if file.starts_with('.') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -276,6 +276,7 @@ pub:
|
||||||
mut:
|
mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
pos token.Position
|
pos token.Position
|
||||||
|
is_used bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GlobalDecl {
|
pub struct GlobalDecl {
|
||||||
|
|
|
@ -12,15 +12,9 @@ mut:
|
||||||
children []&Scope
|
children []&Scope
|
||||||
start_pos int
|
start_pos int
|
||||||
end_pos int
|
end_pos int
|
||||||
unused_vars map[string]UnusedVar
|
|
||||||
objects map[string]ScopeObject
|
objects map[string]ScopeObject
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnusedVar {
|
|
||||||
name string
|
|
||||||
pos token.Position
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_scope(parent &Scope, start_pos int) &Scope {
|
pub fn new_scope(parent &Scope, start_pos int) &Scope {
|
||||||
return &ast.Scope{
|
return &ast.Scope{
|
||||||
parent: parent
|
parent: parent
|
||||||
|
@ -63,12 +57,12 @@ pub fn (s &Scope) is_known(name string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s &Scope) find_var(name string) ?Var {
|
pub fn (s &Scope) find_var(name string) ?&Var {
|
||||||
if obj := s.find(name) {
|
if obj := s.find(name) {
|
||||||
v := ScopeObject(obj)
|
v := ScopeObject(obj)
|
||||||
match v {
|
match v {
|
||||||
Var {
|
Var {
|
||||||
return *it
|
return it
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -76,12 +70,12 @@ pub fn (s &Scope) find_var(name string) ?Var {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s &Scope) find_const(name string) ?ConstField {
|
pub fn (s &Scope) find_const(name string) ?&ConstField {
|
||||||
if obj := s.find(name) {
|
if obj := s.find(name) {
|
||||||
cf := ScopeObject(obj)
|
cf := ScopeObject(obj)
|
||||||
match cf {
|
match cf {
|
||||||
ConstField {
|
ConstField {
|
||||||
return *it
|
return it
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -112,37 +106,13 @@ pub fn (s mut Scope) register(name string, obj ScopeObject) {
|
||||||
if name == '_' {
|
if name == '_' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if x := s.find(name) {
|
if _ := s.find(name) {
|
||||||
// println('existing obect: $name')
|
// println('existing obect: $name')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.objects[name] = obj
|
s.objects[name] = obj
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s mut Scope) register_unused_var(name string, pos token.Position) {
|
|
||||||
s.unused_vars[name] = UnusedVar{name, pos}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (s mut Scope) remove_unused_var(name string) {
|
|
||||||
mut sc := s
|
|
||||||
for !isnil(sc) {
|
|
||||||
sc.unused_vars.delete(name)
|
|
||||||
sc = sc.parent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (s mut Scope) unused_vars() []UnusedVar {
|
|
||||||
ret := []UnusedVar{}
|
|
||||||
for _, v in s.unused_vars {
|
|
||||||
ret << v
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (s mut Scope) clear_unused_vars() {
|
|
||||||
s.unused_vars = map[string]UnusedVar
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (s &Scope) outermost() &Scope {
|
pub fn (s &Scope) outermost() &Scope {
|
||||||
mut sc := s
|
mut sc := s
|
||||||
for !isnil(sc.parent) {
|
for !isnil(sc.parent) {
|
||||||
|
|
|
@ -203,7 +203,7 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
|
||||||
}
|
}
|
||||||
c.error('struct name must begin with capital letter', pos)
|
c.error('struct name must begin with capital letter', pos)
|
||||||
}
|
}
|
||||||
for fi, field in decl.fields {
|
for field in decl.fields {
|
||||||
sym := c.table.get_type_symbol(field.typ)
|
sym := c.table.get_type_symbol(field.typ)
|
||||||
if sym.kind == .placeholder && !decl.is_c && !sym.name.starts_with('C.') {
|
if sym.kind == .placeholder && !decl.is_c && !sym.name.starts_with('C.') {
|
||||||
c.error('unknown type `$sym.name`', field.pos)
|
c.error('unknown type `$sym.name`', field.pos)
|
||||||
|
@ -554,7 +554,7 @@ pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
|
||||||
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
mut scope := c.file.scope.innermost(call_expr.pos.pos)
|
||||||
scope.update_var_type('it', array_info.elem_type)
|
scope.update_var_type('it', array_info.elem_type)
|
||||||
}
|
}
|
||||||
for i, arg in call_expr.args {
|
for arg in call_expr.args {
|
||||||
c.expr(arg.expr)
|
c.expr(arg.expr)
|
||||||
}
|
}
|
||||||
// need to return `array_xxx` instead of `array`
|
// need to return `array_xxx` instead of `array`
|
||||||
|
|
|
@ -480,7 +480,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
g.typedefs.writeln('typedef enum {')
|
g.typedefs.writeln('typedef enum {')
|
||||||
mut cur_enum_expr := ''
|
mut cur_enum_expr := ''
|
||||||
mut cur_enum_offset := 0
|
mut cur_enum_offset := 0
|
||||||
for j, field in it.fields {
|
for field in it.fields {
|
||||||
g.typedefs.write('\t${enum_name}_${field.name}')
|
g.typedefs.write('\t${enum_name}_${field.name}')
|
||||||
if field.has_expr {
|
if field.has_expr {
|
||||||
g.typedefs.write(' = ')
|
g.typedefs.write(' = ')
|
||||||
|
@ -1918,7 +1918,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
for i, field in node.fields {
|
for field in node.fields {
|
||||||
name := c_name(field.name)
|
name := c_name(field.name)
|
||||||
// TODO hack. Cut the generated value and paste it into definitions.
|
// TODO hack. Cut the generated value and paste it into definitions.
|
||||||
pos := g.out.len
|
pos := g.out.len
|
||||||
|
@ -3061,7 +3061,7 @@ fn (mut g Gen) gen_str_for_enum(info table.Enum, styp, str_fn_name string) {
|
||||||
g.definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
g.definitions.writeln('string ${str_fn_name}($styp it); // auto')
|
||||||
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
|
g.auto_str_funcs.writeln('string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
|
||||||
g.auto_str_funcs.writeln('\tswitch(it) {')
|
g.auto_str_funcs.writeln('\tswitch(it) {')
|
||||||
for i, val in info.vals {
|
for val in info.vals {
|
||||||
g.auto_str_funcs.writeln('\t\tcase ${s}_$val: return tos3("$val");')
|
g.auto_str_funcs.writeln('\t\tcase ${s}_$val: return tos3("$val");')
|
||||||
}
|
}
|
||||||
g.auto_str_funcs.writeln('\t\tdefault: return tos3("unknown enum value");')
|
g.auto_str_funcs.writeln('\t\tdefault: return tos3("unknown enum value");')
|
||||||
|
@ -3075,7 +3075,7 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp, str_fn_name string) {
|
||||||
mut fnames2strfunc := {
|
mut fnames2strfunc := {
|
||||||
'': ''
|
'': ''
|
||||||
} // map[string]string // TODO vfmt bug
|
} // map[string]string // TODO vfmt bug
|
||||||
for i, field in info.fields {
|
for field in info.fields {
|
||||||
sym := g.table.get_type_symbol(field.typ)
|
sym := g.table.get_type_symbol(field.typ)
|
||||||
if sym.kind in [.struct_, .array, .array_fixed, .map, .enum_] {
|
if sym.kind in [.struct_, .array, .array_fixed, .map, .enum_] {
|
||||||
field_styp := g.typ(field.typ)
|
field_styp := g.typ(field.typ)
|
||||||
|
|
|
@ -426,7 +426,7 @@ fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||||
is_forwarding_varg := args.len > 0 && args[args.len - 1].typ.flag_is(.variadic)
|
is_forwarding_varg := args.len > 0 && args[args.len - 1].typ.flag_is(.variadic)
|
||||||
gen_vargs := is_variadic && !is_forwarding_varg
|
gen_vargs := is_variadic && !is_forwarding_varg
|
||||||
mut arg_no := 0
|
mut arg_no := 0
|
||||||
for i, arg in args {
|
for arg in args {
|
||||||
if gen_vargs && arg_no == expected_types.len - 1 {
|
if gen_vargs && arg_no == expected_types.len - 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -600,7 +600,7 @@ fn (mut g Gen) allocate_var(name string, size, initial_val int) {
|
||||||
|
|
||||||
fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
||||||
// `a := 1` | `a,b := 1,2`
|
// `a := 1` | `a,b := 1,2`
|
||||||
for i, ident in node.left {
|
for ident in node.left {
|
||||||
match node.right[0] {
|
match node.right[0] {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
g.allocate_var(ident.name, 4, it.val.int())
|
g.allocate_var(ident.name, 4, it.val.int())
|
||||||
|
|
|
@ -32,11 +32,13 @@ fn (mut p Parser) assign_stmt() ast.Stmt {
|
||||||
name: ident.name
|
name: ident.name
|
||||||
expr: exprs[i]
|
expr: exprs[i]
|
||||||
is_mut: ident.is_mut || p.inside_for
|
is_mut: ident.is_mut || p.inside_for
|
||||||
|
pos: ident.pos
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
p.scope.register(ident.name, ast.Var{
|
p.scope.register(ident.name, ast.Var{
|
||||||
name: ident.name
|
name: ident.name
|
||||||
is_mut: ident.is_mut || p.inside_for
|
is_mut: ident.is_mut || p.inside_for
|
||||||
|
pos: ident.pos
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,14 @@ pub fn (mut p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
||||||
p.scope.register('err', ast.Var{
|
p.scope.register('err', ast.Var{
|
||||||
name: 'err'
|
name: 'err'
|
||||||
typ: table.string_type
|
typ: table.string_type
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
p.scope.register('errcode', ast.Var{
|
p.scope.register('errcode', ast.Var{
|
||||||
name: 'errcode'
|
name: 'errcode'
|
||||||
typ: table.int_type
|
typ: table.int_type
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
is_or_block_used = true
|
is_or_block_used = true
|
||||||
or_stmts = p.parse_block_no_scope()
|
or_stmts = p.parse_block_no_scope()
|
||||||
|
@ -164,6 +168,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||||
name: arg.name
|
name: arg.name
|
||||||
typ: arg.typ
|
typ: arg.typ
|
||||||
is_mut: arg.is_mut
|
is_mut: arg.is_mut
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
// Do not allow `mut` with simple types
|
// Do not allow `mut` with simple types
|
||||||
// TODO move to checker?
|
// TODO move to checker?
|
||||||
|
@ -264,6 +270,8 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
|
||||||
p.scope.register(arg.name, ast.Var{
|
p.scope.register(arg.name, ast.Var{
|
||||||
name: arg.name
|
name: arg.name
|
||||||
typ: arg.typ
|
typ: arg.typ
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mut return_type := table.void_type
|
mut return_type := table.void_type
|
||||||
|
|
|
@ -67,12 +67,16 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
}
|
}
|
||||||
} else if p.peek_tok.kind in [.key_in, .comma] {
|
} else if p.peek_tok.kind in [.key_in, .comma] {
|
||||||
// `for i in vals`, `for i in start .. end`
|
// `for i in vals`, `for i in start .. end`
|
||||||
|
mut val_var_pos := p.tok.position()
|
||||||
mut key_var_name := ''
|
mut key_var_name := ''
|
||||||
mut val_var_name := p.check_name()
|
mut val_var_name := p.check_name()
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
|
key_var_pos := val_var_pos
|
||||||
|
val_var_pos = p.tok.position()
|
||||||
key_var_name = val_var_name
|
key_var_name = val_var_name
|
||||||
val_var_name = p.check_name()
|
val_var_name = p.check_name()
|
||||||
|
|
||||||
if p.scope.known_var(key_var_name) {
|
if p.scope.known_var(key_var_name) {
|
||||||
p.error('redefinition of key iteration variable `$key_var_name`')
|
p.error('redefinition of key iteration variable `$key_var_name`')
|
||||||
}
|
}
|
||||||
|
@ -82,6 +86,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
p.scope.register(key_var_name, ast.Var{
|
p.scope.register(key_var_name, ast.Var{
|
||||||
name: key_var_name
|
name: key_var_name
|
||||||
typ: table.int_type
|
typ: table.int_type
|
||||||
|
pos: key_var_pos
|
||||||
})
|
})
|
||||||
} else if p.scope.known_var(val_var_name) {
|
} else if p.scope.known_var(val_var_name) {
|
||||||
p.error('redefinition of value iteration variable `$val_var_name`')
|
p.error('redefinition of value iteration variable `$val_var_name`')
|
||||||
|
@ -104,11 +109,13 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
p.scope.register(val_var_name, ast.Var{
|
p.scope.register(val_var_name, ast.Var{
|
||||||
name: val_var_name
|
name: val_var_name
|
||||||
typ: table.int_type
|
typ: table.int_type
|
||||||
|
pos: val_var_pos
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// this type will be set in checker
|
// this type will be set in checker
|
||||||
p.scope.register(val_var_name, ast.Var{
|
p.scope.register(val_var_name, ast.Var{
|
||||||
name: val_var_name
|
name: val_var_name
|
||||||
|
pos: val_var_pos
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
p.inside_for = false
|
p.inside_for = false
|
||||||
|
|
|
@ -43,12 +43,14 @@ fn (mut p Parser) if_expr() ast.IfExpr {
|
||||||
if p.peek_tok.kind == .decl_assign {
|
if p.peek_tok.kind == .decl_assign {
|
||||||
is_or = true
|
is_or = true
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
|
var_pos := p.tok.position()
|
||||||
var_name := p.check_name()
|
var_name := p.check_name()
|
||||||
p.check(.decl_assign)
|
p.check(.decl_assign)
|
||||||
expr := p.expr(0)
|
expr := p.expr(0)
|
||||||
p.scope.register(var_name, ast.Var{
|
p.scope.register(var_name, ast.Var{
|
||||||
name: var_name
|
name: var_name
|
||||||
expr: expr
|
expr: expr
|
||||||
|
pos: var_pos
|
||||||
})
|
})
|
||||||
cond = ast.IfGuardExpr{
|
cond = ast.IfGuardExpr{
|
||||||
var_name: var_name
|
var_name: var_name
|
||||||
|
@ -89,6 +91,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
if is_mut {
|
if is_mut {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
|
cond_pos := p.tok.position()
|
||||||
cond := p.expr(0)
|
cond := p.expr(0)
|
||||||
p.inside_match = false
|
p.inside_match = false
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
|
@ -119,6 +122,8 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
p.scope.register('it', ast.Var{
|
p.scope.register('it', ast.Var{
|
||||||
name: 'it'
|
name: 'it'
|
||||||
typ: typ.to_ptr()
|
typ: typ.to_ptr()
|
||||||
|
pos: cond_pos
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
// TODO
|
// TODO
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
|
|
|
@ -195,16 +195,22 @@ pub fn (mut p Parser) open_scope() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) close_scope() {
|
pub fn (mut p Parser) close_scope() {
|
||||||
if !p.pref.is_repl && !p.pref.is_fmt {
|
if !p.pref.is_repl && !p.scanner.is_fmt {
|
||||||
for v in p.scope.unused_vars() {
|
for _, obj in p.scope.objects {
|
||||||
|
match obj {
|
||||||
|
ast.Var {
|
||||||
|
if !it.is_used && !it.name.starts_with('__') {
|
||||||
if p.pref.is_prod {
|
if p.pref.is_prod {
|
||||||
p.error_with_pos('Unused variable: $v.name', v.pos)
|
p.error_with_pos('Unused variable: $it.name', it.pos)
|
||||||
} else {
|
} else {
|
||||||
p.warn_with_pos('Unused variable: $v.name', v.pos)
|
p.warn_with_pos('Unused variable: $it.name', it.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.scope.clear_unused_vars()
|
|
||||||
p.scope.end_pos = p.tok.pos
|
p.scope.end_pos = p.tok.pos
|
||||||
p.scope.parent.children << p.scope
|
p.scope.parent.children << p.scope
|
||||||
p.scope = p.scope.parent
|
p.scope = p.scope.parent
|
||||||
|
@ -393,9 +399,6 @@ pub fn (mut p Parser) stmt() ast.Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_mut, .key_static, .key_var {
|
.key_mut, .key_static, .key_var {
|
||||||
if p.peek_tok.kind == .name && p.peek_tok.lit != '_' && !p.peek_tok.lit.starts_with('__') {
|
|
||||||
p.scope.register_unused_var(p.peek_tok.lit, p.peek_tok.position())
|
|
||||||
}
|
|
||||||
return p.assign_stmt()
|
return p.assign_stmt()
|
||||||
}
|
}
|
||||||
.key_for {
|
.key_for {
|
||||||
|
@ -457,14 +460,7 @@ pub fn (mut p Parser) stmt() ast.Stmt {
|
||||||
else {
|
else {
|
||||||
// `x := ...`
|
// `x := ...`
|
||||||
if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
|
if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
|
||||||
register_unused := p.peek_tok.kind == .decl_assign
|
return p.assign_stmt()
|
||||||
lit := p.tok.lit
|
|
||||||
pos := p.tok.position()
|
|
||||||
ret := p.assign_stmt()
|
|
||||||
if register_unused && lit != '_' && !lit.starts_with('__') {
|
|
||||||
p.scope.register_unused_var(lit, pos)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
} else if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
} else if p.tok.kind == .name && p.peek_tok.kind == .colon {
|
||||||
// `label:`
|
// `label:`
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
|
@ -472,8 +468,6 @@ pub fn (mut p Parser) stmt() ast.Stmt {
|
||||||
return ast.GotoLabel{
|
return ast.GotoLabel{
|
||||||
name: name
|
name: name
|
||||||
}
|
}
|
||||||
} else if p.tok.kind == .name {
|
|
||||||
p.scope.remove_unused_var(p.tok.lit)
|
|
||||||
}
|
}
|
||||||
epos := p.tok.position()
|
epos := p.tok.position()
|
||||||
expr := p.expr(0)
|
expr := p.expr(0)
|
||||||
|
@ -609,7 +603,16 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && p.prev_tok.kind != .str_dollar {
|
if p.tok.lit in ['r', 'c', 'js'] && p.peek_tok.kind == .string && p.prev_tok.kind != .str_dollar {
|
||||||
return p.string_expr()
|
return p.string_expr()
|
||||||
}
|
}
|
||||||
known_var := p.scope.known_var(p.tok.lit)
|
mut known_var := false
|
||||||
|
if obj := p.scope.find(p.tok.lit) {
|
||||||
|
match mut obj {
|
||||||
|
ast.Var {
|
||||||
|
known_var = true
|
||||||
|
it.is_used = true
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
if p.peek_tok.kind == .dot && !known_var && (is_c || is_js || p.known_import(p.tok.lit) ||
|
if p.peek_tok.kind == .dot && !known_var && (is_c || is_js || p.known_import(p.tok.lit) ||
|
||||||
p.mod.all_after('.') == p.tok.lit) {
|
p.mod.all_after('.') == p.tok.lit) {
|
||||||
if is_c {
|
if is_c {
|
||||||
|
@ -753,6 +756,8 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
fn (mut p Parser) filter() {
|
fn (mut p Parser) filter() {
|
||||||
p.scope.register('it', ast.Var{
|
p.scope.register('it', ast.Var{
|
||||||
name: 'it'
|
name: 'it'
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,10 +788,14 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||||
p.scope.register('errcode', ast.Var{
|
p.scope.register('errcode', ast.Var{
|
||||||
name: 'errcode'
|
name: 'errcode'
|
||||||
typ: table.int_type
|
typ: table.int_type
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
p.scope.register('err', ast.Var{
|
p.scope.register('err', ast.Var{
|
||||||
name: 'err'
|
name: 'err'
|
||||||
typ: table.string_type
|
typ: table.string_type
|
||||||
|
pos: p.tok.position()
|
||||||
|
is_used: true
|
||||||
})
|
})
|
||||||
is_or_block_used = true
|
is_or_block_used = true
|
||||||
or_stmts = p.parse_block_no_scope()
|
or_stmts = p.parse_block_no_scope()
|
||||||
|
@ -1028,9 +1037,6 @@ fn (mut p Parser) return_stmt() ast.Return {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
if p.tok.kind == .name {
|
|
||||||
p.scope.remove_unused_var(p.tok.lit)
|
|
||||||
}
|
|
||||||
expr := p.expr(0)
|
expr := p.expr(0)
|
||||||
exprs << expr
|
exprs << expr
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
|
@ -1220,10 +1226,11 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
|
||||||
fn (mut p Parser) assoc() ast.Assoc {
|
fn (mut p Parser) assoc() ast.Assoc {
|
||||||
var_name := p.check_name()
|
var_name := p.check_name()
|
||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
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{}
|
||||||
}
|
}
|
||||||
|
v.is_used = true
|
||||||
// println('assoc var $name typ=$var.typ')
|
// println('assoc var $name typ=$var.typ')
|
||||||
mut fields := []string{}
|
mut fields := []string{}
|
||||||
mut vals := []ast.Expr{}
|
mut vals := []ast.Expr{}
|
||||||
|
@ -1245,7 +1252,7 @@ fn (mut p Parser) assoc() ast.Assoc {
|
||||||
fields: fields
|
fields: fields
|
||||||
exprs: vals
|
exprs: vals
|
||||||
pos: pos
|
pos: pos
|
||||||
typ: v.typ
|
// typ: v.typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
// Prefix
|
// Prefix
|
||||||
match p.tok.kind {
|
match p.tok.kind {
|
||||||
.name {
|
.name {
|
||||||
p.scope.remove_unused_var(p.tok.lit)
|
|
||||||
node = p.name_expr()
|
node = p.name_expr()
|
||||||
p.is_stmt_ident = is_stmt_ident
|
p.is_stmt_ident = is_stmt_ident
|
||||||
}
|
}
|
||||||
|
@ -79,7 +78,6 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
type_name: p.check_name()
|
type_name: p.check_name()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
p.scope.remove_unused_var(p.tok.lit)
|
|
||||||
sizeof_type := p.parse_type()
|
sizeof_type := p.parse_type()
|
||||||
node = ast.SizeOf{
|
node = ast.SizeOf{
|
||||||
typ: sizeof_type
|
typ: sizeof_type
|
||||||
|
@ -104,7 +102,6 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
} else {
|
} else {
|
||||||
// it should be a struct
|
// it should be a struct
|
||||||
if p.peek_tok.kind == .pipe {
|
if p.peek_tok.kind == .pipe {
|
||||||
p.scope.remove_unused_var(p.tok.lit)
|
|
||||||
node = p.assoc()
|
node = p.assoc()
|
||||||
} else if p.peek_tok.kind == .colon || p.tok.kind == .rcbr {
|
} else if p.peek_tok.kind == .colon || p.tok.kind == .rcbr {
|
||||||
node = p.struct_init(true) // short_syntax: true
|
node = p.struct_init(true) // short_syntax: true
|
||||||
|
|
|
@ -66,7 +66,7 @@ pub fn (t Type) is_ptr() bool {
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t Type) set_nr_muls(nr_muls int) Type {
|
pub fn (t Type) set_nr_muls(nr_muls int) Type {
|
||||||
if nr_muls < 0 || nr_muls > 255 {
|
if nr_muls < 0 || nr_muls > 255 {
|
||||||
panic('typ_set_nr_muls: nr_muls must be between 0 & 255')
|
panic('set_nr_muls: nr_muls must be between 0 & 255')
|
||||||
}
|
}
|
||||||
return (((int(t) >> 24) & 0xff) << 24) | (nr_muls << 16) | (u16(t) & 0xffff)
|
return (((int(t) >> 24) & 0xff) << 24) | (nr_muls << 16) | (u16(t) & 0xffff)
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ pub fn (t Type) set_nr_muls(nr_muls int) Type {
|
||||||
pub fn (t Type) to_ptr() Type {
|
pub fn (t Type) to_ptr() Type {
|
||||||
nr_muls := (int(t) >> 16) & 0xff
|
nr_muls := (int(t) >> 16) & 0xff
|
||||||
if nr_muls == 255 {
|
if nr_muls == 255 {
|
||||||
panic('type_to_pre: nr_muls is already at max of 255')
|
panic('to_ptr: nr_muls is already at max of 255')
|
||||||
}
|
}
|
||||||
return (((int(t) >> 24) & 0xff) << 24) | ((nr_muls + 1) << 16) | (u16(t) & 0xffff)
|
return (((int(t) >> 24) & 0xff) << 24) | ((nr_muls + 1) << 16) | (u16(t) & 0xffff)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue