From fecf4ddf650564dbe4d3bcb2a083b03650042087 Mon Sep 17 00:00:00 2001 From: Enzo Baldisserri Date: Wed, 22 Apr 2020 20:12:30 +0200 Subject: [PATCH] cgen: fix optional pointers --- cmd/tools/vtest-fixed.v | 1 - vlib/builtin/bare/linuxsys_bare.v | 4 +- vlib/builtin/bare/mm_bare.v | 4 +- vlib/v/gen/cgen.v | 99 ++++++++++++++----------------- vlib/v/gen/cheaders.v | 15 +++-- vlib/v/gen/js/js.v | 3 +- vlib/v/tests/option_test.v | 22 +++---- 7 files changed, 66 insertions(+), 82 deletions(-) diff --git a/cmd/tools/vtest-fixed.v b/cmd/tools/vtest-fixed.v index 53a4937b26..8151dd457a 100644 --- a/cmd/tools/vtest-fixed.v +++ b/cmd/tools/vtest-fixed.v @@ -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', diff --git a/vlib/builtin/bare/linuxsys_bare.v b/vlib/builtin/bare/linuxsys_bare.v index e3511d1883..6ee33b654a 100644 --- a/vlib/builtin/bare/linuxsys_bare.v +++ b/vlib/builtin/bare/linuxsys_bare.v @@ -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))) } diff --git a/vlib/builtin/bare/mm_bare.v b/vlib/builtin/bare/mm_bare.v index 8248231a49..3d68e8b4df 100644 --- a/vlib/builtin/bare/mm_bare.v +++ b/vlib/builtin/bare/mm_bare.v @@ -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) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index ed8c08f832..1c35b3966e 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -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,12 +738,10 @@ 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 { - or_stmts = it.or_block.stmts - return_type = it.return_type - } - else {} + 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 } is_optional := table.type_is(return_type, .optional) mr_var_name := 'mr_$assign_stmt.pos.pos' @@ -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,21 +1557,18 @@ fn (mut g Gen) ident(node ast.Ident) { g.write('_const_') } name := c_name(node.name) - // TODO `is` - match node.info { - 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) { - g.write('/*opt*/') - styp := g.typ(it.typ)[7..] // Option_int => int TODO perf? - g.write('(*($styp*)${name}.data)') - return - } + 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 ident_var.is_optional && !(g.is_assign_lhs && g.right_is_opt) { + g.write('/*opt*/') + 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) } diff --git a/vlib/v/gen/cheaders.v b/vlib/v/gen/cheaders.v index 7ec9acabc2..2731c46c71 100644 --- a/vlib/v/gen/cheaders.v +++ b/vlib/v/gen/cheaders.v @@ -277,7 +277,7 @@ static inline void _wymix128(uint64_t A, uint64_t B, uint64_t *C, uint64_t *D){ } static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed){ const uint8_t *p=(const uint8_t *)key; - uint64_t i=len, see1=seed; + uint64_t i=len, see1=seed; start: if(_likely_(i<=16)){ #ifndef WYHASH_CONDOM @@ -289,7 +289,7 @@ static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed){ if(_likely_(i>=4)) _wymix128(_wyr4(p)^_wyp0,_wyr4(p+i-4)^_wyp1, &seed, &see1); else if (_likely_(i)) _wymix128(_wyr3(p,i)^_wyp0,_wyp1, &seed, &see1); else _wymix128(_wyp0,_wyp1, &seed, &see1); - } + } else _wymix128(_wyr8(p)^_wyp0,_wyr8(p+i-8)^_wyp1, &seed, &see1); #endif _wymix128(len,_wyp0, &seed, &see1); @@ -303,18 +303,18 @@ static inline uint64_t wyhash64(uint64_t A, uint64_t B){ _wymix128(0,0,&A,&B); return A^B; } -static inline uint64_t wyrand(uint64_t *seed){ +static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp0; uint64_t a=0, b=0; _wymix128(*seed,*seed^_wyp1,&a,&b); return a^b; } -static inline double wy2u01(uint64_t r) { - const double _wynorm=1.0/(1ull<<52); +static inline double wy2u01(uint64_t r) { + const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm; } -static inline double wy2gau(uint64_t r) { - const double _wynorm=1.0/(1ull<<20); +static inline double wy2gau(uint64_t r) { + const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0; } #endif @@ -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; diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 6a61cfd457..203a03369d 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -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_') { diff --git a/vlib/v/tests/option_test.v b/vlib/v/tests/option_test.v index 904fc10e1e..1943ad90a3 100644 --- a/vlib/v/tests/option_test.v +++ b/vlib/v/tests/option_test.v @@ -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 }