json: decode() part 1

pull/4665/head
Alexander Medvednikov 2020-05-01 12:02:31 +02:00
parent a0e662bef9
commit c1ee14cc3e
3 changed files with 22 additions and 46 deletions

View File

@ -12,7 +12,7 @@ struct C.cJSON {
valuestring byteptr valuestring byteptr
} }
pub fn decode() ?voidptr { pub fn decode(typ voidptr, s string) ?voidptr {
// compiler implementation // compiler implementation
return 0 return 0
} }

View File

@ -607,12 +607,10 @@ pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
mut scope := c.file.scope.innermost(call_expr.pos.pos) mut scope := c.file.scope.innermost(call_expr.pos.pos)
scope.update_var_type('it', array_info.elem_type) scope.update_var_type('it', array_info.elem_type)
} }
mut arg_type := left_type mut arg_type := left_type
for arg in call_expr.args { for arg in call_expr.args {
arg_type = c.expr(arg.expr) arg_type = c.expr(arg.expr)
} }
call_expr.return_type = left_type call_expr.return_type = left_type
call_expr.receiver_type = left_type call_expr.receiver_type = left_type
if method_name == 'map' && call_expr.args.len == 1 { if method_name == 'map' && call_expr.args.len == 1 {
@ -687,17 +685,13 @@ pub fn (mut c Checker) call_method(call_expr mut ast.CallExpr) table.Type {
return table.string_type return table.string_type
} }
// call struct field fn type // call struct field fn type
// TODO: can we use SelectorExpr for all? this dosent really belong here // TODO: can we use SelectorExpr for all?
if field := c.table.struct_find_field(left_type_sym, method_name) { if field := c.table.struct_find_field(left_type_sym, method_name) {
field_type_sym := c.table.get_type_symbol(field.typ) field_type_sym := c.table.get_type_symbol(field.typ)
if field_type_sym.kind == .function { if field_type_sym.kind == .function {
call_expr.is_method = false call_expr.is_method = false
info := field_type_sym.info as table.FnType info := field_type_sym.info as table.FnType
call_expr.return_type = info.func.return_type call_expr.return_type = info.func.return_type
// TODO: check args (do it once for all of the above)
for i, arg in call_expr.args {
arg_typ := c.expr(arg.expr)
}
return info.func.return_type return info.func.return_type
} }
} }
@ -722,6 +716,13 @@ pub fn (mut c Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
// } // }
if fn_name == 'json.encode' { if fn_name == 'json.encode' {
} }
if fn_name == 'json.decode' {
ident := call_expr.args[0].expr as ast.Ident
// sym := c.table.find_type(ident.name)
idx := c.table.find_type_idx(ident.name)
println('js.decode t=$ident.name')
return table.Type(idx)
}
// look for function in format `mod.fn` or `fn` (main/builtin) // look for function in format `mod.fn` or `fn` (main/builtin)
mut f := table.Fn{} mut f := table.Fn{}
mut found := false mut found := false
@ -1720,6 +1721,10 @@ pub fn (mut c Checker) ident(ident mut ast.Ident) table.Type {
if ident.is_c { if ident.is_c {
return table.int_type return table.int_type
} }
if c.table.known_type(ident.name) {
// e.g. `User` in `json.decode(User, '...')`
return table.void_type
}
if ident.name != '_' { if ident.name != '_' {
c.error('undefined: `$ident.name`', ident.pos) c.error('undefined: `$ident.name`', ident.pos)
} }

View File

@ -25,54 +25,25 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
if sym.name in ['int', 'string', 'bool'] { if sym.name in ['int', 'string', 'bool'] {
return return
} }
// println('gen_json_for_type( $typ.name )') // println('gen_json_for_type($typ.name)')
// Register decoder fn
/*
mut dec_fn := Fn{
mod: p.mod
typ: 'Option_$typ.name'
name: js_dec_name(t)
}
if p.table.known_fn(dec_fn.name) {
// Already registered? Skip.
return
}
// decode_TYPE funcs receive an actual cJSON* object to decode // decode_TYPE funcs receive an actual cJSON* object to decode
// cJSON_Parse(str) call is added by the compiler // cJSON_Parse(str) call is added by the compiler
arg := Var{
typ: 'cJSON*'
}
dec_fn.args << arg
p.table.register_fn(dec_fn)
// Register encoder fn
mut enc_fn := Fn{
mod: p.mod
typ: 'cJSON*'
name: js_enc_name(t)
}
// encode_TYPE funcs receive an object to encode
enc_arg := Var{
typ: t
}
enc_fn.args << enc_arg
p.table.register_fn(enc_fn)
// Code gen decoder // Code gen decoder
dec += ' dec_fn_name := js_dec_name(sym.name)
//$t $dec_fn.name (cJSON* root) { dec.writeln('
Option ${dec_fn.name}(cJSON* root, $t* res) { Option ${dec_fn_name}(cJSON* root, $styp* res) {
// $t res; // $styp res;
if (!root) { if (!root) {
const char *error_ptr = cJSON_GetErrorPtr(); const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) { if (error_ptr != NULL) {
fprintf(stderr, "Error in decode() for $t 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);
return v_error(tos2(error_ptr)); return v_error(tos2(error_ptr));
} }
} }
' ')
*/
// Code gen encoder // Code gen encoder
// encode_TYPE funcs receive an object to encode
enc_fn_name := js_enc_name(sym.name) enc_fn_name := js_enc_name(sym.name)
enc.writeln(' enc.writeln('
cJSON* ${enc_fn_name}($styp val) { cJSON* ${enc_fn_name}($styp val) {
@ -111,7 +82,7 @@ cJSON* ${enc_fn_name}($styp val) {
// p.cgen.fns << '$dec return opt_ok(res); \n}' // p.cgen.fns << '$dec return opt_ok(res); \n}'
dec.writeln('return opt_ok(res, sizeof(*res)); \n}') dec.writeln('return opt_ok(res, sizeof(*res)); \n}')
enc.writeln('\treturn o;\n}') enc.writeln('\treturn o;\n}')
// g.definitions.writeln(dec.str()) g.definitions.writeln(dec.str())
g.gowrappers.writeln(enc.str()) g.gowrappers.writeln(enc.str())
} }