checker: use the new match syntax
parent
78b32892ac
commit
5ddb129bc2
|
@ -126,63 +126,63 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
|
||||||
for stmt in file.stmts {
|
for stmt in file.stmts {
|
||||||
match stmt {
|
match stmt {
|
||||||
ast.ConstDecl {
|
ast.ConstDecl {
|
||||||
if it.is_pub {
|
if stmt.is_pub {
|
||||||
c.warn('const $no_pub_in_main_warning', it.pos)
|
c.warn('const $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.ConstField {
|
ast.ConstField {
|
||||||
if it.is_pub {
|
if stmt.is_pub {
|
||||||
c.warn('const field `$it.name` $no_pub_in_main_warning', it.pos)
|
c.warn('const field `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
if it.is_pub {
|
if stmt.is_pub {
|
||||||
c.warn('enum `$it.name` $no_pub_in_main_warning', it.pos)
|
c.warn('enum `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
if it.name == 'main' {
|
if stmt.name == 'main' {
|
||||||
has_main_fn = true
|
has_main_fn = true
|
||||||
if it.is_pub {
|
if stmt.is_pub {
|
||||||
c.error('function `main` cannot be declared public', it.pos)
|
c.error('function `main` cannot be declared public', stmt.pos)
|
||||||
}
|
}
|
||||||
if it.args.len > 0 {
|
if stmt.args.len > 0 {
|
||||||
c.error('function `main` cannot have arguments', it.pos)
|
c.error('function `main` cannot have arguments', stmt.pos)
|
||||||
}
|
}
|
||||||
if it.return_type != table.void_type {
|
if stmt.return_type != table.void_type {
|
||||||
c.error('function `main` cannot return values', it.pos)
|
c.error('function `main` cannot return values', stmt.pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if it.is_pub && !it.is_method {
|
if stmt.is_pub && !stmt.is_method {
|
||||||
c.warn('function `$it.name` $no_pub_in_main_warning', it.pos)
|
c.warn('function `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if it.ctdefine.len > 0 {
|
if stmt.ctdefine.len > 0 {
|
||||||
if it.return_type != table.void_type {
|
if stmt.return_type != table.void_type {
|
||||||
c.error('only functions that do NOT return values can have `[if ${it.ctdefine}]` tags',
|
c.error('only functions that do NOT return values can have `[if $stmt.ctdefine]` tags',
|
||||||
it.pos)
|
stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
if it.is_pub {
|
if stmt.is_pub {
|
||||||
c.warn('struct `$it.name` $no_pub_in_main_warning', it.pos)
|
c.warn('struct `$stmt.name` $no_pub_in_main_warning', stmt.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.TypeDecl {
|
ast.TypeDecl {
|
||||||
// type_decl := stmt as ast.TypeDecl
|
// type_decl := stmt as ast.TypeDecl
|
||||||
if it is ast.AliasTypeDecl {
|
if stmt is ast.AliasTypeDecl {
|
||||||
alias_decl := it as ast.AliasTypeDecl
|
alias_decl := stmt as ast.AliasTypeDecl
|
||||||
if alias_decl.is_pub {
|
if alias_decl.is_pub {
|
||||||
c.warn('type alias `$alias_decl.name` $no_pub_in_main_warning', alias_decl.pos)
|
c.warn('type alias `$alias_decl.name` $no_pub_in_main_warning', alias_decl.pos)
|
||||||
}
|
}
|
||||||
} else if it is ast.SumTypeDecl {
|
} else if stmt is ast.SumTypeDecl {
|
||||||
sum_decl := it as ast.SumTypeDecl
|
sum_decl := stmt as ast.SumTypeDecl
|
||||||
if sum_decl.is_pub {
|
if sum_decl.is_pub {
|
||||||
c.warn('sum type `$sum_decl.name` $no_pub_in_main_warning', sum_decl.pos)
|
c.warn('sum type `$sum_decl.name` $no_pub_in_main_warning', sum_decl.pos)
|
||||||
}
|
}
|
||||||
} else if it is ast.FnTypeDecl {
|
} else if stmt is ast.FnTypeDecl {
|
||||||
fn_decl := it as ast.FnTypeDecl
|
fn_decl := stmt as ast.FnTypeDecl
|
||||||
if fn_decl.is_pub {
|
if fn_decl.is_pub {
|
||||||
c.warn('type alias `$fn_decl.name` $no_pub_in_main_warning', fn_decl.pos)
|
c.warn('type alias `$fn_decl.name` $no_pub_in_main_warning', fn_decl.pos)
|
||||||
}
|
}
|
||||||
|
@ -223,35 +223,35 @@ pub fn (mut c Checker) type_decl(node ast.TypeDecl) {
|
||||||
ast.AliasTypeDecl {
|
ast.AliasTypeDecl {
|
||||||
// TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available
|
// TODO Replace `c.file.mod.name != 'time'` by `it.language != .v` once available
|
||||||
if c.file.mod.name != 'time' {
|
if c.file.mod.name != 'time' {
|
||||||
c.check_valid_pascal_case(it.name, 'type alias', it.pos)
|
c.check_valid_pascal_case(node.name, 'type alias', node.pos)
|
||||||
}
|
}
|
||||||
typ_sym := c.table.get_type_symbol(it.parent_type)
|
typ_sym := c.table.get_type_symbol(node.parent_type)
|
||||||
if typ_sym.kind == .placeholder {
|
if typ_sym.kind == .placeholder {
|
||||||
c.error("type `$typ_sym.name` doesn't exist", it.pos)
|
c.error("type `$typ_sym.name` doesn't exist", node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.FnTypeDecl {
|
ast.FnTypeDecl {
|
||||||
c.check_valid_pascal_case(it.name, 'fn type', it.pos)
|
c.check_valid_pascal_case(node.name, 'fn type', node.pos)
|
||||||
typ_sym := c.table.get_type_symbol(it.typ)
|
typ_sym := c.table.get_type_symbol(node.typ)
|
||||||
fn_typ_info := typ_sym.info as table.FnType
|
fn_typ_info := typ_sym.info as table.FnType
|
||||||
fn_info := fn_typ_info.func
|
fn_info := fn_typ_info.func
|
||||||
ret_sym := c.table.get_type_symbol(fn_info.return_type)
|
ret_sym := c.table.get_type_symbol(fn_info.return_type)
|
||||||
if ret_sym.kind == .placeholder {
|
if ret_sym.kind == .placeholder {
|
||||||
c.error("type `$ret_sym.name` doesn't exist", it.pos)
|
c.error("type `$ret_sym.name` doesn't exist", node.pos)
|
||||||
}
|
}
|
||||||
for arg in fn_info.args {
|
for arg in fn_info.args {
|
||||||
arg_sym := c.table.get_type_symbol(arg.typ)
|
arg_sym := c.table.get_type_symbol(arg.typ)
|
||||||
if arg_sym.kind == .placeholder {
|
if arg_sym.kind == .placeholder {
|
||||||
c.error("type `$arg_sym.name` doesn't exist", it.pos)
|
c.error("type `$arg_sym.name` doesn't exist", node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.SumTypeDecl {
|
ast.SumTypeDecl {
|
||||||
c.check_valid_pascal_case(it.name, 'sum type', it.pos)
|
c.check_valid_pascal_case(node.name, 'sum type', node.pos)
|
||||||
for typ in it.sub_types {
|
for typ in node.sub_types {
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
if typ_sym.kind == .placeholder {
|
if typ_sym.kind == .placeholder {
|
||||||
c.error("type `$typ_sym.name` doesn't exist", it.pos)
|
c.error("type `$typ_sym.name` doesn't exist", node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ pub fn (mut c Checker) struct_decl(decl ast.StructDecl) {
|
||||||
if !c.check_types(field_expr_type, field.typ) {
|
if !c.check_types(field_expr_type, field.typ) {
|
||||||
field_expr_type_sym := c.table.get_type_symbol(field_expr_type)
|
field_expr_type_sym := c.table.get_type_symbol(field_expr_type)
|
||||||
field_type_sym := c.table.get_type_symbol(field.typ)
|
field_type_sym := c.table.get_type_symbol(field.typ)
|
||||||
c.error('default expression for field `${field.name}` ' + 'has type `${field_expr_type_sym.name}`, but should be `${field_type_sym.name}`',
|
c.error('default expression for field `$field.name` ' + 'has type `$field_expr_type_sym.name`, but should be `$field_type_sym.name`',
|
||||||
field.default_expr.position())
|
field.default_expr.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,7 +404,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if field.typ.is_ptr() {
|
if field.typ.is_ptr() {
|
||||||
c.warn('reference field `${type_sym.name}.${field.name}` must be initialized',
|
c.warn('reference field `${type_sym.name}.$field.name` must be initialized',
|
||||||
struct_init.pos)
|
struct_init.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -498,7 +498,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
if infix_expr.op == .mod {
|
if infix_expr.op == .mod {
|
||||||
c.error('float modulo not allowed, use math.fmod() instead', pos)
|
c.error('float modulo not allowed, use math.fmod() instead', pos)
|
||||||
} else {
|
} else {
|
||||||
c.error('$side type of `${infix_expr.op.str()}` cannot be non-integer type $name',
|
c.error('$side type of `$infix_expr.op.str()` cannot be non-integer type $name',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,7 +553,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
type_expr := infix_expr.right as ast.Type
|
type_expr := infix_expr.right as ast.Type
|
||||||
typ_sym := c.table.get_type_symbol(type_expr.typ)
|
typ_sym := c.table.get_type_symbol(type_expr.typ)
|
||||||
if typ_sym.kind == .placeholder {
|
if typ_sym.kind == .placeholder {
|
||||||
c.error('$infix_expr.op.str(): type `${typ_sym.name}` does not exist', type_expr.pos)
|
c.error('$infix_expr.op.str(): type `$typ_sym.name` does not exist', type_expr.pos)
|
||||||
}
|
}
|
||||||
if left.kind != .interface_ && left.kind != .sum_type {
|
if left.kind != .interface_ && left.kind != .sum_type {
|
||||||
c.error('`$infix_expr.op.str()` can only be used with interfaces and sum types',
|
c.error('`$infix_expr.op.str()` can only be used with interfaces and sum types',
|
||||||
|
@ -607,58 +607,58 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
scope := c.file.scope.innermost(it.pos.pos)
|
scope := c.file.scope.innermost(expr.pos.pos)
|
||||||
if v := scope.find_var(it.name) {
|
if v := scope.find_var(expr.name) {
|
||||||
if !v.is_mut && !v.typ.is_ptr() {
|
if !v.is_mut && !v.typ.is_ptr() {
|
||||||
c.error('`$it.name` is immutable, declare it with `mut` to make it mutable',
|
c.error('`$expr.name` is immutable, declare it with `mut` to make it mutable',
|
||||||
it.pos)
|
expr.pos)
|
||||||
}
|
}
|
||||||
v.is_changed = true
|
v.is_changed = true
|
||||||
} else if it.name in c.const_names {
|
} else if expr.name in c.const_names {
|
||||||
c.error('cannot modify constant `$it.name`', it.pos)
|
c.error('cannot modify constant `$expr.name`', expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
c.fail_if_immutable(it.left)
|
c.fail_if_immutable(expr.left)
|
||||||
}
|
}
|
||||||
ast.ParExpr {
|
ast.ParExpr {
|
||||||
c.fail_if_immutable(it.expr)
|
c.fail_if_immutable(expr.expr)
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
c.fail_if_immutable(it.right)
|
c.fail_if_immutable(expr.right)
|
||||||
}
|
}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
// retrieve table.Field
|
// retrieve table.Field
|
||||||
if it.expr_type == 0 {
|
if expr.expr_type == 0 {
|
||||||
c.error('0 type in SelectorExpr', it.pos)
|
c.error('0 type in SelectorExpr', expr.pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
typ_sym := c.table.get_type_symbol(c.unwrap_generic(it.expr_type))
|
typ_sym := c.table.get_type_symbol(c.unwrap_generic(expr.expr_type))
|
||||||
match typ_sym.kind {
|
match typ_sym.kind {
|
||||||
.struct_ {
|
.struct_ {
|
||||||
struct_info := typ_sym.info as table.Struct
|
struct_info := typ_sym.info as table.Struct
|
||||||
field_info := struct_info.find_field(it.field_name) or {
|
field_info := struct_info.find_field(expr.field_name) or {
|
||||||
type_str := c.table.type_to_str(it.expr_type)
|
type_str := c.table.type_to_str(expr.expr_type)
|
||||||
c.error('unknown field `${type_str}.$it.field_name`', it.pos)
|
c.error('unknown field `${type_str}.$expr.field_name`', expr.pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !field_info.is_mut {
|
if !field_info.is_mut {
|
||||||
type_str := c.table.type_to_str(it.expr_type)
|
type_str := c.table.type_to_str(expr.expr_type)
|
||||||
c.error('field `$it.field_name` of struct `${type_str}` is immutable',
|
c.error('field `$expr.field_name` of struct `$type_str` is immutable',
|
||||||
it.pos)
|
expr.pos)
|
||||||
}
|
}
|
||||||
c.fail_if_immutable(it.expr)
|
c.fail_if_immutable(expr.expr)
|
||||||
}
|
}
|
||||||
.array, .string {
|
.array, .string {
|
||||||
// This should only happen in `builtin`
|
// This should only happen in `builtin`
|
||||||
// TODO Remove `crypto.rand` when possible (see vlib/crypto/rand/rand.v,
|
// TODO Remove `crypto.rand` when possible (see vlib/crypto/rand/rand.v,
|
||||||
// if `c_array_to_bytes_tmp` doesn't exist, then it's safe to remove it)
|
// if `c_array_to_bytes_tmp` doesn't exist, then it's safe to remove it)
|
||||||
if c.file.mod.name !in ['builtin', 'crypto.rand'] {
|
if c.file.mod.name !in ['builtin', 'crypto.rand'] {
|
||||||
c.error('`$typ_sym.kind` can not be modified', it.pos)
|
c.error('`$typ_sym.kind` can not be modified', expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
c.error('unexpected symbol `${typ_sym.kind}`', it.pos)
|
c.error('unexpected symbol `$typ_sym.kind`', expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1109,7 +1109,7 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
||||||
pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type) {
|
pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type) {
|
||||||
if or_expr.kind == .propagate {
|
if or_expr.kind == .propagate {
|
||||||
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main' {
|
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main' {
|
||||||
c.error('to propagate the optional call, `${c.cur_fn.name}` must itself return an optional',
|
c.error('to propagate the optional call, `$c.cur_fn.name` must itself return an optional',
|
||||||
or_expr.pos)
|
or_expr.pos)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -1134,22 +1134,22 @@ pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type
|
||||||
}
|
}
|
||||||
match last_stmt {
|
match last_stmt {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
it.typ = c.expr(it.expr)
|
last_stmt.typ = c.expr(last_stmt.expr)
|
||||||
type_fits := c.check_types(it.typ, ret_type)
|
type_fits := c.check_types(last_stmt.typ, ret_type)
|
||||||
is_panic_or_exit := is_expr_panic_or_exit(it.expr)
|
is_panic_or_exit := is_expr_panic_or_exit(last_stmt.expr)
|
||||||
if type_fits || is_panic_or_exit {
|
if type_fits || is_panic_or_exit {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
type_name := c.table.get_type_symbol(it.typ).name
|
type_name := c.table.get_type_symbol(last_stmt.typ).name
|
||||||
expected_type_name := c.table.get_type_symbol(ret_type).name
|
expected_type_name := c.table.get_type_symbol(ret_type).name
|
||||||
c.error('wrong return type `$type_name` in the `or {}` block, expected `$expected_type_name`',
|
c.error('wrong return type `$type_name` in the `or {}` block, expected `$expected_type_name`',
|
||||||
it.pos)
|
last_stmt.pos)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ast.BranchStmt {
|
ast.BranchStmt {
|
||||||
if it.tok.kind !in [.key_continue, .key_break] {
|
if last_stmt.tok.kind !in [.key_continue, .key_break] {
|
||||||
c.error('only break/continue is allowed as a branch statement in the end of an `or {}` block',
|
c.error('only break/continue is allowed as a branch statement in the end of an `or {}` block',
|
||||||
it.tok.position())
|
last_stmt.tok.position())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1161,7 +1161,7 @@ pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type
|
||||||
|
|
||||||
fn is_expr_panic_or_exit(expr ast.Expr) bool {
|
fn is_expr_panic_or_exit(expr ast.Expr) bool {
|
||||||
match expr {
|
match expr {
|
||||||
ast.CallExpr { return it.name in ['panic', 'exit'] }
|
ast.CallExpr { return expr.name in ['panic', 'exit'] }
|
||||||
else { return false }
|
else { return false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1350,26 +1350,26 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
assign_stmt.left_types << left_type
|
assign_stmt.left_types << left_type
|
||||||
match left {
|
match left {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if it.kind == .blank_ident {
|
if left.kind == .blank_ident {
|
||||||
left_type = right_type
|
left_type = right_type
|
||||||
assign_stmt.left_types[i] = right_type
|
assign_stmt.left_types[i] = right_type
|
||||||
if assign_stmt.op !in [.assign, .decl_assign] {
|
if assign_stmt.op !in [.assign, .decl_assign] {
|
||||||
c.error('cannot modify blank `_` identifier', it.pos)
|
c.error('cannot modify blank `_` identifier', left.pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if is_decl {
|
if is_decl {
|
||||||
c.check_valid_snake_case(it.name, 'variable name', it.pos)
|
c.check_valid_snake_case(left.name, 'variable name', left.pos)
|
||||||
}
|
}
|
||||||
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
mut scope := c.file.scope.innermost(assign_stmt.pos.pos)
|
||||||
mut ident_var_info := it.var_info()
|
mut ident_var_info := left.var_info()
|
||||||
ident_var_info.typ = left_type
|
ident_var_info.typ = left_type
|
||||||
it.info = ident_var_info
|
left.info = ident_var_info
|
||||||
scope.update_var_type(it.name, left_type)
|
scope.update_var_type(left.name, left_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
// Do now allow `*x = y` outside `unsafe`
|
// Do now allow `*x = y` outside `unsafe`
|
||||||
if it.op == .mul && !c.inside_unsafe {
|
if left.op == .mul && !c.inside_unsafe {
|
||||||
c.error('modifying variables via deferencing can only be done in `unsafe` blocks',
|
c.error('modifying variables via deferencing can only be done in `unsafe` blocks',
|
||||||
assign_stmt.pos)
|
assign_stmt.pos)
|
||||||
}
|
}
|
||||||
|
@ -1409,19 +1409,19 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
.mult_assign, .div_assign {
|
.mult_assign, .div_assign {
|
||||||
if !left_sym.is_number() {
|
if !left_sym.is_number() {
|
||||||
c.error('operator ${assign_stmt.op.str()} not defined on left operand type `$left_sym.name`',
|
c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
|
||||||
left.position())
|
left.position())
|
||||||
} else if !right_sym.is_number() {
|
} else if !right_sym.is_number() {
|
||||||
c.error('operator ${assign_stmt.op.str()} not defined on right operand type `$right_sym.name`',
|
c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
|
||||||
right.position())
|
right.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.and_assign, .or_assign, .xor_assign, .mod_assign, .left_shift_assign, .right_shift_assign {
|
.and_assign, .or_assign, .xor_assign, .mod_assign, .left_shift_assign, .right_shift_assign {
|
||||||
if !left_sym.is_int() {
|
if !left_sym.is_int() {
|
||||||
c.error('operator ${assign_stmt.op.str()} not defined on left operand type `$left_sym.name`',
|
c.error('operator $assign_stmt.op.str() not defined on left operand type `$left_sym.name`',
|
||||||
left.position())
|
left.position())
|
||||||
} else if !right_sym.is_int() {
|
} else if !right_sym.is_int() {
|
||||||
c.error('operator ${assign_stmt.op.str()} not defined on right operand type `$right_sym.name`',
|
c.error('operator $assign_stmt.op.str() not defined on right operand type `$right_sym.name`',
|
||||||
right.position())
|
right.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1429,7 +1429,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
// Dual sides check (compatibility check)
|
// Dual sides check (compatibility check)
|
||||||
if !is_blank_ident && !c.check_types(right_type_unwrapped, left_type_unwrapped) {
|
if !is_blank_ident && !c.check_types(right_type_unwrapped, left_type_unwrapped) {
|
||||||
c.error('cannot assign `$right_sym.name` to `${left.str()}` of type `$left_sym.name`',
|
c.error('cannot assign `$right_sym.name` to `$left.str()` of type `$left_sym.name`',
|
||||||
right.position())
|
right.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1588,36 +1588,36 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
// c.expected_type = table.void_type
|
// c.expected_type = table.void_type
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.AssertStmt {
|
ast.AssertStmt {
|
||||||
assert_type := c.expr(it.expr)
|
assert_type := c.expr(node.expr)
|
||||||
if assert_type != table.bool_type_idx {
|
if assert_type != table.bool_type_idx {
|
||||||
atype_name := c.table.get_type_symbol(assert_type).name
|
atype_name := c.table.get_type_symbol(assert_type).name
|
||||||
c.error('assert can be used only with `bool` expressions, but found `${atype_name}` instead',
|
c.error('assert can be used only with `bool` expressions, but found `$atype_name` instead',
|
||||||
it.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ast.Attr {}
|
// ast.Attr {}
|
||||||
ast.AssignStmt {
|
ast.AssignStmt {
|
||||||
c.assign_stmt(mut it)
|
c.assign_stmt(mut node)
|
||||||
}
|
}
|
||||||
ast.Block {
|
ast.Block {
|
||||||
c.stmts(it.stmts)
|
c.stmts(node.stmts)
|
||||||
}
|
}
|
||||||
ast.BranchStmt {
|
ast.BranchStmt {
|
||||||
if c.in_for_count == 0 {
|
if c.in_for_count == 0 {
|
||||||
c.error('$it.tok.lit statement not within a loop', it.tok.position())
|
c.error('$node.tok.lit statement not within a loop', node.tok.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CompIf {
|
ast.CompIf {
|
||||||
// c.expr(it.cond)
|
// c.expr(it.cond)
|
||||||
c.stmts(it.stmts)
|
c.stmts(node.stmts)
|
||||||
if it.has_else {
|
if node.has_else {
|
||||||
c.stmts(it.else_stmts)
|
c.stmts(node.else_stmts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.ConstDecl {
|
ast.ConstDecl {
|
||||||
mut field_names := []string{}
|
mut field_names := []string{}
|
||||||
mut field_order := []int{}
|
mut field_order := []int{}
|
||||||
for i, field in it.fields {
|
for i, field in node.fields {
|
||||||
// TODO Check const name once the syntax is decided
|
// TODO Check const name once the syntax is decided
|
||||||
if field.name in c.const_names {
|
if field.name in c.const_names {
|
||||||
c.error('field name `$field.name` duplicate', field.pos)
|
c.error('field name `$field.name` duplicate', field.pos)
|
||||||
|
@ -1628,13 +1628,13 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
mut needs_order := false
|
mut needs_order := false
|
||||||
mut done_fields := []int{}
|
mut done_fields := []int{}
|
||||||
for i, field in it.fields {
|
for i, field in node.fields {
|
||||||
c.const_decl = field.name
|
c.const_decl = field.name
|
||||||
c.const_deps << field.name
|
c.const_deps << field.name
|
||||||
typ := c.expr(field.expr)
|
typ := c.expr(field.expr)
|
||||||
it.fields[i].typ = c.table.mktyp(typ)
|
node.fields[i].typ = c.table.mktyp(typ)
|
||||||
for cd in c.const_deps {
|
for cd in c.const_deps {
|
||||||
for j, f in it.fields {
|
for j, f in node.fields {
|
||||||
if j != i && cd in field_names && cd == f.name && j !in done_fields {
|
if j != i && cd in field_names && cd == f.name && j !in done_fields {
|
||||||
needs_order = true
|
needs_order = true
|
||||||
x := field_order[j]
|
x := field_order[j]
|
||||||
|
@ -1650,60 +1650,60 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
if needs_order {
|
if needs_order {
|
||||||
mut ordered_fields := []ast.ConstField{}
|
mut ordered_fields := []ast.ConstField{}
|
||||||
for order in field_order {
|
for order in field_order {
|
||||||
ordered_fields << it.fields[order]
|
ordered_fields << node.fields[order]
|
||||||
}
|
}
|
||||||
it.fields = ordered_fields
|
node.fields = ordered_fields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.DeferStmt {
|
ast.DeferStmt {
|
||||||
c.stmts(it.stmts)
|
c.stmts(node.stmts)
|
||||||
}
|
}
|
||||||
ast.EnumDecl {
|
ast.EnumDecl {
|
||||||
c.enum_decl(it)
|
c.enum_decl(node)
|
||||||
}
|
}
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
it.typ = c.expr(it.expr)
|
node.typ = c.expr(node.expr)
|
||||||
c.expected_type = table.void_type
|
c.expected_type = table.void_type
|
||||||
c.check_expr_opt_call(it.expr, table.void_type)
|
c.check_expr_opt_call(node.expr, table.void_type)
|
||||||
// TODO This should work, even if it's prolly useless .-.
|
// TODO This should work, even if it's prolly useless .-.
|
||||||
// it.typ = c.check_expr_opt_call(it.expr, table.void_type)
|
// it.typ = c.check_expr_opt_call(it.expr, table.void_type)
|
||||||
}
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
c.fn_decl(it)
|
c.fn_decl(node)
|
||||||
}
|
}
|
||||||
ast.ForCStmt {
|
ast.ForCStmt {
|
||||||
c.in_for_count++
|
c.in_for_count++
|
||||||
c.stmt(it.init)
|
c.stmt(node.init)
|
||||||
c.expr(it.cond)
|
c.expr(node.cond)
|
||||||
c.stmt(it.inc)
|
c.stmt(node.inc)
|
||||||
// c.expr(it.inc)
|
// c.expr(it.inc)
|
||||||
c.stmts(it.stmts)
|
c.stmts(node.stmts)
|
||||||
c.in_for_count--
|
c.in_for_count--
|
||||||
}
|
}
|
||||||
ast.ForInStmt {
|
ast.ForInStmt {
|
||||||
c.in_for_count++
|
c.in_for_count++
|
||||||
typ := c.expr(it.cond)
|
typ := c.expr(node.cond)
|
||||||
typ_idx := typ.idx()
|
typ_idx := typ.idx()
|
||||||
if it.is_range {
|
if node.is_range {
|
||||||
high_type_idx := c.expr(it.high).idx()
|
high_type_idx := c.expr(node.high).idx()
|
||||||
if typ_idx in table.integer_type_idxs && high_type_idx !in table.integer_type_idxs {
|
if typ_idx in table.integer_type_idxs && high_type_idx !in table.integer_type_idxs {
|
||||||
c.error('range types do not match', it.cond.position())
|
c.error('range types do not match', node.cond.position())
|
||||||
} else if typ_idx in table.float_type_idxs || high_type_idx in table.float_type_idxs {
|
} else if typ_idx in table.float_type_idxs || high_type_idx in table.float_type_idxs {
|
||||||
c.error('range type can not be float', it.cond.position())
|
c.error('range type can not be float', node.cond.position())
|
||||||
} else if typ_idx == table.bool_type_idx || high_type_idx == table.bool_type_idx {
|
} else if typ_idx == table.bool_type_idx || high_type_idx == table.bool_type_idx {
|
||||||
c.error('range type can not be bool', it.cond.position())
|
c.error('range type can not be bool', node.cond.position())
|
||||||
} else if typ_idx == table.string_type_idx || high_type_idx == table.string_type_idx {
|
} else if typ_idx == table.string_type_idx || high_type_idx == table.string_type_idx {
|
||||||
c.error('range type can not be string', it.cond.position())
|
c.error('range type can not be string', node.cond.position())
|
||||||
}
|
}
|
||||||
c.expr(it.high)
|
c.expr(node.high)
|
||||||
} else {
|
} else {
|
||||||
mut scope := c.file.scope.innermost(it.pos.pos)
|
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 && !(it.key_var.len > 0 && it.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' +
|
||||||
'use `_` if you do not need the variable', it.pos)
|
'use `_` if you do not need the variable', node.pos)
|
||||||
}
|
}
|
||||||
if it.key_var.len > 0 {
|
if node.key_var.len > 0 {
|
||||||
key_type := match sym.kind {
|
key_type := match sym.kind {
|
||||||
.map { sym.map_info().key_type }
|
.map { sym.map_info().key_type }
|
||||||
else { table.int_type }
|
else { table.int_type }
|
||||||
|
@ -1817,85 +1817,85 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
keep_fn := c.cur_fn
|
keep_fn := c.cur_fn
|
||||||
c.cur_fn = &it.decl
|
c.cur_fn = &node.decl
|
||||||
c.stmts(it.decl.stmts)
|
c.stmts(node.decl.stmts)
|
||||||
c.cur_fn = keep_fn
|
c.cur_fn = keep_fn
|
||||||
return it.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
return c.array_init(mut it)
|
return c.array_init(mut node)
|
||||||
}
|
}
|
||||||
ast.AsCast {
|
ast.AsCast {
|
||||||
it.expr_type = c.expr(it.expr)
|
node.expr_type = c.expr(node.expr)
|
||||||
expr_type_sym := c.table.get_type_symbol(it.expr_type)
|
expr_type_sym := c.table.get_type_symbol(node.expr_type)
|
||||||
type_sym := c.table.get_type_symbol(it.typ)
|
type_sym := c.table.get_type_symbol(node.typ)
|
||||||
if expr_type_sym.kind == .sum_type {
|
if expr_type_sym.kind == .sum_type {
|
||||||
info := expr_type_sym.info as table.SumType
|
info := expr_type_sym.info as table.SumType
|
||||||
if it.typ !in info.variants {
|
if node.typ !in info.variants {
|
||||||
c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', it.pos)
|
c.error('cannot cast `$expr_type_sym.name` to `$type_sym.name`', node.pos)
|
||||||
// c.error('only $info.variants can be casted to `$typ`', it.pos)
|
// c.error('only $info.variants can be casted to `$typ`', it.pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
c.error('cannot cast non sum type `$type_sym.name` using `as`', it.pos)
|
c.error('cannot cast non sum type `$type_sym.name` using `as`', node.pos)
|
||||||
}
|
}
|
||||||
return it.typ.to_ptr()
|
return node.typ.to_ptr()
|
||||||
// return it.typ
|
// return it.typ
|
||||||
}
|
}
|
||||||
ast.Assoc {
|
ast.Assoc {
|
||||||
scope := c.file.scope.innermost(it.pos.pos)
|
scope := c.file.scope.innermost(node.pos.pos)
|
||||||
v := scope.find_var(it.var_name) or {
|
v := scope.find_var(node.var_name) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
for i, _ in it.fields {
|
for i, _ in node.fields {
|
||||||
c.expr(it.exprs[i])
|
c.expr(node.exprs[i])
|
||||||
}
|
}
|
||||||
it.typ = v.typ
|
node.typ = v.typ
|
||||||
return v.typ
|
return v.typ
|
||||||
}
|
}
|
||||||
ast.BoolLiteral {
|
ast.BoolLiteral {
|
||||||
return table.bool_type
|
return table.bool_type
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
it.expr_type = c.expr(it.expr)
|
node.expr_type = c.expr(node.expr)
|
||||||
sym := c.table.get_type_symbol(it.expr_type)
|
sym := c.table.get_type_symbol(node.expr_type)
|
||||||
if it.typ == table.string_type && !(sym.kind in [.byte, .byteptr] || (sym.kind ==
|
if node.typ == table.string_type && !(sym.kind in [.byte, .byteptr] || (sym.kind ==
|
||||||
.array && sym.name == 'array_byte')) {
|
.array && sym.name == 'array_byte')) {
|
||||||
type_name := c.table.type_to_str(it.expr_type)
|
type_name := c.table.type_to_str(node.expr_type)
|
||||||
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', it.pos)
|
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos)
|
||||||
}
|
}
|
||||||
if it.expr_type == table.string_type {
|
if node.expr_type == table.string_type {
|
||||||
mut error_msg := 'cannot cast a string'
|
mut error_msg := 'cannot cast a string'
|
||||||
if it.expr is ast.StringLiteral {
|
if node.expr is ast.StringLiteral {
|
||||||
str_lit := it.expr as ast.StringLiteral
|
str_lit := node.expr as ast.StringLiteral
|
||||||
if str_lit.val.len == 1 {
|
if str_lit.val.len == 1 {
|
||||||
error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'"
|
error_msg += ", for denoting characters use `$str_lit.val` instead of '$str_lit.val'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.error(error_msg, it.pos)
|
c.error(error_msg, node.pos)
|
||||||
}
|
}
|
||||||
if it.has_arg {
|
if node.has_arg {
|
||||||
c.expr(it.arg)
|
c.expr(node.arg)
|
||||||
}
|
}
|
||||||
it.typname = c.table.get_type_symbol(it.typ).name
|
node.typname = c.table.get_type_symbol(node.typ).name
|
||||||
return it.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
return c.call_expr(mut it)
|
return c.call_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.CharLiteral {
|
ast.CharLiteral {
|
||||||
return table.byte_type
|
return table.byte_type
|
||||||
}
|
}
|
||||||
ast.ComptimeCall {
|
ast.ComptimeCall {
|
||||||
it.sym = c.table.get_type_symbol(c.unwrap_generic(c.expr(it.left)))
|
node.sym = c.table.get_type_symbol(c.unwrap_generic(c.expr(node.left)))
|
||||||
if it.is_vweb {
|
if node.is_vweb {
|
||||||
x := *c.pref
|
x := *c.pref
|
||||||
xx := {
|
xx := {
|
||||||
x |
|
x |
|
||||||
is_vweb: true
|
is_vweb: true
|
||||||
} // TODO assoc parser bug
|
} // TODO assoc parser bug
|
||||||
mut c2 := new_checker(c.table, xx)
|
mut c2 := new_checker(c.table, xx)
|
||||||
c2.check(it.vweb_tmpl)
|
c2.check(node.vweb_tmpl)
|
||||||
c.warnings << c2.warnings
|
c.warnings << c2.warnings
|
||||||
c.errors << c2.errors
|
c.errors << c2.errors
|
||||||
c.nr_warnings += c2.nr_warnings
|
c.nr_warnings += c2.nr_warnings
|
||||||
|
@ -1904,59 +1904,59 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
ast.ConcatExpr {
|
ast.ConcatExpr {
|
||||||
return c.concat_expr(mut it)
|
return c.concat_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.EnumVal {
|
ast.EnumVal {
|
||||||
return c.enum_val(mut it)
|
return c.enum_val(mut node)
|
||||||
}
|
}
|
||||||
ast.FloatLiteral {
|
ast.FloatLiteral {
|
||||||
return table.any_flt_type
|
return table.any_flt_type
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
// c.checked_ident = it.name
|
// c.checked_ident = it.name
|
||||||
res := c.ident(mut it)
|
res := c.ident(mut node)
|
||||||
// c.checked_ident = ''
|
// c.checked_ident = ''
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
return c.if_expr(mut it)
|
return c.if_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.IfGuardExpr {
|
ast.IfGuardExpr {
|
||||||
it.expr_type = c.expr(it.expr)
|
node.expr_type = c.expr(node.expr)
|
||||||
return table.bool_type
|
return table.bool_type
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
return c.index_expr(mut it)
|
return c.index_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.InfixExpr {
|
ast.InfixExpr {
|
||||||
return c.infix_expr(mut it)
|
return c.infix_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
return table.any_int_type
|
return table.any_int_type
|
||||||
}
|
}
|
||||||
ast.MapInit {
|
ast.MapInit {
|
||||||
return c.map_init(mut it)
|
return c.map_init(mut node)
|
||||||
}
|
}
|
||||||
ast.MatchExpr {
|
ast.MatchExpr {
|
||||||
return c.match_expr(mut it)
|
return c.match_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.PostfixExpr {
|
ast.PostfixExpr {
|
||||||
return c.postfix_expr(it)
|
return c.postfix_expr(node)
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
right_type := c.expr(it.right)
|
right_type := c.expr(node.right)
|
||||||
// TODO: testing ref/deref strategy
|
// TODO: testing ref/deref strategy
|
||||||
if it.op == .amp && !right_type.is_ptr() {
|
if node.op == .amp && !right_type.is_ptr() {
|
||||||
return right_type.to_ptr()
|
return right_type.to_ptr()
|
||||||
}
|
}
|
||||||
if it.op == .mul && right_type.is_ptr() {
|
if node.op == .mul && right_type.is_ptr() {
|
||||||
return right_type.deref()
|
return right_type.deref()
|
||||||
}
|
}
|
||||||
if it.op == .bit_not && !right_type.is_int() {
|
if node.op == .bit_not && !right_type.is_int() {
|
||||||
c.error('operator ~ only defined on int types', it.pos)
|
c.error('operator ~ only defined on int types', node.pos)
|
||||||
}
|
}
|
||||||
if it.op == .not && right_type != table.bool_type_idx {
|
if node.op == .not && right_type != table.bool_type_idx {
|
||||||
c.error('! operator can only be used with bool types', it.pos)
|
c.error('! operator can only be used with bool types', node.pos)
|
||||||
}
|
}
|
||||||
return right_type
|
return right_type
|
||||||
}
|
}
|
||||||
|
@ -1968,47 +1968,47 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
ast.ParExpr {
|
ast.ParExpr {
|
||||||
return c.expr(it.expr)
|
return c.expr(node.expr)
|
||||||
}
|
}
|
||||||
ast.RangeExpr {
|
ast.RangeExpr {
|
||||||
// never happens
|
// never happens
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
return c.selector_expr(mut it)
|
return c.selector_expr(mut node)
|
||||||
}
|
}
|
||||||
ast.SizeOf {
|
ast.SizeOf {
|
||||||
return table.u32_type
|
return table.u32_type
|
||||||
}
|
}
|
||||||
ast.SqlExpr {
|
ast.SqlExpr {
|
||||||
return c.sql_expr(it)
|
return c.sql_expr(node)
|
||||||
}
|
}
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
if it.language == .c {
|
if node.language == .c {
|
||||||
return table.byteptr_type
|
return table.byteptr_type
|
||||||
}
|
}
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
ast.StringInterLiteral {
|
ast.StringInterLiteral {
|
||||||
return c.string_inter_lit(mut it)
|
return c.string_inter_lit(mut node)
|
||||||
}
|
}
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
return c.struct_init(mut it)
|
return c.struct_init(mut node)
|
||||||
}
|
}
|
||||||
ast.Type {
|
ast.Type {
|
||||||
return it.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
ast.TypeOf {
|
ast.TypeOf {
|
||||||
it.expr_type = c.expr(it.expr)
|
node.expr_type = c.expr(node.expr)
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
ast.Likely {
|
ast.Likely {
|
||||||
ltype := c.expr(it.expr)
|
ltype := c.expr(node.expr)
|
||||||
if !c.check_types(ltype, table.bool_type) {
|
if !c.check_types(ltype, table.bool_type) {
|
||||||
ltype_sym := c.table.get_type_symbol(ltype)
|
ltype_sym := c.table.get_type_symbol(ltype)
|
||||||
lname := if it.is_likely { '_likely_' } else { '_unlikely_' }
|
lname := if node.is_likely { '_likely_' } else { '_unlikely_' }
|
||||||
c.error('`${lname}()` expects a boolean expression, instead it got `${ltype_sym.name}`',
|
c.error('`${lname}()` expects a boolean expression, instead it got `$ltype_sym.name`',
|
||||||
it.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
return table.bool_type
|
return table.bool_type
|
||||||
}
|
}
|
||||||
|
@ -2051,21 +2051,21 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
ast.GlobalDecl {
|
ast.GlobalDecl {
|
||||||
ident.kind = .global
|
ident.kind = .global
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: it.typ
|
typ: obj.typ
|
||||||
}
|
}
|
||||||
return it.typ
|
return obj.typ
|
||||||
}
|
}
|
||||||
ast.Var {
|
ast.Var {
|
||||||
mut typ := it.typ
|
mut typ := obj.typ
|
||||||
if typ == 0 {
|
if typ == 0 {
|
||||||
if it.expr is ast.Ident {
|
if obj.expr is ast.Ident {
|
||||||
inner_ident := it.expr as ast.Ident
|
inner_ident := obj.expr as ast.Ident
|
||||||
if inner_ident.kind == .unresolved {
|
if inner_ident.kind == .unresolved {
|
||||||
c.error('unresolved variable: `$ident.name`', ident.pos)
|
c.error('unresolved variable: `$ident.name`', ident.pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typ = c.expr(it.expr)
|
typ = c.expr(obj.expr)
|
||||||
}
|
}
|
||||||
is_optional := typ.has_flag(.optional)
|
is_optional := typ.has_flag(.optional)
|
||||||
ident.kind = .variable
|
ident.kind = .variable
|
||||||
|
@ -2080,7 +2080,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
// typ = c.cur_generic_type
|
// typ = c.cur_generic_type
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
it.typ = typ
|
obj.typ = typ
|
||||||
// unwrap optional (`println(x)`)
|
// unwrap optional (`println(x)`)
|
||||||
if is_optional {
|
if is_optional {
|
||||||
return typ.clear_flag(.optional)
|
return typ.clear_flag(.optional)
|
||||||
|
@ -2098,16 +2098,16 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
||||||
if obj := c.file.global_scope.find(name) {
|
if obj := c.file.global_scope.find(name) {
|
||||||
match obj {
|
match obj {
|
||||||
ast.ConstField {
|
ast.ConstField {
|
||||||
mut typ := it.typ
|
mut typ := obj.typ
|
||||||
if typ == 0 {
|
if typ == 0 {
|
||||||
typ = c.expr(it.expr)
|
typ = c.expr(obj.expr)
|
||||||
}
|
}
|
||||||
ident.name = name
|
ident.name = name
|
||||||
ident.kind = .constant
|
ident.kind = .constant
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
typ: typ
|
||||||
}
|
}
|
||||||
it.typ = typ
|
obj.typ = typ
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
|
@ -2224,8 +2224,8 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol
|
||||||
for expr in branch.exprs {
|
for expr in branch.exprs {
|
||||||
mut key := ''
|
mut key := ''
|
||||||
match expr {
|
match expr {
|
||||||
ast.Type { key = c.table.type_to_str(it.typ) }
|
ast.Type { key = c.table.type_to_str(expr.typ) }
|
||||||
ast.EnumVal { key = it.val }
|
ast.EnumVal { key = expr.val }
|
||||||
else { key = expr.str() }
|
else { key = expr.str() }
|
||||||
}
|
}
|
||||||
val := if key in branch_exprs { branch_exprs[key] } else { 0 }
|
val := if key in branch_exprs { branch_exprs[key] } else { 0 }
|
||||||
|
|
Loading…
Reference in New Issue