vfmt: small fixes + run on checker.v and fmt.v

pull/4282/head
Alexander Medvednikov 2020-04-07 15:15:45 +02:00
parent 3c6a4dedd6
commit 8f9a8e1e7f
5 changed files with 139 additions and 118 deletions

View File

@ -384,6 +384,7 @@ pub:
cond Expr cond Expr
stmts []Stmt stmts []Stmt
pos token.Position pos token.Position
comment Comment
} }
pub struct MatchExpr { pub struct MatchExpr {
@ -392,6 +393,7 @@ pub:
cond Expr cond Expr
branches []MatchBranch branches []MatchBranch
pos token.Position pos token.Position
is_mut bool // `match mut ast_node {`
mut: mut:
is_expr bool // returns a value is_expr bool // returns a value
return_type table.Type return_type table.Type
@ -405,6 +407,7 @@ pub:
exprs []Expr exprs []Expr
stmts []Stmt stmts []Stmt
pos token.Position pos token.Position
comment Comment // comment above `xxx {`
} }
pub struct CompIf { pub struct CompIf {

View File

@ -38,11 +38,18 @@ pub fn (node &FnDecl) str(t &table.Table) string {
should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ || (node.is_variadic && i == should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ || (node.is_variadic && i ==
node.args.len - 2) node.args.len - 2)
f.write(arg.name) f.write(arg.name)
mut s := t.type_to_str(arg.typ)
if arg.is_mut {
f.write(' mut')
if s.starts_with('&') {
s = s[1..]
}
}
if should_add_type { if should_add_type {
if node.is_variadic && is_last_arg { if node.is_variadic && is_last_arg {
f.write(' ...' + t.type_to_str(arg.typ)) f.write(' ...' + s)
} else { } else {
f.write(' ' + t.type_to_str(arg.typ)) f.write(' ' + s)
} }
} }
if !is_last_arg { if !is_last_arg {

View File

@ -28,14 +28,12 @@ mut:
fn_return_type table.Type // current function's return type fn_return_type table.Type // current function's return type
const_decl string const_decl string
const_deps []string const_deps []string
//assigned_var_name string
// fn_decl ast.FnDecl
pref &pref.Preferences // Preferences shared from V struct pref &pref.Preferences // Preferences shared from V struct
in_for_count int // if checker is currently in an for loop in_for_count int // if checker is currently in an for loop
} }
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker { pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
return Checker{ return checker.Checker{
table: table table: table
pref: pref pref: pref
} }
@ -119,7 +117,8 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
} }
} }
if !found_field { if !found_field {
c.error('struct init: no such field `$field_name` for struct `$typ_sym.name`', struct_init.pos) c.error('struct init: no such field `$field_name` for struct `$typ_sym.name`',
struct_init.pos)
continue continue
} }
} }
@ -128,7 +127,8 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
expr_type_sym := c.table.get_type_symbol(expr_type) expr_type_sym := c.table.get_type_symbol(expr_type)
field_type_sym := c.table.get_type_symbol(field.typ) field_type_sym := c.table.get_type_symbol(field.typ)
if !c.table.check(expr_type, field.typ) { if !c.table.check(expr_type, field.typ) {
c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$field.name`', struct_init.pos) c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$field.name`',
struct_init.pos)
} }
struct_init.expr_types << expr_type struct_init.expr_types << expr_type
struct_init.expected_types << field.typ struct_init.expected_types << field.typ
@ -160,7 +160,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
left := c.table.get_type_symbol(left_type) left := c.table.get_type_symbol(left_type)
if infix_expr.op == .left_shift { if infix_expr.op == .left_shift {
if left.kind != .array && !left.is_int() { if left.kind != .array && !left.is_int() {
//c.error('<< can only be used with numbers and arrays', infix_expr.pos) // c.error('<< can only be used with numbers and arrays', infix_expr.pos)
c.error('incompatible types: $left.name << $right.name', infix_expr.pos) c.error('incompatible types: $left.name << $right.name', infix_expr.pos)
return table.void_type return table.void_type
} }
@ -224,7 +224,8 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
left_type_sym := c.table.get_type_symbol(left_type) left_type_sym := c.table.get_type_symbol(left_type)
method_name := call_expr.name method_name := call_expr.name
// TODO: remove this for actual methods, use only for compiler magic // TODO: remove this for actual methods, use only for compiler magic
if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse', 'map', 'slice'] { if left_type_sym.kind == .array && method_name in ['filter', 'clone', 'repeat', 'reverse', 'map',
'slice'] {
if method_name in ['filter', 'map'] { if method_name in ['filter', 'map'] {
array_info := left_type_sym.info as table.Array array_info := left_type_sym.info as table.Array
mut scope := c.file.scope.innermost(call_expr.pos.pos) mut scope := c.file.scope.innermost(call_expr.pos.pos)
@ -239,13 +240,11 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
// in ['clone', 'str'] { // in ['clone', 'str'] {
call_expr.receiver_type = table.type_to_ptr(left_type) call_expr.receiver_type = table.type_to_ptr(left_type)
// call_expr.return_type = call_expr.receiver_type // call_expr.return_type = call_expr.receiver_type
} } else {
else {
call_expr.receiver_type = left_type call_expr.receiver_type = left_type
} }
return left_type return left_type
} } else if left_type_sym.kind == .array && method_name in ['first', 'last'] {
else if left_type_sym.kind == .array && method_name in ['first', 'last'] {
info := left_type_sym.info as table.Array info := left_type_sym.info as table.Array
call_expr.return_type = info.elem_type call_expr.return_type = info.elem_type
call_expr.receiver_type = left_type call_expr.receiver_type = left_type
@ -255,10 +254,11 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
no_args := method.args.len - 1 no_args := method.args.len - 1
min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 } min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 }
if call_expr.args.len < min_required_args { if call_expr.args.len < min_required_args {
c.error('too few arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $min_required_args)', call_expr.pos) c.error('too few arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $min_required_args)',
} call_expr.pos)
else if !method.is_variadic && call_expr.args.len > no_args { } else if !method.is_variadic && call_expr.args.len > no_args {
c.error('too many arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $no_args)', call_expr.pos) c.error('too many arguments in call to `${left_type_sym.name}.$method_name` ($call_expr.args.len instead of $no_args)',
call_expr.pos)
return method.return_type return method.return_type
} }
// if method_name == 'clone' { // if method_name == 'clone' {
@ -267,7 +267,11 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
// call_expr.args << method.args[0].typ // call_expr.args << method.args[0].typ
// call_expr.exp_arg_types << method.args[0].typ // call_expr.exp_arg_types << method.args[0].typ
for i, arg in call_expr.args { for i, arg in call_expr.args {
c.expected_type = if method.is_variadic && i >= method.args.len - 1 { method.args[method.args.len - 1].typ } else { method.args[i + 1].typ } c.expected_type = if method.is_variadic && i >= method.args.len - 1 {
method.args[method.args.len - 1].typ
} else {
method.args[i + 1].typ
}
call_expr.args[i].typ = c.expr(arg.expr) call_expr.args[i].typ = c.expr(arg.expr)
} }
// TODO: typ optimize.. this node can get processed more than once // TODO: typ optimize.. this node can get processed more than once
@ -293,8 +297,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
} }
c.error('unknown method: ${left_type_sym.name}.$method_name', call_expr.pos) c.error('unknown method: ${left_type_sym.name}.$method_name', call_expr.pos)
return table.void_type return table.void_type
} } else {
else {
fn_name := call_expr.name fn_name := call_expr.name
// TODO: impl typeof properly (probably not going to be a fn call) // TODO: impl typeof properly (probably not going to be a fn call)
if fn_name == 'typeof' { if fn_name == 'typeof' {
@ -346,10 +349,11 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
} }
min_required_args := if f.is_variadic { f.args.len - 1 } else { f.args.len } min_required_args := if f.is_variadic { f.args.len - 1 } else { f.args.len }
if call_expr.args.len < min_required_args { if call_expr.args.len < min_required_args {
c.error('too few arguments in call to `$fn_name` ($call_expr.args.len instead of $min_required_args)', call_expr.pos) c.error('too few arguments in call to `$fn_name` ($call_expr.args.len instead of $min_required_args)',
} call_expr.pos)
else if !f.is_variadic && call_expr.args.len > f.args.len { } else if !f.is_variadic && call_expr.args.len > f.args.len {
c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos) c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)',
call_expr.pos)
return f.return_type return f.return_type
} }
// println can print anything // println can print anything
@ -379,9 +383,11 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
if typ_sym.kind == .void && arg_typ_sym.kind == .string { if typ_sym.kind == .void && arg_typ_sym.kind == .string {
continue continue
} }
if typ_sym.kind == .array_fixed {} if typ_sym.kind == .array_fixed {
}
// println('fixed') // println('fixed')
c.error('cannot use type `$typ_sym.str()` as type `$arg_typ_sym.str()` in argument ${i+1} to `$fn_name`', call_expr.pos) c.error('cannot use type `$typ_sym.str()` as type `$arg_typ_sym.str()` in argument ${i+1} to `$fn_name`',
call_expr.pos)
} }
} }
return f.return_type return f.return_type
@ -409,8 +415,7 @@ pub fn (c mut Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.T
} }
if typ_sym.kind != .struct_ { if typ_sym.kind != .struct_ {
c.error('`$typ_sym.name` is not a struct', selector_expr.pos) c.error('`$typ_sym.name` is not a struct', selector_expr.pos)
} } else {
else {
c.error('unknown field `${typ_sym.name}.$field_name`', selector_expr.pos) c.error('unknown field `${typ_sym.name}.$field_name`', selector_expr.pos)
} }
return table.void_type return table.void_type
@ -453,13 +458,14 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) {
if !c.table.check(got_typ, exp_typ) { if !c.table.check(got_typ, exp_typ) {
got_typ_sym := c.table.get_type_symbol(got_typ) got_typ_sym := c.table.get_type_symbol(got_typ)
exp_typ_sym := c.table.get_type_symbol(exp_typ) exp_typ_sym := c.table.get_type_symbol(exp_typ)
c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument', return_stmt.pos) c.error('cannot use `$got_typ_sym.name` as type `$exp_typ_sym.name` in return argument',
return_stmt.pos)
} }
} }
} }
pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) { pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
c.expected_type = table.none_type // TODO a hack to make `x := if ... work` c.expected_type = table.none_type // TODO a hack to make `x := if ... work`
// multi return // multi return
if assign_stmt.left.len > assign_stmt.right.len { if assign_stmt.left.len > assign_stmt.right.len {
match assign_stmt.right[0] { match assign_stmt.right[0] {
@ -467,7 +473,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
else { else {
c.error('assign_stmt: expected call', assign_stmt.pos) c.error('assign_stmt: expected call', assign_stmt.pos)
} }
} }
right_type := c.expr(assign_stmt.right[0]) right_type := c.expr(assign_stmt.right[0])
right_type_sym := c.table.get_type_symbol(right_type) right_type_sym := c.table.get_type_symbol(right_type)
mr_info := right_type_sym.mr_info() mr_info := right_type_sym.mr_info()
@ -494,9 +500,8 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
assign_stmt.right_types << val_type assign_stmt.right_types << val_type
scope.update_var_type(ident.name, val_type) scope.update_var_type(ident.name, val_type)
} }
} } else {
// `a := 1` | `a,b := 1,2` // `a := 1` | `a,b := 1,2`
else {
if assign_stmt.left.len != assign_stmt.right.len { if assign_stmt.left.len != assign_stmt.right.len {
c.error('wrong number of vars', assign_stmt.pos) c.error('wrong number of vars', assign_stmt.pos)
} }
@ -504,7 +509,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
for i, _ in assign_stmt.left { for i, _ in assign_stmt.left {
mut ident := assign_stmt.left[i] mut ident := assign_stmt.left[i]
mut ident_var_info := ident.var_info() mut ident_var_info := ident.var_info()
//c.assigned_var_name = ident.name // c.assigned_var_name = ident.name
val_type := c.expr(assign_stmt.right[i]) val_type := c.expr(assign_stmt.right[i])
if assign_stmt.op == .assign { if assign_stmt.op == .assign {
var_type := c.expr(ident) var_type := c.expr(ident)
@ -523,7 +528,7 @@ pub fn (c mut Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
} }
} }
c.expected_type = table.void_type c.expected_type = table.void_type
//c.assigned_var_name = '' // c.assigned_var_name = ''
} }
pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
@ -542,8 +547,8 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
} }
// TODO: seperate errors once bug is fixed with `x := if expr { ... } else { ... }` // TODO: seperate errors once bug is fixed with `x := if expr { ... } else { ... }`
// if c.expected_type == table.void_type { // if c.expected_type == table.void_type {
// c.error('array_init: use `[]Type` instead of `[]`', array_init.pos) // c.error('array_init: use `[]Type` instead of `[]`', array_init.pos)
// return table.void_type // return table.void_type
// } // }
array_info := type_sym.array_info() array_info := type_sym.array_info()
array_init.elem_type = array_info.elem_type array_init.elem_type = array_info.elem_type
@ -567,9 +572,8 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
idx := c.table.find_or_register_array(elem_type, 1) idx := c.table.find_or_register_array(elem_type, 1)
array_init.typ = table.new_type(idx) array_init.typ = table.new_type(idx)
array_init.elem_type = elem_type array_init.elem_type = elem_type
} } else if array_init.exprs.len == 1 && array_init.elem_type != table.void_type {
// [50]byte // [50]byte
else if array_init.exprs.len == 1 && array_init.elem_type != table.void_type {
mut fixed_size := 1 mut fixed_size := 1
match array_init.exprs[0] { match array_init.exprs[0] {
ast.IntegerLiteral { ast.IntegerLiteral {
@ -578,7 +582,7 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
else { else {
c.error('expecting `int` for fixed size', array_init.pos) c.error('expecting `int` for fixed size', array_init.pos)
} }
} }
idx := c.table.find_or_register_array_fixed(array_init.elem_type, fixed_size, 1) idx := c.table.find_or_register_array_fixed(array_init.elem_type, fixed_size, 1)
array_type := table.new_type(idx) array_type := table.new_type(idx)
array_init.typ = array_type array_init.typ = array_type
@ -655,12 +659,12 @@ fn (c mut Checker) stmt(node ast.Stmt) {
c.expected_type = table.void_type c.expected_type = table.void_type
} }
ast.FnDecl { ast.FnDecl {
//if it.is_method { // if it.is_method {
//sym := c.table.get_type_symbol(it.receiver.typ) // sym := c.table.get_type_symbol(it.receiver.typ)
//if sym.has_method(it.name) { // if sym.has_method(it.name) {
//c.warn('duplicate method `$it.name`', it.pos) // c.warn('duplicate method `$it.name`', it.pos)
//} // }
//} // }
c.expected_type = table.void_type c.expected_type = table.void_type
c.fn_return_type = it.return_type c.fn_return_type = it.return_type
c.stmts(it.stmts) c.stmts(it.stmts)
@ -690,17 +694,17 @@ fn (c mut Checker) stmt(node ast.Stmt) {
typ := c.expr(it.cond) typ := c.expr(it.cond)
if it.is_range { if it.is_range {
c.expr(it.high) c.expr(it.high)
} } else {
else {
mut scope := c.file.scope.innermost(it.pos.pos) mut scope := c.file.scope.innermost(it.pos.pos)
sym := c.table.get_type_symbol(typ) sym := c.table.get_type_symbol(typ)
if it.key_var.len > 0 { if it.key_var.len > 0 {
key_type := match sym.kind { key_type := match sym.kind {
.map{ .map {
sym.map_info().key_type sym.map_info().key_type
} }
else { else {
table.int_type} table.int_type
}
} }
it.key_type = key_type it.key_type = key_type
scope.update_var_type(it.key_var, key_type) scope.update_var_type(it.key_var, key_type)
@ -718,12 +722,12 @@ fn (c mut Checker) stmt(node ast.Stmt) {
c.stmts(it.stmts) c.stmts(it.stmts)
c.in_for_count-- c.in_for_count--
} }
ast.GoStmt{ ast.GoStmt {
c.expr(it.call_expr) c.expr(it.call_expr)
} }
// ast.GlobalDecl {}
// ast.HashStmt {} // ast.HashStmt {}
ast.Import {} ast.Import {}
// ast.GlobalDecl {}
ast.Return { ast.Return {
c.return_stmt(mut it) c.return_stmt(mut it)
} }
@ -731,10 +735,10 @@ fn (c mut Checker) stmt(node ast.Stmt) {
ast.UnsafeStmt { ast.UnsafeStmt {
c.stmts(it.stmts) c.stmts(it.stmts)
} }
else {} else {
// println('checker.stmt(): unhandled node') // println('checker.stmt(): unhandled node')
// println('checker.stmt(): unhandled node (${typeof(node)})') // println('checker.stmt(): unhandled node (${typeof(node)})')
// } }
} }
} }
@ -761,8 +765,7 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
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`', it.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`', it.pos)
} }
return it.typ return it.typ
@ -909,17 +912,14 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
if ident.kind == .variable { if ident.kind == .variable {
info := ident.info as ast.IdentVar info := ident.info as ast.IdentVar
return info.typ return info.typ
} } else if ident.kind == .constant {
else if ident.kind == .constant {
info := ident.info as ast.IdentVar info := ident.info as ast.IdentVar
return info.typ return info.typ
} } else if ident.kind == .function {
else if ident.kind == .function {
info := ident.info as ast.IdentFn info := ident.info as ast.IdentFn
return info.typ return info.typ
} } else if ident.kind == .unresolved {
// first use // first use
else if ident.kind == .unresolved {
start_scope := c.file.scope.innermost(ident.pos.pos) start_scope := c.file.scope.innermost(ident.pos.pos)
if obj := start_scope.find(ident.name) { if obj := start_scope.find(ident.name) {
match obj { match obj {
@ -1009,7 +1009,8 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
typ := c.expr(expr) typ := c.expr(expr)
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
// TODO: // TODO:
if typ_sym.kind == .sum_type {} if typ_sym.kind == .sum_type {
}
} }
c.stmts(branch.stmts) c.stmts(branch.stmts)
// If the last statement is an expression, return its type // If the last statement is an expression, return its type
@ -1018,14 +1019,15 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
ast.ExprStmt { ast.ExprStmt {
ret_type = c.expr(it.expr) ret_type = c.expr(it.expr)
} }
// TODO: ask alex about this else {
// typ := c.expr(it.expr) // TODO: ask alex about this
// type_sym := c.table.get_type_symbol(typ) // typ := c.expr(it.expr)
// p.warn('match expr ret $type_sym.name') // type_sym := c.table.get_type_symbol(typ)
// node.typ = typ // p.warn('match expr ret $type_sym.name')
// return typ // node.typ = typ
else {} // return typ
} }
}
} }
} }
// if ret_type != table.void_type { // if ret_type != table.void_type {
@ -1039,19 +1041,21 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
} }
pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type { pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
if c.expected_type != table.void_type { // || c.assigned_var_name != '' { if c.expected_type != table.void_type {
//sym := c.table.get_type_symbol(c.expected_type) // | c.assigned_var_name != '' {
//println('$c.file.path $node.pos.line_nr IF is expr: checker exp type = ' + sym.name) // sym := c.table.get_type_symbol(c.expected_type)
// println('$c.file.path $node.pos.line_nr IF is expr: checker exp type = ' + sym.name)
node.is_expr = true node.is_expr = true
} }
node.typ = table.void_type node.typ = table.void_type
for i, branch in node.branches { for i, branch in node.branches {
match branch.cond { match branch.cond {
ast.ParExpr { ast.ParExpr {
c.error('unnecessary `()` in an if condition. use `if expr {` instead of `if (expr) {`.', node.pos) c.error('unnecessary `()` in an if condition. use `if expr {` instead of `if (expr) {`.',
node.pos)
} }
else {} else {}
} }
typ := c.expr(branch.cond) typ := c.expr(branch.cond)
if i < node.branches.len - 1 || !node.has_else { if i < node.branches.len - 1 || !node.has_else {
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
@ -1074,7 +1078,7 @@ pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
return t return t
} }
else {} else {}
} }
} }
} }
return table.bool_type return table.bool_type
@ -1088,7 +1092,7 @@ pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
} }
else {} else {}
} }
*/ */
typ := c.expr(node.expr) typ := c.expr(node.expr)
typ_sym := c.table.get_type_symbol(typ) typ_sym := c.table.get_type_symbol(typ)
// if !table.is_number(typ) { // if !table.is_number(typ) {
@ -1102,7 +1106,7 @@ pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type { pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
typ := c.expr(node.left) typ := c.expr(node.left)
node.left_type = typ node.left_type = typ
mut is_range := false // TODO is_range := node.index is ast.RangeExpr mut is_range := false // TODO is_range := node.index is ast.RangeExpr
match node.index { match node.index {
ast.RangeExpr { ast.RangeExpr {
is_range = true is_range = true
@ -1122,18 +1126,17 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
// println('index expr left=$typ_sym.name $node.pos.line_nr') // println('index expr left=$typ_sym.name $node.pos.line_nr')
// if typ_sym.kind == .array && (!(table.type_idx(index_type) in table.number_type_idxs) && // if typ_sym.kind == .array && (!(table.type_idx(index_type) in table.number_type_idxs) &&
// index_type_sym.kind != .enum_) { // index_type_sym.kind != .enum_) {
if typ_sym.kind in [.array, .array_fixed] && !(table.is_number(index_type) || index_type_sym.kind == .enum_) { if typ_sym.kind in [.array, .array_fixed] && !(table.is_number(index_type) || index_type_sym.kind ==
.enum_) {
c.error('non-integer index `$index_type_sym.name` (array type `$typ_sym.name`)', node.pos) c.error('non-integer index `$index_type_sym.name` (array type `$typ_sym.name`)', node.pos)
} } else if typ_sym.kind == .map && table.type_idx(index_type) != table.string_type_idx {
else if typ_sym.kind == .map && table.type_idx(index_type) != table.string_type_idx {
c.error('non-string map index (map type `$typ_sym.name`)', node.pos) c.error('non-string map index (map type `$typ_sym.name`)', node.pos)
} }
value_type := c.table.value_type(typ) value_type := c.table.value_type(typ)
if value_type != table.void_type { if value_type != table.void_type {
return value_type return value_type
} }
} } else if is_range {
else if is_range {
// array[1..2] => array // array[1..2] => array
// fixed_array[1..2] => array // fixed_array[1..2] => array
if typ_sym.kind == .array_fixed { if typ_sym.kind == .array_fixed {
@ -1149,8 +1152,11 @@ pub fn (c mut Checker) index_expr(node mut ast.IndexExpr) table.Type {
// If a short form is used, `expected_type` needs to be an enum // If a short form is used, `expected_type` needs to be an enum
// with this value. // with this value.
pub fn (c mut Checker) enum_val(node mut ast.EnumVal) table.Type { pub fn (c mut Checker) enum_val(node mut ast.EnumVal) table.Type {
typ_idx := if node.enum_name == '' { table.type_idx(c.expected_type) } else { // typ_idx := if node.enum_name == '' {
c.table.find_type_idx(node.enum_name) } table.type_idx(c.expected_type)
} else { //
c.table.find_type_idx(node.enum_name)
}
// println('checker: enum_val: $node.enum_name typeidx=$typ_idx') // println('checker: enum_val: $node.enum_name typeidx=$typ_idx')
if typ_idx == 0 { if typ_idx == 0 {
c.error('not an enum (name=$node.enum_name) (type_idx=0)', node.pos) c.error('not an enum (name=$node.enum_name) (type_idx=0)', node.pos)
@ -1209,8 +1215,8 @@ pub fn (c mut Checker) map_init(node mut ast.MapInit) table.Type {
} }
pub fn (c mut Checker) warn(s string, pos token.Position) { pub fn (c mut Checker) warn(s string, pos token.Position) {
allow_warnings := !c.pref.is_prod // allow warnings only in dev builds allow_warnings := !c.pref.is_prod // allow warnings only in dev builds
c.warn_or_error(s, pos, allow_warnings) // allow warnings only in dev builds c.warn_or_error(s, pos, allow_warnings) // allow warnings only in dev builds
} }
pub fn (c mut Checker) error(s string, pos token.Position) { pub fn (c mut Checker) error(s string, pos token.Position) {
@ -1221,16 +1227,12 @@ fn (c mut Checker) warn_or_error(s string, pos token.Position, warn bool) {
if !warn { if !warn {
c.nr_errors++ c.nr_errors++
} }
//if c.pref.is_verbose { // if c.pref.is_verbose {
if c.pref.is_verbose { if c.pref.is_verbose {
print_backtrace() print_backtrace()
} }
typ := if warn { 'warning' } else { 'error' } typ := if warn { 'warning' } else { 'error' }
kind := if c.pref.is_verbose { kind := if c.pref.is_verbose { 'checker $typ #$c.nr_errors:' } else { '$typ:' }
'checker $typ #$c.nr_errors:'
} else {
'$typ:'
}
ferror := util.formated_error(kind, s, c.file.path, pos) ferror := util.formated_error(kind, s, c.file.path, pos)
c.errors << ferror c.errors << ferror
if !(pos.line_nr in c.error_lines) { if !(pos.line_nr in c.error_lines) {

View File

@ -10,8 +10,7 @@ import (
) )
const ( const (
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t']
'\t\t\t\t\t\t\t']
max_len = 100 max_len = 100
) )
@ -25,8 +24,8 @@ mut:
single_line_if bool single_line_if bool
cur_mod string cur_mod string
file ast.File file ast.File
did_imports bool did_imports bool
is_assign bool is_assign bool
} }
pub fn fmt(file ast.File, table &table.Table) string { pub fn fmt(file ast.File, table &table.Table) string {
@ -87,9 +86,7 @@ fn (f mut Fmt) imports(imports []ast.Import) {
if imports.len == 1 { if imports.len == 1 {
imp_stmt_str := f.imp_stmt_str(imports[0]) imp_stmt_str := f.imp_stmt_str(imports[0])
f.writeln('import ${imp_stmt_str}\n') f.writeln('import ${imp_stmt_str}\n')
} } else if imports.len > 1 {
//
else if imports.len > 1 {
f.writeln('import (') f.writeln('import (')
f.indent++ f.indent++
for imp in imports { for imp in imports {
@ -102,11 +99,7 @@ fn (f mut Fmt) imports(imports []ast.Import) {
fn (f Fmt) imp_stmt_str(imp ast.Import) string { fn (f Fmt) imp_stmt_str(imp ast.Import) string {
is_diff := imp.alias != imp.mod && !imp.mod.ends_with('.' + imp.alias) is_diff := imp.alias != imp.mod && !imp.mod.ends_with('.' + imp.alias)
imp_alias_suffix := if is_diff { imp_alias_suffix := if is_diff { ' as ${imp.alias}' } else { '' }
' as ${imp.alias}'
} else {
''
}
return '${imp.mod}${imp_alias_suffix}' return '${imp.mod}${imp_alias_suffix}'
} }
@ -291,11 +284,7 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
f.writeln('') f.writeln('')
} }
ast.CompIf { ast.CompIf {
inversion := if it.is_not { inversion := if it.is_not { '!' } else { '' }
'!'
} else {
''
}
f.writeln('\$if ${inversion}${it.val} {') f.writeln('\$if ${inversion}${it.val} {')
f.stmts(it.stmts) f.stmts(it.stmts)
if it.has_else { if it.has_else {
@ -504,10 +493,16 @@ fn (f mut Fmt) expr(node ast.Expr) {
} }
ast.MatchExpr { ast.MatchExpr {
f.write('match ') f.write('match ')
if it.is_mut {
f.write('mut ')
}
f.expr(it.cond) f.expr(it.cond)
f.writeln(' {') f.writeln(' {')
f.indent++ f.indent++
for i, branch in it.branches { for i, branch in it.branches {
if branch.comment.text != '' {
f.comment(branch.comment)
}
if i < it.branches.len - 1 { if i < it.branches.len - 1 {
// normal branch // normal branch
for j, expr in branch.exprs { for j, expr in branch.exprs {
@ -683,10 +678,13 @@ fn short_module(name string) string {
} }
fn (f mut Fmt) if_expr(it ast.IfExpr) { fn (f mut Fmt) if_expr(it ast.IfExpr) {
single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == single_line := it.branches.len == 2 && it.has_else && it.branches[0].stmts.len == 1 && it.branches[1].stmts.len ==
1 && it.branches[1].stmts.len == 1 && (it.is_expr || f.is_assign) 1 && (it.is_expr || f.is_assign)
f.single_line_if = single_line f.single_line_if = single_line
for i, branch in it.branches { for i, branch in it.branches {
if branch.comment.text != '' {
f.comment(branch.comment)
}
if i == 0 { if i == 0 {
f.write('if ') f.write('if ')
f.expr(branch.cond) f.expr(branch.cond)

View File

@ -337,6 +337,7 @@ pub fn (p mut Parser) check_comment() ast.Comment {
if p.tok.kind == .comment { if p.tok.kind == .comment {
return p.comment() return p.comment()
} }
return ast.Comment{}
} }
pub fn (p mut Parser) comment() ast.Comment { pub fn (p mut Parser) comment() ast.Comment {
@ -1182,10 +1183,15 @@ fn (p mut Parser) if_expr() ast.IfExpr {
mut has_else := false mut has_else := false
for p.tok.kind in [.key_if, .key_else] { for p.tok.kind in [.key_if, .key_else] {
branch_pos := p.tok.position() branch_pos := p.tok.position()
mut comment := ast.Comment{}
if p.tok.kind == .key_if { if p.tok.kind == .key_if {
p.check(.key_if) p.check(.key_if)
} }
else { else {
//if p.tok.kind == .comment {
//p.error('place comments inside {}')
//}
//comment = p.check_comment()
p.check(.key_else) p.check(.key_else)
if p.tok.kind == .key_if { if p.tok.kind == .key_if {
p.check(.key_if) p.check(.key_if)
@ -1195,6 +1201,7 @@ fn (p mut Parser) if_expr() ast.IfExpr {
branches << ast.IfBranch{ branches << ast.IfBranch{
stmts: p.parse_block() stmts: p.parse_block()
pos: branch_pos pos: branch_pos
comment: comment
} }
break break
} }
@ -1229,6 +1236,7 @@ fn (p mut Parser) if_expr() ast.IfExpr {
cond: cond cond: cond
stmts: stmts stmts: stmts
pos: branch_pos pos: branch_pos
comment: ast.Comment{}// comment
} }
if p.tok.kind != .key_else { if p.tok.kind != .key_else {
break break
@ -1811,6 +1819,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
mut branches := []ast.MatchBranch mut branches := []ast.MatchBranch
mut have_final_else := false mut have_final_else := false
for { for {
comment := p.check_comment() // comment before {}
mut exprs := []ast.Expr mut exprs := []ast.Expr
branch_pos := p.tok.position() branch_pos := p.tok.position()
p.open_scope() p.open_scope()
@ -1862,6 +1871,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
exprs: exprs exprs: exprs
stmts: stmts stmts: stmts
pos: branch_pos pos: branch_pos
comment: comment
} }
p.close_scope() p.close_scope()
if p.tok.kind == .rcbr { if p.tok.kind == .rcbr {
@ -1877,6 +1887,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
cond: cond cond: cond
is_sum_type: is_sum_type is_sum_type: is_sum_type
pos: pos pos: pos
is_mut: is_mut
} }
} }