cgen: new Option part 1

pull/4888/head
Alexander Medvednikov 2020-05-13 21:59:05 +02:00
parent 9895cab51c
commit ab7bc760c6
3 changed files with 27 additions and 8 deletions

View File

@ -771,6 +771,9 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
} }
c.expected_type = table.string_type c.expected_type = table.string_type
call_expr.args[1].typ = c.expr(call_expr.args[1].expr) call_expr.args[1].typ = c.expr(call_expr.args[1].expr)
if call_expr.args[1].typ != table.string_type {
c.error('json.decode: second argument needs to be a string', call_expr.pos)
}
typ := expr as ast.Type typ := expr as ast.Type
return typ.typ.set_flag(.optional) return typ.typ.set_flag(.optional)
} }

View File

@ -291,13 +291,15 @@ pub fn (mut g Gen) write_typeof_functions() {
// V type to C type // V type to C type
fn (mut g Gen) typ(t table.Type) string { fn (mut g Gen) typ(t table.Type) string {
mut styp := g.base_type(t) mut styp := g.base_type(t)
base := styp
if t.flag_is(.optional) { if t.flag_is(.optional) {
// Register an optional
styp = 'Option_' + styp
if t.is_ptr() { if t.is_ptr() {
styp = styp.replace('*', '_ptr') styp = styp.replace('*', '_ptr')
} }
styp = 'Option_' + styp
// Register an optional if it's not registered yet
if styp !in g.optionals { if styp !in g.optionals {
g.register_optional(t, base)
// println(styp) // println(styp)
x := styp // .replace('*', '_ptr') // handle option ptrs x := styp // .replace('*', '_ptr') // handle option ptrs
g.typedefs2.writeln('typedef Option $x;') g.typedefs2.writeln('typedef Option $x;')
@ -321,6 +323,18 @@ fn (g &Gen) base_type(t table.Type) string {
return styp return styp
} }
fn (mut g Gen) register_optional(t table.Type, styp string) {
// g.typedefs2.writeln('typedef Option $x;')
no_ptr := styp.replace('*','_ptr')
g.hotcode_definitions.writeln('typedef struct {
$styp data;
string error;
int ecode;
bool ok;
bool is_none;
} Option2_$no_ptr;')
}
// cc_type returns the Cleaned Concrete Type name, *without ptr*, // cc_type returns the Cleaned Concrete Type name, *without ptr*,
// i.e. it's always just Cat, not Cat_ptr: // i.e. it's always just Cat, not Cat_ptr:
fn (g &Gen) cc_type(t table.Type) string { fn (g &Gen) cc_type(t table.Type) string {
@ -801,7 +815,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type)
got_is_ptr := got_type.is_ptr() got_is_ptr := got_type.is_ptr()
expected_is_ptr := expected_type.is_ptr() expected_is_ptr := expected_type.is_ptr()
neither_void := table.voidptr_type !in [got_type, expected_type] neither_void := table.voidptr_type !in [got_type, expected_type]
if got_is_ptr && !expected_is_ptr && neither_void && expected_sym.kind !in [.interface_, .placeholder] { if got_is_ptr && !expected_is_ptr && neither_void && expected_sym.kind !in [.interface_,
.placeholder
] {
got_deref_type := got_type.deref() got_deref_type := got_type.deref()
deref_sym := g.table.get_type_symbol(got_deref_type) deref_sym := g.table.get_type_symbol(got_deref_type)
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx] deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
@ -973,8 +989,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
g.fn_args(func.func.args, func.func.is_variadic) g.fn_args(func.func.args, func.func.is_variadic)
g.definitions.go_back(g.definitions.len - def_pos) g.definitions.go_back(g.definitions.len - def_pos)
g.write(')') g.write(')')
} } else {
else {
g.ident(ident) g.ident(ident)
} }
if g.autofree && right_sym.kind in [.array, .string] { if g.autofree && right_sym.kind in [.array, .string] {
@ -1653,7 +1668,8 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
g.writeln('// match 0') g.writeln('// match 0')
return return
} }
is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary > 0 is_expr := (node.is_expr && node.return_type != table.void_type) || g.inside_ternary >
0
if is_expr { if is_expr {
g.inside_ternary++ g.inside_ternary++
// g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */') // g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')