From bb60b3081f7b46533a543fab1a5c6e37241d9354 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Fri, 7 Feb 2020 07:34:18 +0100 Subject: [PATCH] v2: parse builtin successfully --- vlib/builtin/array.v | 2 +- vlib/v/checker/checker.v | 26 ++++++++++--- vlib/v/gen/tests/1.vv | 7 ++++ vlib/v/parser/fn.v | 3 +- vlib/v/parser/parser.v | 79 +++++++++++++++++++++++++--------------- vlib/v/table/table.v | 19 +++++++--- 6 files changed, 92 insertions(+), 44 deletions(-) diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 97a1cb1889..354b149a34 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -367,7 +367,7 @@ pub fn (b []byte) hex() string { mut hex := malloc(b.len * 2 + 1) mut ptr := &hex[0] for i := 0; i < b.len; i++ { - ptr += C.sprintf(charptr(ptr), '%02x', b[i]) + ptr += C.sprintf(ptr as charptr, '%02x', b[i]) } return string(hex) } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9ac83aac10..c68745f30e 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -7,6 +7,7 @@ import ( v.ast v.table v.token + os ) pub struct Checker { @@ -140,11 +141,13 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef { fn_name := call_expr.name if f := c.table.find_fn(fn_name) { // return_ti := f.return_ti - if call_expr.args.len < f.args.len { - c.error('too few arguments in call to `$fn_name`', call_expr.pos) - } - else if call_expr.args.len > f.args.len { - c.error('too many arguments in call to `$fn_name`', call_expr.pos) + if !f.is_c { + if call_expr.args.len < f.args.len { + c.error('too few arguments in call to `$fn_name`', call_expr.pos) + } + else if call_expr.args.len > f.args.len { + c.error('too many arguments in call to `$fn_name`', call_expr.pos) + } } for i, arg in f.args { arg_expr := call_expr.args[i] @@ -179,6 +182,11 @@ pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.TypeRef } return field.typ } + .array { + if field_name == 'len' { + return c.table.type_ref(table.int_type_idx) + } + } else { c.error('`$typ.typ.name` is not a struct', selector_expr.pos) } @@ -404,7 +412,13 @@ pub fn (c &Checker) index_expr(node ast.IndexExpr) table.TypeRef { pub fn (c &Checker) error(s string, pos token.Position) { print_backtrace() - final_msg_line := '$c.file_name:$pos.line_nr: error: $s' + mut path := c.file_name + // Get relative path + workdir := os.getwd() + os.path_separator + if path.starts_with(workdir) { + path = path.replace(workdir, '') + } + final_msg_line := '$path:$pos.line_nr: checker error: $s' eprintln(final_msg_line) /* if colored_output { diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index 71f02aa4ff..dc1f6ccb53 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -97,6 +97,7 @@ fn multi_return() (int,string) { } fn variadic(a ...int) { + //a := path_sep } fn ensure_cap(required int, cap int) { @@ -105,4 +106,10 @@ fn ensure_cap(required int, cap int) { } } +/* +const ( + path_sep = 10 +) +*/ + diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 7293d66385..7c457da608 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -18,6 +18,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.TypeRef) { name: fn_name args: args // tok: tok + pos: tok.position() } if p.tok.kind == .key_orelse { @@ -166,6 +167,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { name: name args: args return_type: typ + is_c: is_c }) } mut stmts := []ast.Stmt @@ -184,4 +186,3 @@ fn (p mut Parser) fn_decl() ast.FnDecl { } } } - diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 978751e58d..ed4863d440 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -26,25 +26,25 @@ type PostfixParseFn fn()ast.Expr struct Parser { - scanner &scanner.Scanner - file_name string + scanner &scanner.Scanner + file_name string mut: - tok token.Token - peek_tok token.Token + tok token.Token + peek_tok token.Token // vars []string - table &table.Table - return_type table.TypeRef // current function's return type + table &table.Table + return_type table.TypeRef // current function's return type // scope_level int // var_idx int - is_c bool + is_c bool // // prefix_parse_fns []PrefixParseFn - inside_if bool - pref &pref.Preferences // Preferences shared from V struct - builtin_mod bool - mod string - unresolved []ast.Expr - unresolved_idxs map[string]int + inside_if bool + pref &pref.Preferences // Preferences shared from V struct + builtin_mod bool + mod string + unresolved []ast.Expr + unresolved_idxs map[string]int } // for tests @@ -302,9 +302,12 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr { p.next() } p.check(.dotdot) - high,typ := p.expr(0) - if typ.typ.kind != .int { - p.error('non-integer index `$typ.typ.name`') + mut high := ast.Expr{} + if p.tok.kind != .rsbr { + high,_ = p.expr(0) + // if typ.typ.kind != .int { + // p.error('non-integer index `$typ.typ.name`') + // } } node := ast.RangeExpr{ low: low @@ -343,7 +346,13 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt { pub fn (p &Parser) error(s string) { print_backtrace() - final_msg_line := '$p.file_name:$p.tok.line_nr: error: $s' + mut path := p.file_name + // Get relative path + workdir := os.getwd() + os.path_separator + if path.starts_with(workdir) { + path = path.replace(workdir, '') + } + final_msg_line := 'xxx$path:$p.tok.line_nr: error: $s' if colored_output { eprintln(term.bold(term.red(final_msg_line))) } @@ -374,7 +383,7 @@ pub fn (p &Parser) warn(s string) { } } -pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) { +pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.TypeRef) { mut node := ast.Ident{} mut typ := p.table.type_ref(table.void_type_idx) // p.warn('name ') @@ -387,7 +396,7 @@ pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) { if var := p.table.find_var(name) { known_var = true typ = var.typ - } + } // variable if known_var || p.tok.kind in [.comma, .decl_assign, .assign] { // println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx') @@ -396,14 +405,17 @@ pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) { typ: typ // name: ident.name // expr: p.expr(0)// var.expr + } - return ident, typ - }else{ + return ident,typ + } + else { if is_c { typ = p.table.type_ref(table.int_type_idx) ident.info = ast.IdentVar{ typ: typ // name: ident.name + } return ident,typ } @@ -414,18 +426,20 @@ pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) { ident.info = ast.IdentVar{ typ: typ // name: ident.name + } node = ident }else{ // Function object (not a call), e.g. `onclick(my_click)` p.table.find_fn(name) or { + // ident.info = ast.IdentVar p.error('parse_ident: unknown identifier `$name`') exit(0) } // p.next() } } - return node, typ + return node,typ } pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { @@ -484,7 +498,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { } else { mut ident := ast.Ident{} - ident, typ = p.parse_ident(is_c) + ident,typ = p.parse_ident(is_c) node = ident } return node,typ @@ -622,6 +636,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr { index: index_expr pos: p.tok.position() // typ: typ + } return node // return node,typ @@ -707,7 +722,7 @@ fn (p mut Parser) for_statement() ast.Stmt { p.error('`mut` is not required in for loops') } // for i := 0; i < 10; i++ { - else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] { + else if p.peek_tok.kind in [.decl_assign, .assign, .semicolon] || p.tok.kind == .semicolon { mut init := ast.Stmt{} mut cond := ast.Expr{} mut inc := ast.Stmt{} @@ -727,7 +742,9 @@ fn (p mut Parser) for_statement() ast.Stmt { } p.check(.semicolon) if p.tok.kind != .semicolon { - mut typ := table.TypeRef{typ:0} + mut typ := table.TypeRef{ + typ: 0 + } cond,typ = p.expr(0) } p.check(.semicolon) @@ -836,7 +853,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) { } if p.peek_tok.kind != .str_dollar { p.next() - return node, p.table.type_ref(table.string_type_idx) + return node,p.table.type_ref(table.string_type_idx) } // Handle $ interpolation for p.tok.kind == .str { @@ -850,7 +867,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) { p.next() } } - return node, p.table.type_ref(table.string_type_idx) + return node,p.table.type_ref(table.string_type_idx) } fn (p mut Parser) array_init() (ast.Expr,table.TypeRef) { @@ -1011,6 +1028,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { fields << table.Field{ name: field_name // type_idx: ti.idx + typ: typ } // println('struct field $ti.name $field_name') @@ -1072,16 +1090,17 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt { // TODO: multiple return & multiple assign mut idents := []ast.Ident for { - ident, _ := p.parse_ident(false) + ident,_ := p.parse_ident(false) idents << ident if p.tok.kind == .comma { p.check(.comma) - } else { + } + else { break } } p.next() // :=, = - expr, _ := p.expr(0) + expr,_ := p.expr(0) return ast.AssignStmt{ left: idents right: [expr] diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 1912711afe..b3f6e570cc 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -26,6 +26,7 @@ pub: name string args []Var return_type TypeRef + is_c bool } pub struct Var { @@ -37,7 +38,7 @@ pub: is_global bool scope_level int mut: - typ TypeRef + typ TypeRef } pub fn new_table() &Table { @@ -88,6 +89,7 @@ pub fn (t mut Table) register_global(name string, typ TypeRef) { // mod: p.mod // is_mut: true // idx: -1 + } } @@ -222,7 +224,8 @@ pub fn (t mut Table) new_tmp_var() string { pub fn (t &Table) struct_has_field(s &Type, name string) bool { if !isnil(s.parent) { println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') - } else { + } + else { println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=none') } // for typ in t.types { @@ -237,7 +240,8 @@ pub fn (t &Table) struct_has_field(s &Type, name string) bool { pub fn (t &Table) struct_find_field(s &Type, name string) ?Field { if !isnil(s.parent) { println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') - } else { + } + else { println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=none') } info := s.info as Struct @@ -296,7 +300,7 @@ pub fn (t mut Table) register_type(typ Type) int { // panic('cannot register type `$typ.name`, another type with this name exists') return -1 } - } + } } typ_idx := t.types.len t.types << typ @@ -312,7 +316,7 @@ pub fn (t &Table) known_type(name string) bool { } pub fn (t mut Table) find_or_register_map(key_type TypeRef, value_type TypeRef) int { - name := map_name(&key_type, &value_type) + name := map_name(&key_type, &value_type) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -352,7 +356,7 @@ pub fn (t mut Table) find_or_register_array(elem_type TypeRef, nr_dims int) int } pub fn (t mut Table) find_or_register_array_fixed(elem_type TypeRef, size int, nr_dims int) int { - name := array_fixed_name(&elem_type, size, nr_dims) + name := array_fixed_name(&elem_type, size, nr_dims) // existing existing_idx := t.type_idxs[name] if existing_idx > 0 { @@ -428,6 +432,9 @@ pub fn (t &Table) check(got, expected &TypeRef) bool { if expected.typ.kind == .voidptr { return true } + if expected.typ.kind == .byteptr && got.typ.kind == .voidptr { + return true + } // if expected.name == 'array' { // return true // }