v2: parse builtin successfully

pull/3997/head
Alexander Medvednikov 2020-02-07 07:34:18 +01:00
parent 2ce6b190dd
commit bb60b3081f
6 changed files with 92 additions and 44 deletions

View File

@ -367,7 +367,7 @@ pub fn (b []byte) hex() string {
mut hex := malloc(b.len * 2 + 1) mut hex := malloc(b.len * 2 + 1)
mut ptr := &hex[0] mut ptr := &hex[0]
for i := 0; i < b.len; i++ { 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) return string(hex)
} }

View File

@ -7,6 +7,7 @@ import (
v.ast v.ast
v.table v.table
v.token v.token
os
) )
pub struct Checker { pub struct Checker {
@ -140,11 +141,13 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef {
fn_name := call_expr.name fn_name := call_expr.name
if f := c.table.find_fn(fn_name) { if f := c.table.find_fn(fn_name) {
// return_ti := f.return_ti // return_ti := f.return_ti
if call_expr.args.len < f.args.len { if !f.is_c {
c.error('too few arguments in call to `$fn_name`', call_expr.pos) 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) 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 { for i, arg in f.args {
arg_expr := call_expr.args[i] 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 return field.typ
} }
.array {
if field_name == 'len' {
return c.table.type_ref(table.int_type_idx)
}
}
else { else {
c.error('`$typ.typ.name` is not a struct', selector_expr.pos) 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) { pub fn (c &Checker) error(s string, pos token.Position) {
print_backtrace() 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) eprintln(final_msg_line)
/* /*
if colored_output { if colored_output {

View File

@ -97,6 +97,7 @@ fn multi_return() (int,string) {
} }
fn variadic(a ...int) { fn variadic(a ...int) {
//a := path_sep
} }
fn ensure_cap(required int, cap int) { fn ensure_cap(required int, cap int) {
@ -105,4 +106,10 @@ fn ensure_cap(required int, cap int) {
} }
} }
/*
const (
path_sep = 10
)
*/

View File

@ -18,6 +18,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.TypeRef) {
name: fn_name name: fn_name
args: args args: args
// tok: tok // tok: tok
pos: tok.position() pos: tok.position()
} }
if p.tok.kind == .key_orelse { if p.tok.kind == .key_orelse {
@ -166,6 +167,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
name: name name: name
args: args args: args
return_type: typ return_type: typ
is_c: is_c
}) })
} }
mut stmts := []ast.Stmt mut stmts := []ast.Stmt
@ -184,4 +186,3 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
} }
} }
} }

View File

