all: implement error interfaces (#9291)
parent
167dcc415d
commit
e9797c618a
|
@ -207,7 +207,7 @@ fn (vd VDoc) get_readme(path string) string {
|
||||||
return readme_contents
|
return readme_contents
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (vd VDoc) emit_generate_err(err Error) {
|
fn (vd VDoc) emit_generate_err(err IError) {
|
||||||
cfg := vd.cfg
|
cfg := vd.cfg
|
||||||
mut err_msg := err.msg
|
mut err_msg := err.msg
|
||||||
if err.code == 1 {
|
if err.code == 1 {
|
||||||
|
|
|
@ -16,16 +16,20 @@ pub:
|
||||||
code int
|
code int
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Option3 {
|
struct Option3 {
|
||||||
state byte
|
state byte
|
||||||
err IError
|
err IError = none__
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
const none__ = IError(&None__{})
|
||||||
fn (e IError) str() string {
|
|
||||||
return e.msg
|
struct None__ {
|
||||||
|
msg string
|
||||||
|
code int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (_ None__) str() string { return 'none' }
|
||||||
|
|
||||||
fn opt_ok3(data voidptr, mut option Option3, size int) {
|
fn opt_ok3(data voidptr, mut option Option3, size int) {
|
||||||
unsafe {
|
unsafe {
|
||||||
*option = Option3{}
|
*option = Option3{}
|
||||||
|
@ -34,16 +38,6 @@ fn opt_ok3(data voidptr, mut option Option3, size int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (o Option3) str() string {
|
|
||||||
if o.state == 0 {
|
|
||||||
return 'Option{ ok }'
|
|
||||||
}
|
|
||||||
if o.state == 1 {
|
|
||||||
return 'Option{ none }'
|
|
||||||
}
|
|
||||||
return 'Option{ err: "$o.err" }'
|
|
||||||
}
|
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn error3(message string) IError {
|
pub fn error3(message string) IError {
|
||||||
return &Error{
|
return &Error{
|
||||||
|
@ -73,13 +67,6 @@ struct Option2 {
|
||||||
// derived Option2_xxx types
|
// derived Option2_xxx types
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn (e Error) str() string {
|
|
||||||
// TODO: this should probably have a better str method,
|
|
||||||
// but this minimizes the amount of broken code after #8924
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
// `fn foo() ?Foo { return foo }` => `fn foo() ?Foo { return opt_ok(foo); }`
|
// `fn foo() ?Foo { return foo }` => `fn foo() ?Foo { return opt_ok(foo); }`
|
||||||
fn opt_ok(data voidptr, mut option Option2, size int) {
|
fn opt_ok(data voidptr, mut option Option2, size int) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -89,16 +76,6 @@ fn opt_ok(data voidptr, mut option Option2, size int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (o Option2) str() string {
|
|
||||||
if o.state == 0 {
|
|
||||||
return 'Option{ ok }'
|
|
||||||
}
|
|
||||||
if o.state == 1 {
|
|
||||||
return 'Option{ none }'
|
|
||||||
}
|
|
||||||
return 'Option{ error: "$o.err" }'
|
|
||||||
}
|
|
||||||
|
|
||||||
// error returns an optional containing the error given in `message`.
|
// error returns an optional containing the error given in `message`.
|
||||||
// `if ouch { return error('an error occurred') }`
|
// `if ouch { return error('an error occurred') }`
|
||||||
pub fn error2(message string) Option2 {
|
pub fn error2(message string) Option2 {
|
||||||
|
|
|
@ -14,7 +14,7 @@ fn do_rec_calc_send(chs []chan i64, mut sem sync.Semaphore) {
|
||||||
mut msg := ''
|
mut msg := ''
|
||||||
for {
|
for {
|
||||||
mut s := get_val_from_chan(chs[0]) or {
|
mut s := get_val_from_chan(chs[0]) or {
|
||||||
msg = err.str()
|
msg = err.msg
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s++
|
s++
|
||||||
|
|
|
@ -413,7 +413,7 @@ pub fn (mut c Checker) struct_decl(mut decl ast.StructDecl) {
|
||||||
c.check_expected(field_expr_type, field.typ) or {
|
c.check_expected(field_expr_type, field.typ) or {
|
||||||
if !(sym.kind == .interface_
|
if !(sym.kind == .interface_
|
||||||
&& c.type_implements(field_expr_type, field.typ, field.pos)) {
|
&& c.type_implements(field_expr_type, field.typ, field.pos)) {
|
||||||
c.error('incompatible initializer for field `$field.name`: $err',
|
c.error('incompatible initializer for field `$field.name`: $err.msg',
|
||||||
field.default_expr.position())
|
field.default_expr.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,7 +592,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
expr_type_sym := c.table.get_type_symbol(expr_type)
|
expr_type_sym := c.table.get_type_symbol(expr_type)
|
||||||
if expr_type != table.void_type && expr_type_sym.kind != .placeholder {
|
if expr_type != table.void_type && expr_type_sym.kind != .placeholder {
|
||||||
c.check_expected(expr_type, embed_type) or {
|
c.check_expected(expr_type, embed_type) or {
|
||||||
c.error('cannot assign to field `$info_field.name`: $err',
|
c.error('cannot assign to field `$info_field.name`: $err.msg',
|
||||||
field.pos)
|
field.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type {
|
||||||
c.type_implements(expr_type, info_field.typ, field.pos)
|
c.type_implements(expr_type, info_field.typ, field.pos)
|
||||||
} else if expr_type != table.void_type && expr_type_sym.kind != .placeholder {
|
} else if expr_type != table.void_type && expr_type_sym.kind != .placeholder {
|
||||||
c.check_expected(expr_type, info_field.typ) or {
|
c.check_expected(expr_type, info_field.typ) or {
|
||||||
c.error('cannot assign to field `$info_field.name`: $err',
|
c.error('cannot assign to field `$info_field.name`: $err.msg',
|
||||||
field.pos)
|
field.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -762,21 +762,21 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
elem_type := right.array_info().elem_type
|
elem_type := right.array_info().elem_type
|
||||||
// if left_default.kind != right_sym.kind {
|
// if left_default.kind != right_sym.kind {
|
||||||
c.check_expected(left_type, elem_type) or {
|
c.check_expected(left_type, elem_type) or {
|
||||||
c.error('left operand to `$infix_expr.op` does not match the array element type: $err',
|
c.error('left operand to `$infix_expr.op` does not match the array element type: $err.msg',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
map_info := right.map_info()
|
map_info := right.map_info()
|
||||||
c.check_expected(left_type, map_info.key_type) or {
|
c.check_expected(left_type, map_info.key_type) or {
|
||||||
c.error('left operand to `$infix_expr.op` does not match the map key type: $err',
|
c.error('left operand to `$infix_expr.op` does not match the map key type: $err.msg',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
}
|
}
|
||||||
infix_expr.left_type = map_info.key_type
|
infix_expr.left_type = map_info.key_type
|
||||||
}
|
}
|
||||||
.string {
|
.string {
|
||||||
c.check_expected(left_type, right_type) or {
|
c.check_expected(left_type, right_type) or {
|
||||||
c.error('left operand to `$infix_expr.op` does not match: $err',
|
c.error('left operand to `$infix_expr.op` does not match: $err.msg',
|
||||||
left_right_pos)
|
left_right_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,16 +923,28 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
return c.check_shift(left_type, right_type, left_pos, right_pos)
|
return c.check_shift(left_type, right_type, left_pos, right_pos)
|
||||||
}
|
}
|
||||||
.key_is, .not_is {
|
.key_is, .not_is {
|
||||||
type_expr := infix_expr.right as ast.Type
|
right_expr := infix_expr.right
|
||||||
typ_sym := c.table.get_type_symbol(type_expr.typ)
|
mut typ := match right_expr {
|
||||||
|
ast.Type {
|
||||||
|
right_expr.typ
|
||||||
|
}
|
||||||
|
ast.None {
|
||||||
|
table.none_type_idx
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c.error('invalid type `$right_expr`', right_expr.position())
|
||||||
|
table.Type(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
|
op := infix_expr.op.str()
|
||||||
if typ_sym.kind == .placeholder {
|
if typ_sym.kind == .placeholder {
|
||||||
c.error('$infix_expr.op.str(): type `$typ_sym.name` does not exist', type_expr.pos)
|
c.error('$op: type `$typ_sym.name` does not exist', right_expr.position())
|
||||||
}
|
}
|
||||||
if left.kind !in [.interface_, .sum_type] {
|
if left.kind !in [.interface_, .sum_type] {
|
||||||
c.error('`$infix_expr.op.str()` can only be used with interfaces and sum types',
|
c.error('`$op` can only be used with interfaces and sum types', infix_expr.pos)
|
||||||
infix_expr.pos)
|
|
||||||
} else if mut left.info is table.SumType {
|
} else if mut left.info is table.SumType {
|
||||||
if type_expr.typ !in left.info.variants {
|
if typ !in left.info.variants {
|
||||||
c.error('`$left.name` has no variant `$right.name`', infix_expr.pos)
|
c.error('`$left.name` has no variant `$right.name`', infix_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1411,7 +1423,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
}
|
}
|
||||||
if left_type_sym.kind == .aggregate {
|
if left_type_sym.kind == .aggregate {
|
||||||
// the error message contains the problematic type
|
// the error message contains the problematic type
|
||||||
unknown_method_msg = err
|
unknown_method_msg = err.msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if has_method {
|
if has_method {
|
||||||
|
@ -1493,7 +1505,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
// continue
|
// continue
|
||||||
// }
|
// }
|
||||||
if got_arg_typ != table.void_type {
|
if got_arg_typ != table.void_type {
|
||||||
c.error('$err in argument ${i + 1} to `${left_type_sym.name}.$method_name`',
|
c.error('$err.msg in argument ${i + 1} to `${left_type_sym.name}.$method_name`',
|
||||||
arg.pos)
|
arg.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2014,7 +2026,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
||||||
if f.generic_names.len > 0 {
|
if f.generic_names.len > 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.error('$err in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
c.error('$err.msg in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f.generic_names.len != call_expr.generic_types.len {
|
if f.generic_names.len != call_expr.generic_types.len {
|
||||||
|
@ -2043,9 +2055,24 @@ fn (mut c Checker) type_implements(typ table.Type, inter_typ table.Type, pos tok
|
||||||
utyp := c.unwrap_generic(typ)
|
utyp := c.unwrap_generic(typ)
|
||||||
typ_sym := c.table.get_type_symbol(utyp)
|
typ_sym := c.table.get_type_symbol(utyp)
|
||||||
mut inter_sym := c.table.get_type_symbol(inter_typ)
|
mut inter_sym := c.table.get_type_symbol(inter_typ)
|
||||||
|
// do not check the same type more than once
|
||||||
|
if mut inter_sym.info is table.Interface {
|
||||||
|
for t in inter_sym.info.types {
|
||||||
|
if t.idx() == utyp.idx() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
styp := c.table.type_to_str(utyp)
|
styp := c.table.type_to_str(utyp)
|
||||||
same_base_type := utyp.idx() == inter_typ.idx()
|
if utyp.idx() == inter_typ.idx() {
|
||||||
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ && !same_base_type {
|
// same type -> already casted to the interface
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if inter_typ.idx() == table.error_type_idx && utyp.idx() == table.none_type_idx {
|
||||||
|
// `none` "implements" the Error interface
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ {
|
||||||
c.error('cannot implement interface `$inter_sym.name` with a different interface `$styp`',
|
c.error('cannot implement interface `$inter_sym.name` with a different interface `$styp`',
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
|
@ -2314,7 +2341,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sym.kind in [.aggregate, .sum_type] {
|
if sym.kind in [.aggregate, .sum_type] {
|
||||||
unknown_field_msg = err
|
unknown_field_msg = err.msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !c.inside_unsafe {
|
if !c.inside_unsafe {
|
||||||
|
@ -2884,7 +2911,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
|
||||||
&& left_sym.kind != .interface_ {
|
&& left_sym.kind != .interface_ {
|
||||||
// Dual sides check (compatibility check)
|
// Dual sides check (compatibility check)
|
||||||
c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
|
c.check_expected(right_type_unwrapped, left_type_unwrapped) or {
|
||||||
c.error('cannot assign to `$left`: $err', right.position())
|
c.error('cannot assign to `$left`: $err.msg', right.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if left_sym.kind == .interface_ {
|
if left_sym.kind == .interface_ {
|
||||||
|
@ -3064,7 +3091,7 @@ pub fn (mut c Checker) array_init(mut array_init ast.ArrayInit) table.Type {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.check_expected(typ, elem_type) or {
|
c.check_expected(typ, elem_type) or {
|
||||||
c.error('invalid array element: $err', expr.position())
|
c.error('invalid array element: $err.msg', expr.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if array_init.is_fixed {
|
if array_init.is_fixed {
|
||||||
|
@ -4421,7 +4448,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
// probably any mismatch will be caught by not producing a value instead
|
// probably any mismatch will be caught by not producing a value instead
|
||||||
for st in branch.stmts[0..branch.stmts.len - 1] {
|
for st in branch.stmts[0..branch.stmts.len - 1] {
|
||||||
// must not contain C statements
|
// must not contain C statements
|
||||||
st.check_c_expr() or { c.error('`match` expression branch has $err', st.pos) }
|
st.check_c_expr() or { c.error('`match` expression branch has $err.msg', st.pos) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the last statement is an expression, return its type
|
// If the last statement is an expression, return its type
|
||||||
|
@ -5040,7 +5067,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) table.Type {
|
||||||
}
|
}
|
||||||
for st in branch.stmts {
|
for st in branch.stmts {
|
||||||
// must not contain C statements
|
// must not contain C statements
|
||||||
st.check_c_expr() or { c.error('`if` expression branch has $err', st.pos) }
|
st.check_c_expr() or { c.error('`if` expression branch has $err.msg', st.pos) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Also check for returns inside a comp.if's statements, even if its contents aren't parsed
|
// Also check for returns inside a comp.if's statements, even if its contents aren't parsed
|
||||||
|
|
|
@ -142,9 +142,7 @@ fn (mut g Gen) gen_str_for_option(typ table.Type, styp string, str_fn_name strin
|
||||||
g.type_definitions.writeln('string indent_${str_fn_name}($styp it, int indent_count); // auto')
|
g.type_definitions.writeln('string indent_${str_fn_name}($styp it, int indent_count); // auto')
|
||||||
g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp it, int indent_count) {')
|
g.auto_str_funcs.writeln('string indent_${str_fn_name}($styp it, int indent_count) {')
|
||||||
g.auto_str_funcs.writeln('\tstring res;')
|
g.auto_str_funcs.writeln('\tstring res;')
|
||||||
g.auto_str_funcs.writeln('\tif (it.state == 1) {')
|
g.auto_str_funcs.writeln('\tif (it.state == 0) {')
|
||||||
g.auto_str_funcs.writeln('\t\tres = _SLIT("none");')
|
|
||||||
g.auto_str_funcs.writeln('\t} else if (it.state == 0) {')
|
|
||||||
if sym.kind == .string {
|
if sym.kind == .string {
|
||||||
g.auto_str_funcs.writeln('\t\tres = _STR("\'%.*s\\000\'", 2, ${parent_str_fn_name}(*($sym.cname*)it.data));')
|
g.auto_str_funcs.writeln('\t\tres = _STR("\'%.*s\\000\'", 2, ${parent_str_fn_name}(*($sym.cname*)it.data));')
|
||||||
} else if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
} else if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||||
|
@ -153,7 +151,7 @@ fn (mut g Gen) gen_str_for_option(typ table.Type, styp string, str_fn_name strin
|
||||||
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*($sym.cname*)it.data);')
|
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*($sym.cname*)it.data);')
|
||||||
}
|
}
|
||||||
g.auto_str_funcs.writeln('\t} else {')
|
g.auto_str_funcs.writeln('\t} else {')
|
||||||
g.auto_str_funcs.writeln('\t\tres = _STR("error: \'%.*s\\000\'", 2, it.err.msg);')
|
g.auto_str_funcs.writeln('\t\tres = _STR("error: %.*s\\000", 2, indent_IError_str(it.err, indent_count));')
|
||||||
g.auto_str_funcs.writeln('\t}')
|
g.auto_str_funcs.writeln('\t}')
|
||||||
g.auto_str_funcs.writeln('\treturn _STR("Option(%.*s\\000)", 2, res);')
|
g.auto_str_funcs.writeln('\treturn _STR("Option(%.*s\\000)", 2, res);')
|
||||||
g.auto_str_funcs.writeln('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
|
|
|
@ -569,7 +569,7 @@ fn (mut g Gen) expr_string(expr ast.Expr) string {
|
||||||
// if one location changes
|
// if one location changes
|
||||||
fn (mut g Gen) optional_type_name(t table.Type) (string, string) {
|
fn (mut g Gen) optional_type_name(t table.Type) (string, string) {
|
||||||
base := g.base_type(t)
|
base := g.base_type(t)
|
||||||
mut styp := 'Option2_$base'
|
mut styp := 'Option3_$base'
|
||||||
if t.is_ptr() {
|
if t.is_ptr() {
|
||||||
styp = styp.replace('*', '_ptr')
|
styp = styp.replace('*', '_ptr')
|
||||||
}
|
}
|
||||||
|
@ -581,7 +581,7 @@ fn (g &Gen) optional_type_text(styp string, base string) string {
|
||||||
size := if base == 'void' { 'byte' } else { base }
|
size := if base == 'void' { 'byte' } else { base }
|
||||||
ret := 'struct $styp {
|
ret := 'struct $styp {
|
||||||
byte state;
|
byte state;
|
||||||
Error err;
|
IError err;
|
||||||
byte data[sizeof($size)];
|
byte data[sizeof($size)];
|
||||||
}'
|
}'
|
||||||
return ret
|
return ret
|
||||||
|
@ -652,13 +652,10 @@ fn (mut g Gen) register_chan_pop_optional_call(opt_el_type string, styp string)
|
||||||
if opt_el_type !in g.chan_pop_optionals {
|
if opt_el_type !in g.chan_pop_optionals {
|
||||||
g.chan_pop_optionals << opt_el_type
|
g.chan_pop_optionals << opt_el_type
|
||||||
g.channel_definitions.writeln('
|
g.channel_definitions.writeln('
|
||||||
static inline $opt_el_type __Option2_${styp}_popval($styp ch) {
|
static inline $opt_el_type __Option3_${styp}_popval($styp ch) {
|
||||||
$opt_el_type _tmp = {0};
|
$opt_el_type _tmp = {0};
|
||||||
if (sync__Channel_try_pop_priv(ch, _tmp.data, false)) {
|
if (sync__Channel_try_pop_priv(ch, _tmp.data, false)) {
|
||||||
Option2 _tmp2 = error2(_SLIT("channel closed"));
|
return ($opt_el_type){ .state = 2, .err = error3(_SLIT("channel closed")) };
|
||||||
$opt_el_type _tmp3;
|
|
||||||
memcpy(&_tmp3, &_tmp2, sizeof(Option2));
|
|
||||||
return _tmp3;
|
|
||||||
}
|
}
|
||||||
return _tmp;
|
return _tmp;
|
||||||
}')
|
}')
|
||||||
|
@ -669,14 +666,11 @@ fn (mut g Gen) register_chan_push_optional_call(el_type string, styp string) {
|
||||||
if styp !in g.chan_push_optionals {
|
if styp !in g.chan_push_optionals {
|
||||||
g.chan_push_optionals << styp
|
g.chan_push_optionals << styp
|
||||||
g.channel_definitions.writeln('
|
g.channel_definitions.writeln('
|
||||||
static inline Option2_void __Option2_${styp}_pushval($styp ch, $el_type e) {
|
static inline Option3_void __Option3_${styp}_pushval($styp ch, $el_type e) {
|
||||||
if (sync__Channel_try_push_priv(ch, &e, false)) {
|
if (sync__Channel_try_push_priv(ch, &e, false)) {
|
||||||
Option2 _tmp2 = error2(_SLIT("channel closed"));
|
return (Option3_void){ .state = 2, .err = error3(_SLIT("channel closed")) };
|
||||||
Option2_void _tmp3;
|
|
||||||
memcpy(&_tmp3, &_tmp2, sizeof(Option2));
|
|
||||||
return _tmp3;
|
|
||||||
}
|
}
|
||||||
return (Option2_void){0};
|
return (Option3_void){0};
|
||||||
}')
|
}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -913,10 +907,10 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) {
|
||||||
sym := g.table.get_type_symbol(stmt.typ)
|
sym := g.table.get_type_symbol(stmt.typ)
|
||||||
if sym.name in ['Option2', 'Option3'] || stmt.expr is ast.None {
|
if sym.name in ['Option2', 'Option3'] || stmt.expr is ast.None {
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
g.write('Option2 $tmp = ')
|
g.write('Option3 $tmp = (Option3){.state = 0,.err = ')
|
||||||
g.expr(stmt.expr)
|
g.expr(stmt.expr)
|
||||||
g.writeln(';')
|
g.writeln('};')
|
||||||
g.writeln('memcpy(&$tmp_var, &$tmp, sizeof(Option2));')
|
g.writeln('memcpy(&$tmp_var, &$tmp, sizeof(Option3));')
|
||||||
} else {
|
} else {
|
||||||
mut styp := g.base_type(stmt.typ)
|
mut styp := g.base_type(stmt.typ)
|
||||||
$if tinyc && x32 && windows {
|
$if tinyc && x32 && windows {
|
||||||
|
@ -926,9 +920,9 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) {
|
||||||
styp = 'f64'
|
styp = 'f64'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.write('opt_ok(&($styp[]) { ')
|
g.write('opt_ok3(&($styp[]) { ')
|
||||||
g.stmt(stmt)
|
g.stmt(stmt)
|
||||||
g.writeln(' }, (Option2*)(&$tmp_var), sizeof($styp));')
|
g.writeln(' }, (Option3*)(&$tmp_var), sizeof($styp));')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1602,8 +1596,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw table.Type, expected_t
|
||||||
// allow using the new Error struct as a string, to avoid a breaking change
|
// allow using the new Error struct as a string, to avoid a breaking change
|
||||||
// TODO: temporary to allow people to migrate their code; remove soon
|
// TODO: temporary to allow people to migrate their code; remove soon
|
||||||
if got_type == table.error_type_idx && expected_type == table.string_type_idx {
|
if got_type == table.error_type_idx && expected_type == table.string_type_idx {
|
||||||
|
g.write('(*(')
|
||||||
g.expr(expr)
|
g.expr(expr)
|
||||||
g.write('.msg')
|
g.write('.msg))')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if exp_sym.kind == .interface_ && got_type_raw.idx() != expected_type.idx()
|
if exp_sym.kind == .interface_ && got_type_raw.idx() != expected_type.idx()
|
||||||
|
@ -2801,7 +2796,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
g.map_init(node)
|
g.map_init(node)
|
||||||
}
|
}
|
||||||
ast.None {
|
ast.None {
|
||||||
g.write('(Option2){.state = 1, .err = (Error){.msg = _SLIT(""), .code = 0,}}')
|
g.write('_const_none__')
|
||||||
}
|
}
|
||||||
ast.OrExpr {
|
ast.OrExpr {
|
||||||
// this should never appear here
|
// this should never appear here
|
||||||
|
@ -2852,7 +2847,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
if gen_or {
|
if gen_or {
|
||||||
opt_elem_type := g.typ(elem_type.set_flag(.optional))
|
opt_elem_type := g.typ(elem_type.set_flag(.optional))
|
||||||
g.register_chan_pop_optional_call(opt_elem_type, styp)
|
g.register_chan_pop_optional_call(opt_elem_type, styp)
|
||||||
g.write('$opt_elem_type $tmp_opt = __Option2_${styp}_popval(')
|
g.write('$opt_elem_type $tmp_opt = __Option3_${styp}_popval(')
|
||||||
} else {
|
} else {
|
||||||
g.write('__${styp}_popval(')
|
g.write('__${styp}_popval(')
|
||||||
}
|
}
|
||||||
|
@ -3409,7 +3404,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
if gen_or {
|
if gen_or {
|
||||||
elem_styp := g.typ(elem_type)
|
elem_styp := g.typ(elem_type)
|
||||||
g.register_chan_push_optional_call(elem_styp, styp)
|
g.register_chan_push_optional_call(elem_styp, styp)
|
||||||
g.write('Option2_void $tmp_opt = __Option2_${styp}_pushval(')
|
g.write('Option3_void $tmp_opt = __Option3_${styp}_pushval(')
|
||||||
} else {
|
} else {
|
||||||
g.write('__${styp}_pushval(')
|
g.write('__${styp}_pushval(')
|
||||||
}
|
}
|
||||||
|
@ -3719,9 +3714,13 @@ fn (mut g Gen) match_expr_sumtype(node ast.MatchExpr, is_expr bool, cond_var str
|
||||||
g.write('${dot_or_ptr}_typ == ')
|
g.write('${dot_or_ptr}_typ == ')
|
||||||
g.expr(branch.exprs[sumtype_index])
|
g.expr(branch.exprs[sumtype_index])
|
||||||
} else if sym.kind == .interface_ {
|
} else if sym.kind == .interface_ {
|
||||||
typ := branch.exprs[sumtype_index] as ast.Type
|
if branch.exprs[sumtype_index] is ast.Type {
|
||||||
branch_sym := g.table.get_type_symbol(typ.typ)
|
typ := branch.exprs[sumtype_index] as ast.Type
|
||||||
g.write('${dot_or_ptr}_interface_idx == _${sym.cname}_${branch_sym.cname}_index')
|
branch_sym := g.table.get_type_symbol(typ.typ)
|
||||||
|
g.write('${dot_or_ptr}_interface_idx == _${sym.cname}_${branch_sym.cname}_index')
|
||||||
|
} else if branch.exprs[sumtype_index] is ast.None && sym.name == 'IError' {
|
||||||
|
g.write('${dot_or_ptr}_interface_idx == _IError_None___index')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if is_expr && tmp_var.len == 0 {
|
if is_expr && tmp_var.len == 0 {
|
||||||
g.write(') ? ')
|
g.write(') ? ')
|
||||||
|
@ -4227,7 +4226,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||||
// define `err` only for simple `if val := opt {...} else {`
|
// define `err` only for simple `if val := opt {...} else {`
|
||||||
if is_guard && guard_idx == i - 1 {
|
if is_guard && guard_idx == i - 1 {
|
||||||
cvar_name := guard_vars[guard_idx]
|
cvar_name := guard_vars[guard_idx]
|
||||||
g.writeln('\tError err = ${cvar_name}.err;')
|
g.writeln('\tIError err = ${cvar_name}.err;')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match branch.cond {
|
match branch.cond {
|
||||||
|
@ -4344,27 +4343,17 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
ftyp := g.typ(node.types[0])
|
ftyp := g.typ(node.types[0])
|
||||||
mut is_regular_option := ftyp in ['Option2', 'Option3']
|
mut is_regular_option := ftyp in ['Option2', 'Option3']
|
||||||
if optional_none || is_regular_option {
|
if optional_none || is_regular_option {
|
||||||
tmp := g.new_tmp_var()
|
|
||||||
g.write('Option2 $tmp = ')
|
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
|
||||||
g.writeln(';')
|
|
||||||
styp := g.typ(g.fn_decl.return_type)
|
styp := g.typ(g.fn_decl.return_type)
|
||||||
err_obj := g.new_tmp_var()
|
g.write('return ($styp){ .state=2, .err=')
|
||||||
g.writeln('$styp $err_obj;')
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
g.writeln('memcpy(&$err_obj, &$tmp, sizeof(Option2));')
|
g.writeln(' };')
|
||||||
g.writeln('return $err_obj;')
|
|
||||||
return
|
return
|
||||||
} else if node.types[0] == table.error_type_idx {
|
} else if node.types[0] == table.error_type_idx {
|
||||||
// foo() or { return err }
|
// foo() or { return err }
|
||||||
tmp := g.new_tmp_var()
|
|
||||||
g.write('Option2 $tmp = (Option2){.state=2, .err=')
|
|
||||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
|
||||||
g.writeln('};')
|
|
||||||
styp := g.typ(g.fn_decl.return_type)
|
styp := g.typ(g.fn_decl.return_type)
|
||||||
err_obj := g.new_tmp_var()
|
g.write('return ($styp){.state=2, .err=')
|
||||||
g.writeln('$styp $err_obj;')
|
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||||
g.writeln('memcpy(&$err_obj, &$tmp, sizeof(Option2));')
|
g.writeln(' };')
|
||||||
g.writeln('return $err_obj;')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4381,7 +4370,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
opt_tmp = g.new_tmp_var()
|
opt_tmp = g.new_tmp_var()
|
||||||
g.writeln('$opt_type $opt_tmp;')
|
g.writeln('$opt_type $opt_tmp;')
|
||||||
styp = g.base_type(g.fn_decl.return_type)
|
styp = g.base_type(g.fn_decl.return_type)
|
||||||
g.write('opt_ok(&($styp/*X*/[]) { ')
|
g.write('opt_ok3(&($styp/*X*/[]) { ')
|
||||||
} else {
|
} else {
|
||||||
g.write('return ')
|
g.write('return ')
|
||||||
styp = g.typ(g.fn_decl.return_type)
|
styp = g.typ(g.fn_decl.return_type)
|
||||||
|
@ -4439,7 +4428,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
}
|
}
|
||||||
g.write('}')
|
g.write('}')
|
||||||
if fn_return_is_optional {
|
if fn_return_is_optional {
|
||||||
g.writeln(' }, (Option2*)(&$opt_tmp), sizeof($styp));')
|
g.writeln(' }, (Option3*)(&$opt_tmp), sizeof($styp));')
|
||||||
g.write('return $opt_tmp')
|
g.write('return $opt_tmp')
|
||||||
}
|
}
|
||||||
// Make sure to add our unpacks
|
// Make sure to add our unpacks
|
||||||
|
@ -4465,7 +4454,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
// Create a tmp for this option
|
// Create a tmp for this option
|
||||||
opt_tmp := g.new_tmp_var()
|
opt_tmp := g.new_tmp_var()
|
||||||
g.writeln('$opt_type $opt_tmp;')
|
g.writeln('$opt_type $opt_tmp;')
|
||||||
g.write('opt_ok(&($styp[]) { ')
|
g.write('opt_ok3(&($styp[]) { ')
|
||||||
if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() {
|
if !g.fn_decl.return_type.is_ptr() && node.types[0].is_ptr() {
|
||||||
if !(node.exprs[0] is ast.Ident && !g.is_amp) {
|
if !(node.exprs[0] is ast.Ident && !g.is_amp) {
|
||||||
g.write('*')
|
g.write('*')
|
||||||
|
@ -4477,7 +4466,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g.writeln(' }, (Option2*)(&$opt_tmp), sizeof($styp));')
|
g.writeln(' }, (Option3*)(&$opt_tmp), sizeof($styp));')
|
||||||
g.writeln('return $opt_tmp;')
|
g.writeln('return $opt_tmp;')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -4585,7 +4574,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
if val.starts_with('Option2_') {
|
if val.starts_with('Option3_') {
|
||||||
g.inits[field.mod].writeln(val)
|
g.inits[field.mod].writeln(val)
|
||||||
unwrap_option := field.expr.or_block.kind != .absent
|
unwrap_option := field.expr.or_block.kind != .absent
|
||||||
g.const_decl_init_later(field.mod, name, g.current_tmp_var(), field.typ,
|
g.const_decl_init_later(field.mod, name, g.current_tmp_var(), field.typ,
|
||||||
|
@ -4614,6 +4603,9 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, val string, typ ta
|
||||||
// Initialize more complex consts in `void _vinit/2{}`
|
// Initialize more complex consts in `void _vinit/2{}`
|
||||||
// (C doesn't allow init expressions that can't be resolved at compile time).
|
// (C doesn't allow init expressions that can't be resolved at compile time).
|
||||||
mut styp := g.typ(typ)
|
mut styp := g.typ(typ)
|
||||||
|
if styp == 'Option2' {
|
||||||
|
styp = 'IError'
|
||||||
|
}
|
||||||
cname := '_const_$name'
|
cname := '_const_$name'
|
||||||
g.definitions.writeln('$styp $cname; // inited later')
|
g.definitions.writeln('$styp $cname; // inited later')
|
||||||
if cname == '_const_os__args' {
|
if cname == '_const_os__args' {
|
||||||
|
@ -5268,7 +5260,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||||
is_none_ok := mr_styp == 'void'
|
is_none_ok := mr_styp == 'void'
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
if is_none_ok {
|
if is_none_ok {
|
||||||
g.writeln('if (${cvar_name}.state == 2) {')
|
g.writeln('if (${cvar_name}.state != 0 && ${cvar_name}.err._interface_idx != _IError_None___index) {')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('if (${cvar_name}.state != 0) { /*or block*/ ')
|
g.writeln('if (${cvar_name}.state != 0) { /*or block*/ ')
|
||||||
}
|
}
|
||||||
|
@ -5276,7 +5268,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||||
if g.inside_or_block {
|
if g.inside_or_block {
|
||||||
g.writeln('\terr = ${cvar_name}.err;')
|
g.writeln('\terr = ${cvar_name}.err;')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('\tError err = ${cvar_name}.err;')
|
g.writeln('\tIError err = ${cvar_name}.err;')
|
||||||
}
|
}
|
||||||
g.inside_or_block = true
|
g.inside_or_block = true
|
||||||
defer {
|
defer {
|
||||||
|
@ -5312,7 +5304,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||||
// In main(), an `opt()?` call is sugar for `opt() or { panic(err) }`
|
// In main(), an `opt()?` call is sugar for `opt() or { panic(err) }`
|
||||||
if g.pref.is_debug {
|
if g.pref.is_debug {
|
||||||
paline, pafile, pamod, pafn := g.panic_debug_info(or_block.pos)
|
paline, pafile, pamod, pafn := g.panic_debug_info(or_block.pos)
|
||||||
g.writeln('panic_debug($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), ${cvar_name}.err.msg );')
|
g.writeln('panic_debug($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), *${cvar_name}.err.msg );')
|
||||||
} else {
|
} else {
|
||||||
g.writeln('\tv_panic(_STR("optional not set (%.*s\\000)", 2, ${cvar_name}.err.msg));')
|
g.writeln('\tv_panic(_STR("optional not set (%.*s\\000)", 2, ${cvar_name}.err.msg));')
|
||||||
}
|
}
|
||||||
|
@ -5331,7 +5323,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
||||||
styp := g.typ(g.fn_decl.return_type)
|
styp := g.typ(g.fn_decl.return_type)
|
||||||
err_obj := g.new_tmp_var()
|
err_obj := g.new_tmp_var()
|
||||||
g.writeln('\t$styp $err_obj;')
|
g.writeln('\t$styp $err_obj;')
|
||||||
g.writeln('\tmemcpy(&$err_obj, &$cvar_name, sizeof(Option2));')
|
g.writeln('\tmemcpy(&$err_obj, &$cvar_name, sizeof(Option3));')
|
||||||
g.writeln('\treturn $err_obj;')
|
g.writeln('\treturn $err_obj;')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5782,8 +5774,12 @@ fn (mut g Gen) is_expr(node ast.InfixExpr) {
|
||||||
if sym.kind == .interface_ {
|
if sym.kind == .interface_ {
|
||||||
g.write('_interface_idx $eq ')
|
g.write('_interface_idx $eq ')
|
||||||
// `_Animal_Dog_index`
|
// `_Animal_Dog_index`
|
||||||
sub_type := node.right as ast.Type
|
sub_type := match mut node.right {
|
||||||
sub_sym := g.table.get_type_symbol(sub_type.typ)
|
ast.Type { node.right.typ }
|
||||||
|
ast.None { g.table.type_idxs['None__'] }
|
||||||
|
else { table.Type(0) }
|
||||||
|
}
|
||||||
|
sub_sym := g.table.get_type_symbol(sub_type)
|
||||||
g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index')
|
g.write('_${c_name(sym.name)}_${c_name(sub_sym.name)}_index')
|
||||||
return
|
return
|
||||||
} else if sym.kind == .sum_type {
|
} else if sym.kind == .sum_type {
|
||||||
|
|
|
@ -141,7 +141,7 @@ pub fn (mut g Gen) gen_failing_error_propagation_for_test_fn(or_block ast.OrExpr
|
||||||
// `or { cb_propagate_test_error(@LINE, @FILE, @MOD, @FN, err.msg) }`
|
// `or { cb_propagate_test_error(@LINE, @FILE, @MOD, @FN, err.msg) }`
|
||||||
// and the test is considered failed
|
// and the test is considered failed
|
||||||
paline, pafile, pamod, pafn := g.panic_debug_info(or_block.pos)
|
paline, pafile, pamod, pafn := g.panic_debug_info(or_block.pos)
|
||||||
g.writeln('\tmain__cb_propagate_test_error($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), ${cvar_name}.err.msg );')
|
g.writeln('\tmain__cb_propagate_test_error($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), *(${cvar_name}.err.msg) );')
|
||||||
g.writeln('\tg_test_fails++;')
|
g.writeln('\tg_test_fails++;')
|
||||||
g.writeln('\tlongjmp(g_jump_buffer, 1);')
|
g.writeln('\tlongjmp(g_jump_buffer, 1);')
|
||||||
}
|
}
|
||||||
|
|
|
@ -720,10 +720,10 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
mut name := node.name
|
mut name := node.name
|
||||||
if node.name == 'error' {
|
if node.name == 'error' {
|
||||||
name = 'error2'
|
name = 'error3'
|
||||||
}
|
}
|
||||||
if node.name == 'error_with_code' {
|
if node.name == 'error_with_code' {
|
||||||
name = 'error_with_code2'
|
name = 'error_with_code3'
|
||||||
}
|
}
|
||||||
is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic']
|
is_print := name in ['print', 'println', 'eprint', 'eprintln', 'panic']
|
||||||
print_method := name
|
print_method := name
|
||||||
|
@ -773,7 +773,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||||
g.is_js_call = false
|
g.is_js_call = false
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
tmp2 = g.new_tmp_var()
|
tmp2 = g.new_tmp_var()
|
||||||
g.writeln('Option2_$typ $tmp2 = $fn_name ($json_obj);')
|
g.writeln('Option3_$typ $tmp2 = $fn_name ($json_obj);')
|
||||||
}
|
}
|
||||||
if !g.is_autofree {
|
if !g.is_autofree {
|
||||||
g.write('cJSON_Delete($json_obj); //del')
|
g.write('cJSON_Delete($json_obj); //del')
|
||||||
|
|
|
@ -247,7 +247,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym table.TypeSymbol) {
|
||||||
g.writeln('if ($tmp_opt_ptr) {')
|
g.writeln('if ($tmp_opt_ptr) {')
|
||||||
g.writeln('\t*(($elem_type_str*)&${tmp_opt}.data) = *(($elem_type_str*)$tmp_opt_ptr);')
|
g.writeln('\t*(($elem_type_str*)&${tmp_opt}.data) = *(($elem_type_str*)$tmp_opt_ptr);')
|
||||||
g.writeln('} else {')
|
g.writeln('} else {')
|
||||||
g.writeln('\t${tmp_opt}.state = 2; ${tmp_opt}.err = (Error){.msg=_SLIT("array index out of range"), .code=0};')
|
g.writeln('\t${tmp_opt}.state = 2; ${tmp_opt}.err = error3(_SLIT("array index out of range"));')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if !node.is_option {
|
if !node.is_option {
|
||||||
g.or_block(tmp_opt, node.or_expr, elem_type)
|
g.or_block(tmp_opt, node.or_expr, elem_type)
|
||||||
|
@ -414,8 +414,7 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym table.TypeSymbol) {
|
||||||
g.writeln('if ($tmp_opt_ptr) {')
|
g.writeln('if ($tmp_opt_ptr) {')
|
||||||
g.writeln('\t*(($elem_type_str*)&${tmp_opt}.data) = *(($elem_type_str*)$tmp_opt_ptr);')
|
g.writeln('\t*(($elem_type_str*)&${tmp_opt}.data) = *(($elem_type_str*)$tmp_opt_ptr);')
|
||||||
g.writeln('} else {')
|
g.writeln('} else {')
|
||||||
g.writeln('\t${tmp_opt}.state = 2; ${tmp_opt}.err = (Error){.msg=_SLIT("array index out of range"), .code=0};')
|
g.writeln('\t${tmp_opt}.state = 2; ${tmp_opt}.err = error3(_SLIT("array index out of range"));')
|
||||||
|
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if !node.is_option {
|
if !node.is_option {
|
||||||
g.or_block(tmp_opt, node.or_expr, elem_type)
|
g.or_block(tmp_opt, node.or_expr, elem_type)
|
||||||
|
|
|
@ -41,7 +41,7 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
|
||||||
dec_fn_name := js_dec_name(styp)
|
dec_fn_name := js_dec_name(styp)
|
||||||
// Make sure that this optional type actually exists
|
// Make sure that this optional type actually exists
|
||||||
g.register_optional(utyp)
|
g.register_optional(utyp)
|
||||||
dec_fn_dec := 'Option2_$styp ${dec_fn_name}(cJSON* root)'
|
dec_fn_dec := 'Option3_$styp ${dec_fn_name}(cJSON* root)'
|
||||||
dec.writeln('
|
dec.writeln('
|
||||||
$dec_fn_dec {
|
$dec_fn_dec {
|
||||||
$styp res;
|
$styp res;
|
||||||
|
@ -50,8 +50,7 @@ $dec_fn_dec {
|
||||||
if (error_ptr != NULL) {
|
if (error_ptr != NULL) {
|
||||||
// fprintf(stderr, "Error in decode() for $styp error_ptr=: %s\\n", error_ptr);
|
// fprintf(stderr, "Error in decode() for $styp error_ptr=: %s\\n", error_ptr);
|
||||||
// printf("\\nbad js=%%s\\n", js.str);
|
// printf("\\nbad js=%%s\\n", js.str);
|
||||||
Option2 err = error2(tos2(error_ptr));
|
return (Option3_$styp){.state = 2,.err = error3(tos2(error_ptr))};
|
||||||
return *(Option2_$styp *)&err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
')
|
')
|
||||||
|
@ -102,8 +101,8 @@ $enc_fn_dec {
|
||||||
}
|
}
|
||||||
// cJSON_delete
|
// cJSON_delete
|
||||||
// p.cgen.fns << '$dec return opt_ok(res); \n}'
|
// p.cgen.fns << '$dec return opt_ok(res); \n}'
|
||||||
dec.writeln('\tOption2_$styp ret;')
|
dec.writeln('\tOption3_$styp ret;')
|
||||||
dec.writeln('\topt_ok(&res, (Option2*)&ret, sizeof(res));')
|
dec.writeln('\topt_ok3(&res, (Option3*)&ret, sizeof(res));')
|
||||||
dec.writeln('\treturn ret;\n}')
|
dec.writeln('\treturn ret;\n}')
|
||||||
enc.writeln('\treturn o;\n}')
|
enc.writeln('\treturn o;\n}')
|
||||||
g.definitions.writeln(dec.str())
|
g.definitions.writeln(dec.str())
|
||||||
|
@ -152,18 +151,18 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
|
||||||
} else {
|
} else {
|
||||||
g.gen_json_for_type(field.typ)
|
g.gen_json_for_type(field.typ)
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
dec.writeln('\tOption2_$field_type $tmp = $dec_name (js_get(root,"$name"));')
|
dec.writeln('\tOption3_$field_type $tmp = $dec_name (js_get(root,"$name"));')
|
||||||
dec.writeln('\tif(${tmp}.state != 0) {')
|
dec.writeln('\tif(${tmp}.state != 0) {')
|
||||||
dec.writeln('\t\treturn *(Option2_$styp*) &$tmp;')
|
dec.writeln('\t\treturn *(Option3_$styp*) &$tmp;')
|
||||||
dec.writeln('\t}')
|
dec.writeln('\t}')
|
||||||
dec.writeln('\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;')
|
dec.writeln('\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// dec.writeln(' $dec_name (js_get(root, "$name"), & (res . $field.name));')
|
// dec.writeln(' $dec_name (js_get(root, "$name"), & (res . $field.name));')
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
dec.writeln('\tOption2_$field_type $tmp = $dec_name (js_get(root,"$name"));')
|
dec.writeln('\tOption3_$field_type $tmp = $dec_name (js_get(root,"$name"));')
|
||||||
dec.writeln('\tif(${tmp}.state != 0) {')
|
dec.writeln('\tif(${tmp}.state != 0) {')
|
||||||
dec.writeln('\t\treturn *(Option2_$styp*) &$tmp;')
|
dec.writeln('\t\treturn *(Option3_$styp*) &$tmp;')
|
||||||
dec.writeln('\t}')
|
dec.writeln('\t}')
|
||||||
dec.writeln('\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;')
|
dec.writeln('\tres.${c_name(field.name)} = *($field_type*) ${tmp}.data;')
|
||||||
}
|
}
|
||||||
|
@ -215,18 +214,17 @@ fn (mut g Gen) decode_array(value_type table.Type) string {
|
||||||
s = '$styp val = ${fn_name}(jsval); '
|
s = '$styp val = ${fn_name}(jsval); '
|
||||||
} else {
|
} else {
|
||||||
s = '
|
s = '
|
||||||
Option2_$styp val2 = $fn_name (jsval);
|
Option3_$styp val2 = $fn_name (jsval);
|
||||||
if(val2.state != 0) {
|
if(val2.state != 0) {
|
||||||
array_free(&res);
|
array_free(&res);
|
||||||
return *(Option2_Array_$styp*)&val2;
|
return *(Option3_Array_$styp*)&val2;
|
||||||
}
|
}
|
||||||
$styp val = *($styp*)val2.data;
|
$styp val = *($styp*)val2.data;
|
||||||
'
|
'
|
||||||
}
|
}
|
||||||
return '
|
return '
|
||||||
if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) {
|
if(root && !cJSON_IsArray(root) && !cJSON_IsNull(root)) {
|
||||||
Option2 err = error2( string_add(_SLIT("Json element is not an array: "), tos2(cJSON_PrintUnformatted(root))) );
|
return (Option3_Array_$styp){.state = 2, .err = error3(string_add(_SLIT("Json element is not an array: "), tos2(cJSON_PrintUnformatted(root))))};
|
||||||
return *(Option2_Array_$styp *)&err;
|
|
||||||
}
|
}
|
||||||
res = __new_array(0, 0, sizeof($styp));
|
res = __new_array(0, 0, sizeof($styp));
|
||||||
const cJSON *jsval = NULL;
|
const cJSON *jsval = NULL;
|
||||||
|
@ -260,18 +258,17 @@ fn (mut g Gen) decode_map(key_type table.Type, value_type table.Type) string {
|
||||||
s = '$styp_v val = $fn_name_v (js_get(root, jsval->string));'
|
s = '$styp_v val = $fn_name_v (js_get(root, jsval->string));'
|
||||||
} else {
|
} else {
|
||||||
s = '
|
s = '
|
||||||
Option2_$styp_v val2 = $fn_name_v (js_get(root, jsval->string));
|
Option3_$styp_v val2 = $fn_name_v (js_get(root, jsval->string));
|
||||||
if(val2.state != 0) {
|
if(val2.state != 0) {
|
||||||
map_free(&res);
|
map_free(&res);
|
||||||
return *(Option2_Map_${styp}_$styp_v*)&val2;
|
return *(Option3_Map_${styp}_$styp_v*)&val2;
|
||||||
}
|
}
|
||||||
$styp_v val = *($styp_v*)val2.data;
|
$styp_v val = *($styp_v*)val2.data;
|
||||||
'
|
'
|
||||||
}
|
}
|
||||||
return '
|
return '
|
||||||
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
|
if(!cJSON_IsObject(root) && !cJSON_IsNull(root)) {
|
||||||
Option2 err = error2( string_add(_SLIT("Json element is not an object: "), tos2(cJSON_PrintUnformatted(root))) );
|
return (Option3_Map_${styp}_$styp_v){ .state = 2, .err = error3( string_add(_SLIT("Json element is not an object: "), tos2(cJSON_PrintUnformatted(root))) )};
|
||||||
return *(Option2_Map_${styp}_$styp_v *)&err;
|
|
||||||
}
|
}
|
||||||
res = new_map_2(sizeof($styp), sizeof($styp_v), $hash_fn, $key_eq_fn, $clone_fn, $free_fn);
|
res = new_map_2(sizeof($styp), sizeof($styp_v), $hash_fn, $key_eq_fn, $clone_fn, $free_fn);
|
||||||
cJSON *jsval = NULL;
|
cJSON *jsval = NULL;
|
||||||
|
|
|
@ -88,7 +88,7 @@ fn main() {
|
||||||
println(message)
|
println(message)
|
||||||
})
|
})
|
||||||
hl.raw_js_log()
|
hl.raw_js_log()
|
||||||
propagation() or { println(err.msg) }
|
propagation() or { println(err) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn anon_consumer(greeting string, anon fn (message string)) {
|
fn anon_consumer(greeting string, anon fn (message string)) {
|
||||||
|
|
|
@ -30,7 +30,8 @@ pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []
|
||||||
'tos2',
|
'tos2',
|
||||||
'tos3',
|
'tos3',
|
||||||
'isnil',
|
'isnil',
|
||||||
'opt_ok',
|
'opt_ok3',
|
||||||
|
'error3',
|
||||||
// utf8_str_visible_length is used by c/str.v
|
// utf8_str_visible_length is used by c/str.v
|
||||||
'utf8_str_visible_length',
|
'utf8_str_visible_length',
|
||||||
'compare_ints',
|
'compare_ints',
|
||||||
|
|
|
@ -235,9 +235,7 @@ fn (mut w Walker) expr(node ast.Expr) {
|
||||||
w.stmts(b.stmts)
|
w.stmts(b.stmts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.None {
|
ast.None {}
|
||||||
w.mark_fn_as_used('opt_none2')
|
|
||||||
}
|
|
||||||
ast.ParExpr {
|
ast.ParExpr {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -551,7 +551,7 @@ pub fn (mut t Table) register_builtin_type_symbols() {
|
||||||
return_type: table.void_type
|
return_type: table.void_type
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
t.register_type_symbol(kind: .struct_, name: 'Error', cname: 'Error', mod: 'builtin')
|
t.register_type_symbol(kind: .interface_, name: 'IError', cname: 'IError', mod: 'builtin')
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
|
|
@ -296,7 +296,12 @@ fn create_option_err() ?string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_option_err() {
|
fn test_option_err() {
|
||||||
assert '$create_option_err()' == 'Option(error: \'this is an error\')'
|
assert '$create_option_err()' == "
|
||||||
|
Option(error: IError(Error{
|
||||||
|
msg: 'this is an error'
|
||||||
|
code: 0
|
||||||
|
}))
|
||||||
|
".trim_space()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_option_none() ?string {
|
fn create_option_none() ?string {
|
||||||
|
@ -304,7 +309,7 @@ fn create_option_none() ?string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_option_none() {
|
fn test_option_none() {
|
||||||
assert '$create_option_none()' == 'Option(none)'
|
assert '$create_option_none()' == 'Option(error: IError(none))'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_option_string() ?string {
|
fn create_option_string() ?string {
|
||||||
|
|
Loading…
Reference in New Issue