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/enum_bitfield_test.v',
'vlib/v/tests/fixed_array_test.v', 'vlib/v/tests/fixed_array_test.v',
'vlib/v/tests/num_lit_call_method_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/pointers_test.v',
'vlib/v/tests/string_interpolation_variadic_test.v', 'vlib/v/tests/string_interpolation_variadic_test.v',
'vlib/v/tests/type_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 // 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))) 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 // 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))) 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) a, e := sys_mmap(0, n_bytes, mem_prot, mem_flags, -1, 0)
if e == .enoerror { if e == .enoerror {
mut ap := intptr(a) mut ap := &int(a)
*ap = pages *ap = pages
return byteptr(a+4), e return byteptr(a+4), e
} }
@ -25,7 +25,7 @@ pub fn mm_alloc(size u64) (byteptr, errno) {
} }
pub fn mm_free(addr 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) size := u64(*ap) * u64(linux_mem.page_size)
return sys_munmap(ap, 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 // V type to C type
pub fn (mut g Gen) typ(t table.Type) string { 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) nr_muls := table.type_nr_muls(t)
sym := g.table.get_type_symbol(t) sym := g.table.get_type_symbol(t)
mut styp := sym.name.replace('.', '__') 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 return styp
} }
@ -733,12 +738,10 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
// multi return // multi return
mut or_stmts := []ast.Stmt mut or_stmts := []ast.Stmt
mut return_type := table.void_type mut return_type := table.void_type
match assign_stmt.right[0] { if assign_stmt.right[0] is ast.CallExpr {
ast.CallExpr { it := assign_stmt.right[0] as ast.CallExpr
or_stmts = it.or_block.stmts or_stmts = it.or_block.stmts
return_type = it.return_type return_type = it.return_type
}
else {}
} }
is_optional := table.type_is(return_type, .optional) is_optional := table.type_is(return_type, .optional)
mr_var_name := 'mr_$assign_stmt.pos.pos' 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) g.expr(ident)
if is_optional { if is_optional {
mr_styp2 := mr_styp[7..] // remove Option_ mr_base_styp := g.base_typ(return_type)
g.writeln(' = (*(${mr_styp2}*)${mr_var_name}.data).arg$i;') g.writeln(' = (*(${mr_base_styp}*)${mr_var_name}.data).arg$i;')
} else { } else {
g.writeln(' = ${mr_var_name}.arg$i;') 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 { if is_decl {
g.write('$styp ') g.write('$styp ')
} }
g.expr(ident) g.ident(ident)
if g.autofree && right_sym.kind in [.array, .string] { if g.autofree && right_sym.kind in [.array, .string] {
if g.gen_clone_assignment(val, right_sym, true) { if g.gen_clone_assignment(val, right_sym, true) {
g.writeln(';') g.writeln(';')
@ -1554,21 +1557,18 @@ fn (mut g Gen) ident(node ast.Ident) {
g.write('_const_') g.write('_const_')
} }
name := c_name(node.name) name := c_name(node.name)
// TODO `is` if node.info is ast.IdentVar {
match node.info { ident_var := node.info as ast.IdentVar
ast.IdentVar { // x ?int
// x ?int // `x = 10` => `x.data = 10` (g.right_is_opt == false)
// `x = 10` => `x.data = 10` (g.right_is_opt == false) // `x = new_opt()` => `x = new_opt()` (g.right_is_opt == true)
// `x = new_opt()` => `x = new_opt()` (g.right_is_opt == true) // `println(x)` => `println(*(int*)x.data)`
// `println(x)` => `println(*(int*)x.data)` if ident_var.is_optional && !(g.is_assign_lhs && g.right_is_opt) {
if it.is_optional && !(g.is_assign_lhs && g.right_is_opt) { g.write('/*opt*/')
g.write('/*opt*/') styp := g.base_typ(ident_var.typ)
styp := g.typ(it.typ)[7..] // Option_int => int TODO perf? g.write('(*($styp*)${name}.data)')
g.write('(*($styp*)${name}.data)') return
return
}
} }
else {}
} }
g.write(name) g.write(name)
} }
@ -1821,14 +1821,12 @@ fn (mut g Gen) return_statement(node ast.Return) {
g.write(' ') g.write(' ')
// typ_sym := g.table.get_type_symbol(g.fn_decl.return_type) // typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
// mr_info := typ_sym.info as table.MultiReturn // 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] != if fn_return_is_optional { // && !table.type_is(node.types[0], .optional) && node.types[0] !=
styp = styp[7..] // remove 'Option_' styp = g.base_typ(g.fn_decl.return_type)
mut x := styp g.write('opt_ok(&($styp/*X*/[]) { ')
if x.ends_with('_ptr') { } else {
x = x.replace('_ptr', '*') styp = g.typ(g.fn_decl.return_type)
}
g.write('opt_ok(&($x/*X*/[]) { ')
} }
g.write('($styp){') g.write('($styp){')
for i, expr in node.exprs { for i, expr in node.exprs {
@ -1864,14 +1862,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
else {} else {}
} }
if !is_none && !is_error { if !is_none && !is_error {
styp := g.typ(g.fn_decl.return_type)[7..] // remove 'Option_' styp := g.base_typ(g.fn_decl.return_type)
mut x := styp g.write('/*:)$return_sym.name*/opt_ok(&($styp[]) { ')
if x.ends_with('_ptr') {
x = x.replace('_ptr', '*')
}
g.write('/*:)$return_sym.name*/opt_ok(&($x[]) { ')
g.expr(node.exprs[0]) g.expr(node.exprs[0])
g.writeln(' }, sizeof($x));') g.writeln(' }, sizeof($styp));')
return return
} }
// g.write('/*OPTIONAL*/') // g.write('/*OPTIONAL*/')
@ -2454,8 +2448,7 @@ fn (mut g Gen) insert_before(s string) {
// to access its fields (`.ok`, `.error` etc) // to access its fields (`.ok`, `.error` etc)
// `os.cp(...)` => `Option bool tmp = os__cp(...); if (!tmp.ok) { ... }` // `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) { fn (mut g Gen) or_block(var_name string, stmts []ast.Stmt, return_type table.Type) {
mr_styp := g.typ(return_type) mr_styp := g.base_typ(return_type)
mr_styp2 := mr_styp[7..] // remove Option_
g.writeln(';') // or') g.writeln(';') // or')
g.writeln('if (!${var_name}.ok) {') g.writeln('if (!${var_name}.ok) {')
g.writeln('\tstring err = ${var_name}.v_error;') 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 { for i, stmt in stmts {
if i == stmts.len - 1 { if i == stmts.len - 1 {
g.indent-- g.indent--
g.write('\t*(${mr_styp2}*) ${var_name}.data = ') g.write('\t*(${mr_styp}*) ${var_name}.data = ')
} }
g.stmt(stmt) g.stmt(stmt)
} }

View File

@ -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){ static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed){
const uint8_t *p=(const uint8_t *)key; const uint8_t *p=(const uint8_t *)key;
uint64_t i=len, see1=seed; uint64_t i=len, see1=seed;
start: start:
if(_likely_(i<=16)){ if(_likely_(i<=16)){
#ifndef WYHASH_CONDOM #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); 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 if (_likely_(i)) _wymix128(_wyr3(p,i)^_wyp0,_wyp1, &seed, &see1);
else _wymix128(_wyp0,_wyp1, &seed, &see1); else _wymix128(_wyp0,_wyp1, &seed, &see1);
} }
else _wymix128(_wyr8(p)^_wyp0,_wyr8(p+i-8)^_wyp1, &seed, &see1); else _wymix128(_wyr8(p)^_wyp0,_wyr8(p+i-8)^_wyp1, &seed, &see1);
#endif #endif
_wymix128(len,_wyp0, &seed, &see1); _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); _wymix128(0,0,&A,&B);
return A^B; return A^B;
} }
static inline uint64_t wyrand(uint64_t *seed){ static inline uint64_t wyrand(uint64_t *seed){
*seed+=_wyp0; *seed+=_wyp0;
uint64_t a=0, b=0; uint64_t a=0, b=0;
_wymix128(*seed,*seed^_wyp1,&a,&b); _wymix128(*seed,*seed^_wyp1,&a,&b);
return a^b; return a^b;
} }
static inline double wy2u01(uint64_t r) { static inline double wy2u01(uint64_t r) {
const double _wynorm=1.0/(1ull<<52); const double _wynorm=1.0/(1ull<<52);
return (r>>12)*_wynorm; return (r>>12)*_wynorm;
} }
static inline double wy2gau(uint64_t r) { static inline double wy2gau(uint64_t r) {
const double _wynorm=1.0/(1ull<<20); const double _wynorm=1.0/(1ull<<20);
return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0; return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0;
} }
#endif #endif
@ -335,7 +335,6 @@ typedef uint32_t rune;
typedef float f32; typedef float f32;
typedef double f64; typedef double f64;
typedef unsigned char* byteptr; typedef unsigned char* byteptr;
typedef int* intptr;
typedef void* voidptr; typedef void* voidptr;
typedef char* charptr; typedef char* charptr;
typedef struct array array; typedef struct array array;

View File

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

View File

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