v2: parse builtin successfully
parent
2ce6b190dd
commit
bb60b3081f
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
// }
|
// }
|
||||||
|
|
Loading…
Reference in New Issue