cgen: unwrapped optionals

pull/4033/head
Alexander Medvednikov 2020-03-15 08:18:42 +01:00
parent 8d19ba9195
commit 8a8f50a6a0
5 changed files with 31 additions and 3 deletions

View File

@ -727,10 +727,14 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type {
typ: typ typ: typ
is_optional: table.type_is_optional(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 return typ
} }
} }
// second use, already resovled in unresovled branch // second use, already resovled in unresolved branch
else if ident.kind == .constant { else if ident.kind == .constant {
info := ident.info as ast.IdentVar info := ident.info as ast.IdentVar
return info.typ return info.typ

View File

@ -21,6 +21,7 @@ mut:
is_assign_expr bool // inside left part of assign expr (for array_set(), etc) is_assign_expr bool // inside left part of assign expr (for array_set(), etc)
is_array_set bool is_array_set bool
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc 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 { 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) { if table.type_is_optional(t) {
styp = 'Option_' + styp 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 return styp
} }

View File

@ -5,9 +5,14 @@ struct User {
// multi return structs // multi return structs
// end of definitions #endif // end of definitions #endif
typedef Option Option_int;
Option_int get_opt();
void User_foo(User* u); void User_foo(User* u);
Option_int get_opt() {
return opt_ok(& (int []) { 0 }, sizeof(int));
}
void User_foo(User* u) { void User_foo(User* u) {
int age = u->age; int age = u->age;
array_string zzz = array_repeat(new_array_from_c_array(1, 1, sizeof(string), (string[]){ 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 = 10;
user.age++; user.age++;
user.name = tos3("bob"); user.name = tos3("bob");
Option_int n = get_opt();
int a = /*opt*/(*(int*)n.data) + 3;
return 0; return 0;
} }

View File

@ -3,6 +3,10 @@ struct User {
name string name string
} }
fn get_opt() ?int {
return 0
}
fn (u &User) foo() { fn (u &User) foo() {
age := u.age age := u.age
zzz := [''].repeat(u.age) zzz := [''].repeat(u.age)
@ -13,4 +17,8 @@ fn main() {
user.age = 10 user.age = 10
user.age++ user.age++
user.name = 'bob' user.name = 'bob'
n := get_opt() or {
return
}
a := n + 3
} }

View File

@ -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)) 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 // return extra info
[inline] [inline]
pub fn type_extra(t Type) TypeExtra { pub fn type_extra(t Type) TypeExtra {