mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker/gen: add unchecked exprs & small fixes
This commit is contained in:
parent
a011b8951a
commit
126ef0f5c2
@ -235,14 +235,14 @@ fn vfopen(path, mode string) &C.FILE {
|
||||
// read_lines reads the file in `path` into an array of lines.
|
||||
pub fn read_lines(path string) ?[]string {
|
||||
buf := read_file(path) or {
|
||||
return err
|
||||
return error(err)
|
||||
}
|
||||
return buf.split_into_lines()
|
||||
}
|
||||
|
||||
fn read_ulines(path string) ?[]ustring {
|
||||
lines := read_lines(path) or {
|
||||
return err
|
||||
return error(err)
|
||||
}
|
||||
// mut ulines := new_array(0, lines.len, sizeof(ustring))
|
||||
mut ulines := []ustring
|
||||
|
@ -82,7 +82,8 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type
|
||||
.placeholder {
|
||||
c.error('unknown struct: $typ_sym.name', struct_init.pos)
|
||||
}
|
||||
.struct_ {
|
||||
// string & array are also structs but .kind of string/array
|
||||
.struct_, .string, .array {
|
||||
info := typ_sym.info as table.Struct
|
||||
if struct_init.fields.len == 0 {
|
||||
// Short syntax TODO check
|
||||
@ -154,17 +155,15 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||
}
|
||||
|
||||
fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||
if ast.expr_is_blank_ident(assign_expr.left) {
|
||||
return
|
||||
}
|
||||
left_type := c.expr(assign_expr.left)
|
||||
c.expected_type = left_type
|
||||
assign_expr.left_type = left_type
|
||||
// assign_expr.left_type = left_type
|
||||
// t := c.table.get_type_symbol(left_type)
|
||||
// println('setting exp type to $c.expected_type $t.name')
|
||||
right_type := c.expr(assign_expr.val)
|
||||
assign_expr.right_type = right_type
|
||||
if ast.expr_is_blank_ident(assign_expr.left) {
|
||||
return
|
||||
}
|
||||
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)
|
||||
@ -174,18 +173,19 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||
|
||||
pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||
fn_name := call_expr.name
|
||||
c.stmts(call_expr.or_block.stmts)
|
||||
// TODO: impl typeof properly (probably not going to be a fn call)
|
||||
if fn_name == 'typeof' {
|
||||
return table.string_type
|
||||
}
|
||||
// start hack: until v1 is fixed and c definitions are added for these
|
||||
if fn_name == 'C.calloc' {
|
||||
return table.byteptr_type
|
||||
}
|
||||
else if fn_name == 'C.exit' {
|
||||
return table.void_type
|
||||
}
|
||||
else if fn_name == 'C.free' {
|
||||
if fn_name in ['C.calloc', 'C.exit', 'C.free'] {
|
||||
for arg in call_expr.args {
|
||||
c.expr(arg.expr)
|
||||
}
|
||||
if fn_name == 'C.calloc' {
|
||||
return table.byteptr_type
|
||||
}
|
||||
return table.void_type
|
||||
}
|
||||
// end hack
|
||||
@ -224,6 +224,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||
}
|
||||
if !found {
|
||||
c.error('unknown fn: $fn_name', call_expr.pos)
|
||||
return table.void_type
|
||||
}
|
||||
call_expr.return_type = f.return_type
|
||||
if f.is_c || call_expr.is_c {
|
||||
@ -275,6 +276,7 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr)
|
||||
method_call_expr.expr_type = typ
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
name := method_call_expr.name
|
||||
c.stmts(method_call_expr.or_block.stmts)
|
||||
// println('method call $name $method_call_expr.pos.line_nr')
|
||||
if typ_sym.kind == .array && name in ['filter', 'clone', 'repeat'] {
|
||||
if name == 'filter' {
|
||||
@ -285,12 +287,11 @@ pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr)
|
||||
typ: array_info.elem_type
|
||||
})
|
||||
}
|
||||
else if name == 'repeat' {
|
||||
c.expr(method_call_expr.args[0].expr)
|
||||
for i, arg in method_call_expr.args {
|
||||
c.expr(arg.expr)
|
||||
}
|
||||
// need to return `array_xxx` instead of `array`
|
||||
method_call_expr.return_type = typ
|
||||
// method_call_expr.receiver_type = typ
|
||||
return typ
|
||||
}
|
||||
else if typ_sym.kind == .array && name in ['first', 'last'] {
|
||||
@ -466,7 +467,6 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
|
||||
// [1,2,3]
|
||||
if array_init.exprs.len > 0 && array_init.elem_type == table.void_type {
|
||||
for i, expr in array_init.exprs {
|
||||
c.expr(expr)
|
||||
typ := c.expr(expr)
|
||||
// The first element's type
|
||||
if i == 0 {
|
||||
|
@ -412,7 +412,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||
else {
|
||||
g.write('{$styp _ = ')
|
||||
g.expr(val)
|
||||
g.writeln('}')
|
||||
g.writeln(';}')
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -575,7 +575,7 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
else {
|
||||
g.write('{${g.typ(it.left_type)} _ = ')
|
||||
g.expr(it.val)
|
||||
g.writeln('}')
|
||||
g.writeln(';}')
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -732,20 +732,20 @@ fn (g mut Gen) expr(node ast.Expr) {
|
||||
}
|
||||
}
|
||||
ast.MethodCallExpr {
|
||||
mut receiver_name := 'TODO'
|
||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||
if it.expr_type != 0 {
|
||||
typ_sym := g.table.get_type_symbol(it.expr_type)
|
||||
// rec_sym := g.table.get_type_symbol(it.receiver_type)
|
||||
receiver_name = typ_sym.name
|
||||
if typ_sym.kind == .array && it.name in
|
||||
// TODO performance, detect `array` method differently
|
||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'clone'] {
|
||||
// && rec_sym.name == 'array' {
|
||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||
// `array_byte_clone` => `array_clone`
|
||||
receiver_name = 'array'
|
||||
}
|
||||
if it.expr_type == 0 {
|
||||
verror('method receiver type is 0, this means there are some uchecked exprs')
|
||||
}
|
||||
typ_sym := g.table.get_type_symbol(it.expr_type)
|
||||
// rec_sym := g.table.get_type_symbol(it.receiver_type)
|
||||
mut receiver_name := typ_sym.name
|
||||
if typ_sym.kind == .array && it.name in
|
||||
// TODO performance, detect `array` method differently
|
||||
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'clone'] {
|
||||
// && rec_sym.name == 'array' {
|
||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||
// `array_byte_clone` => `array_clone`
|
||||
receiver_name = 'array'
|
||||
}
|
||||
name := '${receiver_name}_$it.name'.replace('.', '__')
|
||||
// if it.receiver_type != 0 {
|
||||
|
@ -17,12 +17,19 @@ pub fn (p mut Parser) call_expr(is_c bool, mod string) ast.CallExpr {
|
||||
mut or_stmts := []ast.Stmt
|
||||
if p.tok.kind == .key_orelse {
|
||||
p.next()
|
||||
or_stmts = p.parse_block()
|
||||
p.open_scope()
|
||||
p.scope.register_var(ast.Var{
|
||||
name: 'err'
|
||||
typ: table.type_to_optional(table.string_type)
|
||||
})
|
||||
or_stmts = p.parse_block_no_scope()
|
||||
p.close_scope()
|
||||
}
|
||||
node := ast.CallExpr{
|
||||
name: fn_name
|
||||
args: args
|
||||
// tok: tok
|
||||
|
||||
pos: tok.position()
|
||||
is_c: is_c
|
||||
or_block: ast.OrExpr{
|
||||
|
@ -193,6 +193,14 @@ pub fn (p mut Parser) close_scope() {
|
||||
|
||||
pub fn (p mut Parser) parse_block() []ast.Stmt {
|
||||
p.open_scope()
|
||||
// println('parse block')
|
||||
stmts := p.parse_block_no_scope()
|
||||
p.close_scope()
|
||||
// println('nr exprs in block = $exprs.len')
|
||||
return stmts
|
||||
}
|
||||
|
||||
pub fn (p mut Parser) parse_block_no_scope() []ast.Stmt {
|
||||
p.check(.lcbr)
|
||||
mut stmts := []ast.Stmt
|
||||
if p.tok.kind != .rcbr {
|
||||
@ -205,9 +213,6 @@ pub fn (p mut Parser) parse_block() []ast.Stmt {
|
||||
}
|
||||
}
|
||||
p.check(.rcbr)
|
||||
// println('parse block')
|
||||
p.close_scope()
|
||||
// println('nr exprs in block = $exprs.len')
|
||||
return stmts
|
||||
}
|
||||
|
||||
@ -945,15 +950,21 @@ fn (p mut Parser) dot_expr(left ast.Expr) ast.Expr {
|
||||
// p.close_scope()
|
||||
// }
|
||||
}
|
||||
// Method call
|
||||
pos := p.tok.position()
|
||||
// Method call
|
||||
if p.tok.kind == .lpar {
|
||||
p.next()
|
||||
args := p.call_args()
|
||||
mut or_stmts := []ast.Stmt
|
||||
if p.tok.kind == .key_orelse {
|
||||
p.next()
|
||||
or_stmts = p.parse_block()
|
||||
p.open_scope()
|
||||
p.scope.register_var(ast.Var{
|
||||
name: 'err'
|
||||
typ: table.type_to_optional(table.string_type)
|
||||
})
|
||||
or_stmts = p.parse_block_no_scope()
|
||||
p.close_scope()
|
||||
}
|
||||
mcall_expr := ast.MethodCallExpr{
|
||||
expr: left
|
||||
|
Loading…
Reference in New Issue
Block a user