diff --git a/vlib/builtin/option.v b/vlib/builtin/option.v index a0c64d87e7..5c7ee10182 100644 --- a/vlib/builtin/option.v +++ b/vlib/builtin/option.v @@ -26,7 +26,7 @@ pub fn (o Option) str() string { return 'Option{ data: ' + o.data[0..32].hex() + ' }' } if o.is_none { - return 'Option{ none }' + return 'Option{ none }' } return 'Option{ error: "${o.error}" }' } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e6533da5ab..3618fe73d7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -771,6 +771,9 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { } c.expected_type = table.string_type 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 return typ.typ.set_flag(.optional) } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index d943c106bb..1274e89b46 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -291,13 +291,15 @@ pub fn (mut g Gen) write_typeof_functions() { // V type to C type fn (mut g Gen) typ(t table.Type) string { mut styp := g.base_type(t) + base := styp if t.flag_is(.optional) { - // Register an optional - styp = 'Option_' + styp if t.is_ptr() { styp = styp.replace('*', '_ptr') } + styp = 'Option_' + styp + // Register an optional if it's not registered yet if styp !in g.optionals { + g.register_optional(t, base) // println(styp) x := styp // .replace('*', '_ptr') // handle option ptrs g.typedefs2.writeln('typedef Option $x;') @@ -321,6 +323,18 @@ fn (g &Gen) base_type(t table.Type) string { 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*, // i.e. it's always just Cat, not Cat_ptr: fn (g &Gen) cc_type(t table.Type) string { @@ -801,12 +815,14 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type) got_is_ptr := got_type.is_ptr() expected_is_ptr := expected_type.is_ptr() 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() 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] got_is_opt := got_type.flag_is(.optional) - if deref_will_match || got_is_opt { + if deref_will_match || got_is_opt { g.write('*') } } @@ -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.definitions.go_back(g.definitions.len - def_pos) g.write(')') - } - else { + } else { g.ident(ident) } 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') 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 { g.inside_ternary++ // g.write('/* EM ret type=${g.typ(node.return_type)} expected_type=${g.typ(node.expected_type)} */')