@ -26,25 +26,25 @@ type PostfixParseFn fn()ast.Expr
struct Parser { struct Parser {
scanner &scanner.Scanner scanner &scanner.Scanner
file_name string file_name string
mut: mut:
tok token.Token tok token.Token
peek_tok token.Token peek_tok token.Token
// vars []string // vars []string
table &table.Table table &table.Table
return_type table.TypeRef // current function's return type return_type table.TypeRef // current function's return type
// scope_level int // scope_level int
// var_idx int // var_idx int
is_c bool is_c bool
// //
// prefix_parse_fns []PrefixParseFn // prefix_parse_fns []PrefixParseFn
inside_if bool inside_if bool
pref &pref.Preferences // Preferences shared from V struct pref &pref.Preferences // Preferences shared from V struct
builtin_mod bool builtin_mod bool
mod string mod string
unresolved []ast.Expr unresolved []ast.Expr
unresolved_idxs map[string]int unresolved_idxs map[string]int
} }
// for tests // for tests
@ -302,9 +302,12 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
p.next() p.next()
} }
p.check(.dotdot) p.check(.dotdot)
high,typ := p.expr(0) mut high := ast.Expr{}
if typ.typ.kind != .int { if p.tok.kind != .rsbr {
p.error('non-integer index `$typ.typ.name`') high,_ = p.expr(0)
// if typ.typ.kind != .int {
// p.error('non-integer index `$typ.typ.name`')
// }
} }
node := ast.RangeExpr{ node := ast.RangeExpr{
low: low low: low
@ -343,7 +346,13 @@ pub fn (p mut Parser) assign_stmt() ast.AssignStmt {
pub fn (p &Parser) error(s string) { pub fn (p &Parser) error(s string) {
print_backtrace() 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 { if colored_output {
eprintln(term.bold(term.red(final_msg_line))) 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 node := ast.Ident{}
mut typ := p.table.type_ref(table.void_type_idx) mut typ := p.table.type_ref(table.void_type_idx)
// p.warn('name ') // p.warn('name ')
@ -396,14 +405,17 @@ pub fn(p mut Parser) parse_ident(is_c bool) (ast.Ident, table.TypeRef) {
typ: typ typ: typ
// name: ident.name // name: ident.name
// expr: p.expr(0)// var.expr // expr: p.expr(0)// var.expr
} }
return ident, typ return ident,typ
}else{ }
else {
if is_c { if is_c {
typ = p.table.type_ref(table.int_type_idx) typ = p.table.type_ref(table.int_type_idx)
ident.info = ast.IdentVar{ ident.info = ast.IdentVar{
typ: typ typ: typ
// name: ident.name // name: ident.name
} }
return ident,typ 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{ ident.info = ast.IdentVar{
typ: typ typ: typ
// name: ident.name // name: ident.name
} }
node = ident node = ident
}else{ }else{
// Function object (not a call), e.g. `onclick(my_click)` // Function object (not a call), e.g. `onclick(my_click)`
p.table.find_fn(name) or { p.table.find_fn(name) or {
// ident.info = ast.IdentVar
p.error('parse_ident: unknown identifier `$name`') p.error('parse_ident: unknown identifier `$name`')
exit(0) exit(0)
} }
// p.next() // p.next()
} }
} }
return node, typ return node,typ
} }
pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) { 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 { else {
mut ident := ast.Ident{} mut ident := ast.Ident{}
ident, typ = p.parse_ident(is_c) ident,typ = p.parse_ident(is_c)
node = ident node = ident
} }
return node,typ return node,typ
@ -622,6 +636,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr {
index: index_expr index: index_expr
pos: p.tok.position() pos: p.tok.position()
// typ: typ // typ: typ
} }
return node return node
// return node,typ // return node,typ
@ -707,7 +722,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
p.error('`mut` is not required in for loops') p.error('`mut` is not required in for loops')
} }
// for i := 0; i < 10; i++ { // 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 init := ast.Stmt{}
mut cond := ast.Expr{} mut cond := ast.Expr{}
mut inc := ast.Stmt{} mut inc := ast.Stmt{}
@ -727,7 +742,9 @@ fn (p mut Parser) for_statement() ast.Stmt {
} }
p.check(.semicolon) p.check(.semicolon)
if p.tok.kind != .semicolon { if p.tok.kind != .semicolon {
mut typ := table.TypeRef{typ:0} mut typ := table.TypeRef{
typ: 0
}
cond,typ = p.expr(0) cond,typ = p.expr(0)
} }
p.check(.semicolon) p.check(.semicolon)
@ -836,7 +853,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) {
} }
if p.peek_tok.kind != .str_dollar { if p.peek_tok.kind != .str_dollar {
p.next() p.next()
return node, p.table.type_ref(table.string_type_idx) return node,p.table.type_ref(table.string_type_idx)
} }
// Handle $ interpolation // Handle $ interpolation
for p.tok.kind == .str { for p.tok.kind == .str {
@ -850,7 +867,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.TypeRef) {
p.next() 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) { 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{ fields << table.Field{
name: field_name name: field_name
// type_idx: ti.idx // type_idx: ti.idx
typ: typ typ: typ
} }
// println('struct field $ti.name $field_name') // 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 // TODO: multiple return & multiple assign
mut idents := []ast.Ident mut idents := []ast.Ident
for { for {
ident, _ := p.parse_ident(false) ident,_ := p.parse_ident(false)
idents << ident idents << ident
if p.tok.kind == .comma { if p.tok.kind == .comma {
p.check(.comma) p.check(.comma)
} else { }
else {
break break
} }
} }
p.next() // :=, = p.next() // :=, =
expr, _ := p.expr(0) expr,_ := p.expr(0)
return ast.AssignStmt{ return ast.AssignStmt{
left: idents left: idents
right: [expr] right: [expr]

View File

@ -26,6 +26,7 @@ pub:
name string name string
args []Var args []Var
return_type TypeRef return_type TypeRef
is_c bool
} }
pub struct Var { pub struct Var {
@ -37,7 +38,7 @@ pub:
is_global bool is_global bool
scope_level int scope_level int
mut: mut:
typ TypeRef typ TypeRef
} }
pub fn new_table() &Table { pub fn new_table() &Table {
@ -88,6 +89,7 @@ pub fn (t mut Table) register_global(name string, typ TypeRef) {
// mod: p.mod // mod: p.mod
// is_mut: true // is_mut: true
// idx: -1 // 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 { pub fn (t &Table) struct_has_field(s &Type, name string) bool {
if !isnil(s.parent) { if !isnil(s.parent) {
println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') 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') println('struct_has_field($s.name, $name) types.len=$t.types.len s.parent=none')
} }
// for typ in t.types { // 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 { pub fn (t &Table) struct_find_field(s &Type, name string) ?Field {
if !isnil(s.parent) { if !isnil(s.parent) {
println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=$s.parent.name') 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') println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent=none')
} }
info := s.info as Struct 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') // panic('cannot register type `$typ.name`, another type with this name exists')
return -1 return -1
} }
} }
} }
typ_idx := t.types.len typ_idx := t.types.len
t.types << typ t.types << typ
@ -428,6 +432,9 @@ pub fn (t &Table) check(got, expected &TypeRef) bool {
if expected.typ.kind == .voidptr { if expected.typ.kind == .voidptr {
return true return true
} }
if expected.typ.kind == .byteptr && got.typ.kind == .voidptr {
return true
}
// if expected.name == 'array' { // if expected.name == 'array' {
// return true // return true
// } // }