From 8a8f50a6a0efd85814bd5bc90ef08631fcf52579 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 15 Mar 2020 08:18:42 +0100 Subject: [PATCH] cgen: unwrapped optionals --- vlib/v/checker/checker.v | 6 +++++- vlib/v/gen/cgen.v | 6 +++++- vlib/v/gen/tests/3.c | 9 ++++++++- vlib/v/gen/tests/3.vv | 8 ++++++++ vlib/v/table/atypes.v | 5 +++++ 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 95c75b47e3..9238ad876f 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -727,10 +727,14 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type { typ: typ is_optional: table.type_is_optional(typ) } + // unwrap optional (`println(x)`) + if table.type_is_optional(typ) { + return table.type_clear_extra(typ) + } return typ } } - // second use, already resovled in unresovled branch + // second use, already resovled in unresolved branch else if ident.kind == .constant { info := ident.info as ast.IdentVar return info.typ diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index e77b22c892..d96a70940e 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -21,6 +21,7 @@ mut: is_assign_expr bool // inside left part of assign expr (for array_set(), etc) is_array_set bool is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc + optionals []string // to avoid duplicates TODO perf, use map } pub fn cgen(files []ast.File, table &table.Table) string { @@ -69,7 +70,10 @@ pub fn (g mut Gen) typ(t table.Type) string { } if table.type_is_optional(t) { styp = 'Option_' + styp - g.definitions.writeln('typedef Option $styp;') + if !(styp in g.optionals) { + g.definitions.writeln('typedef Option $styp;') + g.optionals << styp + } } return styp } diff --git a/vlib/v/gen/tests/3.c b/vlib/v/gen/tests/3.c index 17c7cbf5f5..abf97d5623 100644 --- a/vlib/v/gen/tests/3.c +++ b/vlib/v/gen/tests/3.c @@ -5,9 +5,14 @@ struct User { // multi return structs // end of definitions #endif - +typedef Option Option_int; +Option_int get_opt(); void User_foo(User* u); +Option_int get_opt() { + return opt_ok(& (int []) { 0 }, sizeof(int)); +} + void User_foo(User* u) { int age = u->age; array_string zzz = array_repeat(new_array_from_c_array(1, 1, sizeof(string), (string[]){ @@ -21,5 +26,7 @@ int main() { user.age = 10; user.age++; user.name = tos3("bob"); + Option_int n = get_opt(); + int a = /*opt*/(*(int*)n.data) + 3; return 0; } diff --git a/vlib/v/gen/tests/3.vv b/vlib/v/gen/tests/3.vv index b6240e48da..4ad37cfa19 100644 --- a/vlib/v/gen/tests/3.vv +++ b/vlib/v/gen/tests/3.vv @@ -3,6 +3,10 @@ struct User { name string } +fn get_opt() ?int { + return 0 +} + fn (u &User) foo() { age := u.age zzz := [''].repeat(u.age) @@ -13,4 +17,8 @@ fn main() { user.age = 10 user.age++ user.name = 'bob' + n := get_opt() or { + return + } + a := n + 3 } diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index a52f526b1f..6005721d40 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -81,6 +81,11 @@ pub fn type_deref(t Type) Type { return (int(type_extra(t))<<24) | ((nr_muls - 1)<<16) | u16(type_idx(t)) } +[inline] +pub fn type_clear_extra(t Type) Type { + return type_set_extra(t, .unset) +} + // return extra info [inline] pub fn type_extra(t Type) TypeExtra {