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
for {
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] {
C.memcpy(out, node.values[i], m.value_bytes)
return true

View File

@ -11,7 +11,7 @@ import (
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
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 |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
@ -473,6 +473,10 @@ pub:
text string
}
pub struct None {
pub:
foo int // todo
}
// string representaiton of expr
pub fn (x Expr) str() string {
match x {

View File

@ -11,11 +11,16 @@ import (
filepath
)
const (
max_nr_errors = 10
)
pub struct Checker {
table &table.Table
mut:
file_name string
scope &ast.Scope
nr_errors int
}
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)
right_type := c.expr(infix_expr.right)
if !c.table.check(right_type, left_type) {
left_type_sym := c.table.get_type_symbol(left_type)
right_type_sym := c.table.get_type_symbol(right_type)
left := c.table.get_type_symbol(left_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) {
// 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() {
return table.bool_type
@ -367,6 +377,9 @@ pub fn (c mut Checker) expr(node ast.Expr) table.Type {
ast.CastExpr {
return it.typ
}
ast.None {
return table.none_type
}
else {}
}
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] {
return table.byte_type
}
//else {
// return table.int_type
//}
// else {
// return table.int_type
// }
}
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()
mut path := c.file_name
// Get relative path
@ -585,7 +599,7 @@ pub fn (c &Checker) error(s string, pos token.Position) {
if path.starts_with(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)
/*
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('')
}
ast.FnDecl {
mut receiver := ''
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.write(it.str(f.table))
f.writeln(' {')
f.stmts(it.stmts)
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() {
println('')
}
//fn get_user() ?User {
//}

View File

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

View File

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

View File

@ -56,7 +56,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
pref: &pref.Preferences{}
scope: scope
// scope: &ast.Scope{start_pos: 0, parent: 0}
}
p.init_parse_fns()
p.read_first_token()
@ -320,7 +320,7 @@ pub fn (p mut Parser) stmt() ast.Stmt {
return ast.ExprStmt{
expr: expr
// typ: typ
}
}
}
@ -638,6 +638,8 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
}
.key_none {
p.next()
typ = table.none_type
node = ast.None {}
}
.key_sizeof {
p.next() // sizeof
@ -1072,10 +1074,10 @@ fn (p mut Parser) if_expr() ast.Expr {
stmts: stmts
else_stmts: else_stmts
// typ: typ
pos: pos
// left: left
}
return node
}
@ -1463,10 +1465,10 @@ fn (p mut Parser) var_decl() ast.VarDecl {
node := ast.VarDecl{
name: name
expr: expr // p.expr(token.lowest_prec)
is_mut: is_mut
// typ: typ
pos: p.tok.position()
}
p.scope.register_var(node)
@ -1585,7 +1587,7 @@ fn (p mut Parser) match_expr() ast.Expr {
blocks: blocks
match_exprs: match_exprs
// typ: typ
cond: cond
}
return node

View File

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

View File

@ -2,9 +2,12 @@
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.
module table
// import (
// v.ast
// )
import (
v.token
// v.ast
)
pub struct Table {
// struct_fields map[string][]string
pub mut:
@ -361,6 +364,10 @@ pub fn (t &Table) check(got, expected Type) bool {
got_idx := type_idx(got)
exp_idx := type_idx(expected)
// 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 {
return true
}

View File

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