cgen: fix optional pointers

pull/4553/head
Enzo Baldisserri 2020-04-22 20:12:30 +02:00 committed by GitHub
parent 54c382f6f1
commit fecf4ddf65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 82 deletions

View File

@ -18,7 +18,6 @@ const (
'vlib/v/tests/enum_bitfield_test.v',
'vlib/v/tests/fixed_array_test.v',
'vlib/v/tests/num_lit_call_method_test.v',
'vlib/v/tests/option_test.v',
'vlib/v/tests/pointers_test.v',
'vlib/v/tests/string_interpolation_variadic_test.v',
'vlib/v/tests/type_test.v',

View File

@ -363,7 +363,7 @@ pub fn sys_munmap(addr voidptr, len u64) errno {
}
// 22 sys_pipe int *filedes
pub fn sys_pipe(filedes intptr) errno {
pub fn sys_pipe(filedes &int) errno {
return errno(sys_call1(22, u64(filedes)))
}
@ -415,7 +415,7 @@ pub fn sys_getuid() int {
}
// 247 sys_waitid int which pid_t upid struct siginfo *infop int options struct rusage *ru
pub fn sys_waitid (which wi_which, pid int, infop intptr, options wp_sys, ru voidptr) errno {
pub fn sys_waitid (which wi_which, pid int, infop &int, options wp_sys, ru voidptr) errno {
return errno(sys_call5(247, u64(which), u64(pid), u64(infop), u64(options), u64(ru)))
}

View File

@ -17,7 +17,7 @@ pub fn mm_alloc(size u64) (byteptr, errno) {
a, e := sys_mmap(0, n_bytes, mem_prot, mem_flags, -1, 0)
if e == .enoerror {
mut ap := intptr(a)
mut ap := &int(a)
*ap = pages
return byteptr(a+4), e
}
@ -25,7 +25,7 @@ pub fn mm_alloc(size u64) (byteptr, errno) {
}
pub fn mm_free(addr byteptr) errno {
ap := intptr(addr-4)
ap := &int(addr-4)
size := u64(*ap) * u64(linux_mem.page_size)
return sys_munmap(ap, size)

View File

@ -228,6 +228,24 @@ pub fn (mut g Gen) write_typeof_functions() {
// V type to C type
pub fn (mut g Gen) typ(t table.Type) string {
mut styp := g.base_typ(t)
if table.type_is(t, .optional) {
// Register an optional
styp = 'Option_' + styp
if table.type_is_ptr(t) {
styp = styp.replace('*', '_ptr')
}
if !(styp in g.optionals) {
// println(styp)
x := styp // .replace('*', '_ptr') // handle option ptrs
g.typedefs2.writeln('typedef Option $x;')
g.optionals << styp
}
}
return styp
}
pub fn (mut g Gen) base_typ(t table.Type) string {
nr_muls := table.type_nr_muls(t)
sym := g.table.get_type_symbol(t)
mut styp := sym.name.replace('.', '__')
@ -243,19 +261,6 @@ pub fn (mut g Gen) typ(t table.Type) string {
}
}
}
if table.type_is(t, .optional) {
// Register an optional
styp = 'Option_' + styp
if table.type_is_ptr(t) {
styp = styp.replace('*', '_ptr')
}
if !(styp in g.optionals) {
// println(styp)
x := styp // .replace('*', '_ptr') // handle option ptrs
g.typedefs2.writeln('typedef Option $x;')
g.optionals << styp
}
}
return styp
}
@ -733,13 +738,11 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
// multi return
mut or_stmts := []ast.Stmt
mut return_type := table.void_type
match assign_stmt.right[0] {
ast.CallExpr {
if assign_stmt.right[0] is ast.CallExpr {
it := assign_stmt.right[0] as ast.CallExpr
or_stmts = it.or_block.stmts
return_type = it.return_type
}
else {}
}
is_optional := table.type_is(return_type, .optional)
mr_var_name := 'mr_$assign_stmt.pos.pos'
mr_styp := g.typ(return_type)
@ -762,8 +765,8 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
}
g.expr(ident)
if is_optional {
mr_styp2 := mr_styp[7..] // remove Option_
g.writeln(' = (*(${mr_styp2}*)${mr_var_name}.data).arg$i;')
mr_base_styp := g.base_typ(return_type)
g.writeln(' = (*(${mr_base_styp}*)${mr_var_name}.data).arg$i;')
} else {
g.writeln(' = ${mr_var_name}.arg$i;')
}
@ -819,7 +822,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
if is_decl {
g.write('$styp ')
}
g.expr(ident)
g.ident(ident)
if g.autofree && right_sym.kind in [.array, .string] {
if g.gen_clone_assignment(val, right_sym, true) {
g.writeln(';')
@ -1554,22 +1557,19 @@ fn (mut g Gen) ident(node ast.Ident) {
g.write('_const_')
}
name := c_name(node.name)
// TODO `is`
match node.info {
ast.IdentVar {
if node.info is ast.IdentVar {
ident_var := node.info as ast.IdentVar
// x ?int
// `x = 10` => `x.data = 10` (g.right_is_opt == false)
// `x = new_opt()` => `x = new_opt()` (g.right_is_opt == true)
// `println(x)` => `println(*(int*)x.data)`
if it.is_optional && !(g.is_assign_lhs && g.right_is_opt) {
if ident_var.is_optional && !(g.is_assign_lhs && g.right_is_opt) {
g.write('/*opt*/')
styp := g.typ(it.typ)[7..] // Option_int => int TODO perf?
styp := g.base_typ(ident_var.typ)
g.write('(*($styp*)${name}.data)')
return
}
}
else {}
}
g.write(name)
}
@ -1821,14 +1821,12 @@ fn (mut g Gen) return_statement(node ast.Return) {
g.write(' ')
// typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
// mr_info := typ_sym.info as table.MultiReturn
mut styp := g.typ(g.fn_decl.return_type)
mut styp := ''
if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] !=
styp = styp[7..] // remove 'Option_'
mut x := styp
if x.ends_with('_ptr') {
x = x.replace('_ptr', '*')
}
g.write('opt_ok(&($x/*X*/[]) { ')
styp = g.base_typ(g.fn_decl.return_type)
g.write('opt_ok(&($styp/*X*/[]) { ')
} else {
styp = g.typ(g.fn_decl.return_type)
}
g.write('($styp){')
for i, expr in node.exprs {
@ -1864,14 +1862,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
else {}
}
if !is_none && !is_error {
styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_'
mut x := styp
if x.ends_with('_ptr') {
x = x.replace('_ptr', '*')
}
g.write('/*:)$return_sym.name*/opt_ok(&($x[]) { ')
styp := g.base_typ(g.fn_decl.return_type)
g.write('/*:)$return_sym.name*/opt_ok(&($styp[]) { ')
g.expr(node.exprs[0])
g.writeln(' }, sizeof($x));')
g.writeln(' }, sizeof($styp));')
return
}
// g.write('/*OPTIONAL*/')
@ -2454,8 +2448,7 @@ fn (mut g Gen) insert_before(s string) {
// to access its fields (`.ok`, `.error` etc)
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }`
fn (mut g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) {
mr_styp := g.typ(return_type)
mr_styp2 := mr_styp[7..] // remove Option_
mr_styp := g.base_typ(return_type)
g.writeln(';') // or')
g.writeln('if (!${var_name}.ok) {')
g.writeln('\tstring err = ${var_name}.v_error;')
@ -2466,7 +2459,7 @@ fn (mut g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Typ
for i, stmt in stmts {
if i == stmts.len - 1 {
g.indent--
g.write('\t*(${mr_styp2}*) ${var_name}.data = ')
g.write('\t*(${mr_styp}*) ${var_name}.data = ')
}
g.stmt(stmt)
}

View File

@ -335,7 +335,6 @@ typedef uint32_t rune;
typedef float f32;
typedef double f64;
typedef unsigned char* byteptr;
typedef int* intptr;
typedef void* voidptr;
typedef char* charptr;
typedef struct array array;

View File

@ -184,7 +184,8 @@ fn (g mut JsGen) to_js_typ(typ string) string {
}
'charptr' {
styp = 'string'
} else {
}
else {
if typ.starts_with('array_') {
styp = g.to_js_typ(typ.replace('array_', '')) + '[]'
} else if typ.starts_with('map_') {

View File

@ -38,16 +38,14 @@ fn ret_none() ?int {
}
fn test_option_for_base_type_without_variable() {
val := err_call(true) or {
panic(err)
mut val := err_call(true) or {
assert false
0
}
assert val == 42
println('hm')
val2 := ret_none() or {
println('yep')
val = ret_none() or {
return
}
println('$val2 should have been `none`')
assert false
// This is invalid:
// x := 5 or {
@ -60,7 +58,6 @@ fn test_if_opt() {
assert val == 42
}
assert 1 == 1
println('nice')
}
fn for_opt_default() ?string {
@ -135,24 +132,19 @@ fn test_opt_field() {
fn opt_ptr(a &int) ?&int {
if isnil(a) {
return none
}
//
else {
}
return a
}
fn test_opt_ptr() {
a := 3
r1 := opt_ptr(&a) or {
mut r := opt_ptr(&a) or {
&int(0)
}
assert r1 == &a
r2 := opt_ptr(&int(0)) or {
assert r == &a
r = opt_ptr(&int(0)) or {
return
}
println('`$r2` should be none')
assert false
}