checker: print multiple errors; none

pull/3785/head
Alexander Medvednikov 2020-02-19 19:54:36 +01:00
parent d91945cc99
commit ec3d67c19f
11 changed files with 112 additions and 88 deletions

View File

@ -148,7 +148,9 @@ fn (m map) get(key string, out voidptr) bool {
mut node := m.root mut node := m.root
for { for {
mut i := node.size - 1 mut i := node.size - 1
for i >= 0 && key < node.keys[i] { i-- } for i >= 0 && key < node.keys[i] {
i--
}
if i != -1 && key == node.keys[i] { if i != -1 && key == node.keys[i] {
C.memcpy(out, node.values[i], m.value_bytes) C.memcpy(out, node.values[i], m.value_bytes)
return true return true

View File

@ -11,7 +11,7 @@ import (
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr |
CastExpr | EnumVal | Assoc | SizeOf CastExpr | EnumVal | Assoc | SizeOf | None
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
@ -473,6 +473,10 @@ pub:
text string text string
} }
pub struct None {
pub:
foo int // todo
}
// string representaiton of expr // string representaiton of expr
pub fn (x Expr) str() string { pub fn (x Expr) str() string {
match x { match x {

View File

@ -11,11 +11,16 @@ import (
filepath filepath
) )
const (
max_nr_errors = 10
)
pub struct Checker { pub struct Checker {
table &table.Table table &table.Table
mut: mut:
file_name string file_name string
scope &ast.Scope scope &ast.Scope
nr_errors int
} }
pub fn new_checker(table &table.Table) Checker { pub fn new_checker(table &table.Table) Checker {
@ -86,11 +91,16 @@ pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
left_type := c.expr(infix_expr.left) left_type := c.expr(infix_expr.left)
right_type := c.expr(infix_expr.right) right_type := c.expr(infix_expr.right)
if !c.table.check(right_type, left_type) { if !c.table.check(right_type, left_type) {
left_type_sym := c.table.get_type_symbol(left_type) left := c.table.get_type_symbol(left_type)
right_type_sym := c.table.get_type_symbol(right_type) right := c.table.get_type_symbol(right_type)
// array << elm
// the expressions have different types (array_x and x)
if left.kind == .array && infix_expr.op == .left_shift {
return table.void_type
}
// if !c.table.check(&infix_expr.right_type, &infix_expr.right_type) { // if !c.table.check(&infix_expr.right_type, &infix_expr.right_type) {
// c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos) // c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos)
c.error('infix expr: cannot use `$right_type_sym.name` as `$left_type_sym.name`', infix_expr.pos) c.error('infix expr: cannot use `$right.name` (right) as `$left.name`', infix_expr.pos)
} }
if infix_expr.op.is_relational() { if infix_expr.op.is_relational() {
return table.bool_type return table.bool_type
@ -367,6 +377,9 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
ast.CastExpr { ast.CastExpr {
return it.typ return it.typ
} }
ast.None {
return table.none_type
}
else {} else {}
} }
return table.void_type return table.void_type
@ -570,14 +583,15 @@ pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type {
else if typ_sym.kind in [.byteptr, .string] { else if typ_sym.kind in [.byteptr, .string] {
return table.byte_type return table.byte_type
} }
//else { // else {
// return table.int_type // return table.int_type
//} // }
} }
return typ return typ
} }
pub fn (c &Checker) error(s string, pos token.Position) { pub fn (c mut Checker) error(s string, pos token.Position) {
c.nr_errors++
print_backtrace() print_backtrace()
mut path := c.file_name mut path := c.file_name
// Get relative path // Get relative path
@ -585,7 +599,7 @@ pub fn (c &Checker) error(s string, pos token.Position) {
if path.starts_with(workdir) { if path.starts_with(workdir) {
path = path.replace(workdir, '') path = path.replace(workdir, '')
} }
final_msg_line := '$path:$pos.line_nr: checker error: $s' final_msg_line := '$path:$pos.line_nr: checker error #$c.nr_errors: $s'
eprintln(final_msg_line) eprintln(final_msg_line)
/* /*
if colored_output { if colored_output {
@ -595,5 +609,8 @@ pub fn (c &Checker) error(s string, pos token.Position) {
} }
*/ */
exit(1) println('\n\n')
if c.nr_errors >= max_nr_errors {
exit(1)
}
} }

View File

@ -128,31 +128,7 @@ fn (f mut Fmt) stmt(node ast.Stmt) {
f.writeln('') f.writeln('')
} }
ast.FnDecl { ast.FnDecl {
mut receiver := '' f.write(it.str(f.table))
if it.is_method {
sym := f.table.get_type_symbol(it.receiver.typ)
name := sym.name.after('.')
m := if it.rec_mut { 'mut ' } else { '' }
receiver = '($it.receiver.name ${m}$name) '
}
f.write('fn ${receiver}${it.name}(')
for i, arg in it.args {
is_last_arg := i == it.args.len - 1
should_add_type := is_last_arg || it.args[i + 1].typ != arg.typ
f.write(arg.name)
if should_add_type {
arg_typ_sym := f.table.get_type_symbol(arg.typ)
f.write(' ${arg_typ_sym.name}')
}
if !is_last_arg {
f.write(', ')
}
}
f.write(')')
if it.typ != table.void_type {
sym := f.table.get_type_symbol(it.typ)
f.write(' ' + sym.name)
}
f.writeln(' {') f.writeln(' {')
f.stmts(it.stmts) f.stmts(it.stmts)
f.writeln('}\n') f.writeln('}\n')

View File

@ -68,3 +68,7 @@ fn fn_with_3_args(arg1 string, arg2 int, arg3 User) int {
fn (this User) fn_with_receiver() { fn (this User) fn_with_receiver() {
println('') println('')
} }
//fn get_user() ?User {
//}

View File

@ -72,3 +72,7 @@ return 0
fn (this User) fn_with_receiver() { fn (this User) fn_with_receiver() {
println('') println('')
} }
//fn get_user() ? User {
//}

View File

@ -134,6 +134,8 @@ const (
) )
fn end() { fn end() {
//mut a := [1,2,3]
//(a << 4) + 2
} }

View File

@ -638,6 +638,8 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
} }
.key_none { .key_none {
p.next() p.next()
typ = table.none_type
node = ast.None {}
} }
.key_sizeof { .key_sizeof {
p.next() // sizeof p.next() // sizeof

View File

@ -39,6 +39,7 @@ pub const (
string_type_idx = 17 string_type_idx = 17
array_type_idx = 18 array_type_idx = 18
map_type_idx = 19 map_type_idx = 19
none_type_idx = 20
) )
pub const ( pub const (
@ -81,6 +82,7 @@ pub enum Kind {
sum_type sum_type
alias alias
unresolved unresolved
none_
} }
[inline] [inline]
@ -236,6 +238,10 @@ pub fn (t mut Table) register_builtin_type_symbols() {
kind: .map kind: .map
name: 'map' name: 'map'
}) })
t.register_type_symbol(TypeSymbol{
kind: .none_
name: 'none'
})
// TODO: remove // TODO: remove
t.register_type_symbol(TypeSymbol{ t.register_type_symbol(TypeSymbol{
parent_idx: map_type_idx parent_idx: map_type_idx

View File

@ -2,9 +2,12 @@
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module table module table
// import (
// v.ast import (
// ) v.token
// v.ast
)
pub struct Table { pub struct Table {
// struct_fields map[string][]string // struct_fields map[string][]string
pub mut: pub mut:
@ -361,6 +364,10 @@ pub fn (t &Table) check(got, expected Type) bool {
got_idx := type_idx(got) got_idx := type_idx(got)
exp_idx := type_idx(expected) exp_idx := type_idx(expected)
// println('check: $got_type_sym.name, $exp_type_sym.name') // println('check: $got_type_sym.name, $exp_type_sym.name')
if got_type_sym.kind == .none_ {
// TODO
return true
}
if exp_type_sym.kind == .voidptr { if exp_type_sym.kind == .voidptr {
return true return true
} }

View File

@ -1,87 +1,87 @@
module table module table
pub type Type int pub type Type int
// return underlying TypeSymbol idx // return underlying TypeSymbol idx
[inline] [inline]
pub fn type_idx(t Type) int { pub fn type_idx(t Type) int {
return i16(int(t) >> 16) & 0xffffffff return i16(int(t)>>16) & 0xffffffff
} }
// return nr_muls // return nr_muls
[inline] [inline]
pub fn type_nr_muls(t Type) int { pub fn type_nr_muls(t Type) int {
return i16(int(t) & 0xffffffff) return i16(int(t) & 0xffffffff)
} }
// return true if pointer (nr_muls>0) // return true if pointer (nr_muls>0)
[inline] [inline]
pub fn type_is_ptr(t Type) bool { pub fn type_is_ptr(t Type) bool {
return type_nr_muls(t) > 0 return type_nr_muls(t) > 0
} }
// increments nr_nuls on Type and return it // increments nr_nuls on Type and return it
[inline] [inline]
pub fn type_to_ptr(t Type) Type { pub fn type_to_ptr(t Type) Type {
return type_idx(t) << i16(16) | (type_nr_muls(t)+1) return type_idx(t)<<i16(16) | (type_nr_muls(t) + 1)
} }
// decrement nr_muls on Type and return it // decrement nr_muls on Type and return it
[inline] [inline]
pub fn type_deref(t Type) Type { pub fn type_deref(t Type) Type {
idx := type_idx(t) idx := type_idx(t)
nr_muls := type_nr_muls(t) nr_muls := type_nr_muls(t)
if nr_muls == 0 { if nr_muls == 0 {
panic('deref: $idx is not a pointer') panic('deref: $idx is not a pointer')
} }
return idx << i16(16) | (nr_muls+-1) return idx<<i16(16) | (nr_muls + -1)
} }
// new type with idx of TypeSymbol, not pointer (nr_muls=0) // new type with idx of TypeSymbol, not pointer (nr_muls=0)
[inline] [inline]
pub fn new_type(idx int) Type { pub fn new_type(idx int) Type {
if idx > 32767 || idx < -32767 { if idx > 32767 || idx < -32767 {
panic('new_type_id: idx must be between -32767 & 32767') panic('new_type_id: idx must be between -32767 & 32767')
} }
return idx << i16(16) return idx<<i16(16)
} }
// return Type idx of TypeSymbol & specify if ptr (nr_muls) // return Type idx of TypeSymbol & specify if ptr (nr_muls)
[inline] [inline]
pub fn new_type_ptr(idx, nr_muls int) Type { pub fn new_type_ptr(idx, nr_muls int) Type {
if idx > 32767 || idx < -32767 { if idx > 32767 || idx < -32767 {
panic('typ_ptr: idx must be between -32767 & 32767') panic('typ_ptr: idx must be between -32767 & 32767')
} }
if nr_muls > 32767 || nr_muls < -0 { if nr_muls > 32767 || nr_muls < -0 {
panic('typ_ptr: nr_muls must be between 0 & 32767') panic('typ_ptr: nr_muls must be between 0 & 32767')
} }
return idx << i16(16) | nr_muls return idx<<i16(16) | nr_muls
} }
// true if the type of unresolved expression // true if the type of unresolved expression
[inline] [inline]
pub fn type_is_unresolved(t Type) bool { pub fn type_is_unresolved(t Type) bool {
return type_idx(t) < 0 return type_idx(t) < 0
} }
pub const ( pub const (
void_type = new_type(void_type_idx) void_type = new_type(void_type_idx)
voidptr_type = new_type(voidptr_type_idx) voidptr_type = new_type(voidptr_type_idx)
byteptr_type = new_type(byteptr_type_idx) byteptr_type = new_type(byteptr_type_idx)
charptr_type = new_type(charptr_type_idx) charptr_type = new_type(charptr_type_idx)
i8_type = new_type(i8_type_idx) i8_type = new_type(i8_type_idx)
int_type = new_type(int_type_idx) int_type = new_type(int_type_idx)
i16_type = new_type(i16_type_idx) i16_type = new_type(i16_type_idx)
i64_type = new_type(i64_type_idx) i64_type = new_type(i64_type_idx)
byte_type = new_type(byte_type_idx) byte_type = new_type(byte_type_idx)
u16_type = new_type(u16_type_idx) u16_type = new_type(u16_type_idx)
u32_type = new_type(u32_type_idx) u32_type = new_type(u32_type_idx)
u64_type = new_type(u64_type_idx) u64_type = new_type(u64_type_idx)
f32_type = new_type(f32_type_idx) f32_type = new_type(f32_type_idx)
f64_type = new_type(f64_type_idx) f64_type = new_type(f64_type_idx)
char_type = new_type(char_type_idx) char_type = new_type(char_type_idx)
bool_type = new_type(bool_type_idx) bool_type = new_type(bool_type_idx)
string_type = new_type(string_type_idx) string_type = new_type(string_type_idx)
array_type = new_type(array_type_idx) array_type = new_type(array_type_idx)
map_type = new_type(map_type_idx) map_type = new_type(map_type_idx)
none_type = new_type(none_type_idx)
) )