json: encode
parent
a9a8f8c804
commit
1185f04868
|
@ -13,6 +13,7 @@ struct C.cJSON {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode() voidptr {
|
pub fn decode() voidptr {
|
||||||
|
// compiler implementation
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,51 +130,51 @@ fn jsdecode_bool(root &C.cJSON) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ///////////////////
|
// ///////////////////
|
||||||
fn jsencode_int(val int) &C.cJSON {
|
fn encode_int(val int) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_i8(val i8) &C.cJSON {
|
fn encode_i8(val i8) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_i16(val i16) &C.cJSON {
|
fn encode_i16(val i16) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_i64(val i64) &C.cJSON {
|
fn encode_i64(val i64) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_byte(val byte) &C.cJSON {
|
fn encode_byte(val byte) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_u16(val u16) &C.cJSON {
|
fn encode_u16(val u16) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_u32(val u32) &C.cJSON {
|
fn encode_u32(val u32) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_u64(val u64) &C.cJSON {
|
fn encode_u64(val u64) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_f32(val f32) &C.cJSON {
|
fn encode_f32(val f32) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_f64(val f64) &C.cJSON {
|
fn encode_f64(val f64) &C.cJSON {
|
||||||
return C.cJSON_CreateNumber(val)
|
return C.cJSON_CreateNumber(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_bool(val bool) &C.cJSON {
|
fn encode_bool(val bool) &C.cJSON {
|
||||||
return C.cJSON_CreateBool(val)
|
return C.cJSON_CreateBool(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn jsencode_string(val string) &C.cJSON {
|
fn encode_string(val string) &C.cJSON {
|
||||||
return C.cJSON_CreateString(val.str)
|
return C.cJSON_CreateString(val.str)
|
||||||
}
|
}
|
||||||
// ///////////////////////
|
// ///////////////////////
|
||||||
|
|
|
@ -60,6 +60,7 @@ mut:
|
||||||
str_types []string // types that need automatic str() generation
|
str_types []string // types that need automatic str() generation
|
||||||
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
threaded_fns []string // for generating unique wrapper types and fns for `go xxx()`
|
||||||
array_fn_definitions []string // array equality functions that have been defined
|
array_fn_definitions []string // array equality functions that have been defined
|
||||||
|
is_json_fn bool // inside json.encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1935,49 +1936,6 @@ fn (g mut Gen) assoc(node ast.Assoc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
|
||||||
is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len -
|
|
||||||
1], .variadic)
|
|
||||||
mut arg_no := 0
|
|
||||||
for arg in args {
|
|
||||||
if is_variadic && arg_no == expected_types.len - 1 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// some c fn definitions dont have args (cfns.v) or are not updated in checker
|
|
||||||
// when these are fixed we wont need this check
|
|
||||||
if arg_no < expected_types.len {
|
|
||||||
g.ref_or_deref_arg(arg, expected_types[arg_no])
|
|
||||||
} else {
|
|
||||||
g.expr(arg.expr)
|
|
||||||
}
|
|
||||||
if arg_no < args.len - 1 || is_variadic {
|
|
||||||
g.write(', ')
|
|
||||||
}
|
|
||||||
arg_no++
|
|
||||||
}
|
|
||||||
if is_variadic {
|
|
||||||
varg_type := expected_types[expected_types.len - 1]
|
|
||||||
struct_name := 'varg_' + g.typ(varg_type).replace('*', '_ptr')
|
|
||||||
variadic_count := args.len - arg_no
|
|
||||||
varg_type_str := int(varg_type).str()
|
|
||||||
if variadic_count > g.variadic_args[varg_type_str] {
|
|
||||||
g.variadic_args[varg_type_str] = variadic_count
|
|
||||||
}
|
|
||||||
g.write('($struct_name){.len=$variadic_count,.args={')
|
|
||||||
if variadic_count > 0 {
|
|
||||||
for j in arg_no .. args.len {
|
|
||||||
g.ref_or_deref_arg(args[j], varg_type)
|
|
||||||
if j < args.len - 1 {
|
|
||||||
g.write(', ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.write('0')
|
|
||||||
}
|
|
||||||
g.write('}}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (g mut Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &table.TypeSymbol) {
|
fn (g mut Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &table.TypeSymbol) {
|
||||||
g.array_fn_definitions << ptr_typ
|
g.array_fn_definitions << ptr_typ
|
||||||
g.definitions.writeln('bool ${ptr_typ}_arr_eq(array_${ptr_typ} a, array_${ptr_typ} b) {')
|
g.definitions.writeln('bool ${ptr_typ}_arr_eq(array_${ptr_typ} a, array_${ptr_typ} b) {')
|
||||||
|
@ -1999,32 +1957,6 @@ fn (g mut Gen) generate_array_equality_fn(ptr_typ string, styp table.Type, sym &
|
||||||
g.definitions.writeln('}')
|
g.definitions.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
|
||||||
fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
|
||||||
arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs
|
|
||||||
expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs
|
|
||||||
if arg.is_mut && !arg_is_ptr {
|
|
||||||
g.write('&/*mut*/')
|
|
||||||
} else if arg_is_ptr && !expr_is_ptr {
|
|
||||||
if arg.is_mut {
|
|
||||||
sym := g.table.get_type_symbol(expected_type)
|
|
||||||
if sym.kind == .array {
|
|
||||||
// Special case for mutable arrays. We can't `&` function
|
|
||||||
// results, have to use `(array[]){ expr }[0]` hack.
|
|
||||||
g.write('&/*111*/(array[]){')
|
|
||||||
g.expr(arg.expr)
|
|
||||||
g.write('}[0]')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.write('&/*qq*/')
|
|
||||||
} else if !arg_is_ptr && expr_is_ptr {
|
|
||||||
// Dereference a pointer if a value is required
|
|
||||||
g.write('*/*d*/')
|
|
||||||
}
|
|
||||||
g.expr_with_cast(arg.expr, arg.typ, expected_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verror(s string) {
|
fn verror(s string) {
|
||||||
util.verror('cgen error', s)
|
util.verror('cgen error', s)
|
||||||
}
|
}
|
||||||
|
@ -2377,182 +2309,6 @@ fn (g mut Gen) insert_before(s string) {
|
||||||
g.write(cur_line)
|
g.write(cur_line)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) call_expr(node ast.CallExpr) {
|
|
||||||
gen_or := !g.is_assign_rhs && node.or_block.stmts.len > 0
|
|
||||||
tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
|
|
||||||
if gen_or {
|
|
||||||
styp := g.typ(node.return_type)
|
|
||||||
g.write('$styp $tmp_opt = ')
|
|
||||||
}
|
|
||||||
if node.is_method {
|
|
||||||
g.method_call(node)
|
|
||||||
} else {
|
|
||||||
g.fn_call(node)
|
|
||||||
}
|
|
||||||
if gen_or {
|
|
||||||
g.or_block(tmp_opt, node.or_block.stmts, node.return_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (g mut Gen) method_call(node ast.CallExpr) {
|
|
||||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
|
||||||
if node.left_type == 0 {
|
|
||||||
verror('method receiver type is 0, this means there are some uchecked exprs')
|
|
||||||
}
|
|
||||||
typ_sym := g.table.get_type_symbol(node.receiver_type)
|
|
||||||
// rec_sym := g.table.get_type_symbol(node.receiver_type)
|
|
||||||
mut receiver_name := typ_sym.name
|
|
||||||
if typ_sym.kind == .array && node.name == 'filter' {
|
|
||||||
g.gen_filter(node)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO performance, detect `array` method differently
|
|
||||||
if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many',
|
|
||||||
'trim', 'first', 'last', 'clone', 'reverse', 'slice'] {
|
|
||||||
// && rec_sym.name == 'array' {
|
|
||||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
|
||||||
// `array_byte_clone` => `array_clone`
|
|
||||||
receiver_name = 'array'
|
|
||||||
if node.name in ['last', 'first'] {
|
|
||||||
return_type_str := g.typ(node.return_type)
|
|
||||||
g.write('*($return_type_str*)')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
name := '${receiver_name}_$node.name'.replace('.', '__')
|
|
||||||
// if node.receiver_type != 0 {
|
|
||||||
// g.write('/*${g.typ(node.receiver_type)}*/')
|
|
||||||
// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
|
|
||||||
// }
|
|
||||||
g.write('${name}(')
|
|
||||||
if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) {
|
|
||||||
// The receiver is a reference, but the caller provided a value
|
|
||||||
// Add `&` automatically.
|
|
||||||
// TODO same logic in call_args()
|
|
||||||
g.write('&')
|
|
||||||
} else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) {
|
|
||||||
g.write('/*rec*/*')
|
|
||||||
}
|
|
||||||
g.expr(node.left)
|
|
||||||
is_variadic := node.expected_arg_types.len > 0 && table.type_is(node.expected_arg_types[node.expected_arg_types.len -
|
|
||||||
1], .variadic)
|
|
||||||
if node.args.len > 0 || is_variadic {
|
|
||||||
g.write(', ')
|
|
||||||
}
|
|
||||||
// /////////
|
|
||||||
/*
|
|
||||||
if name.contains('subkeys') {
|
|
||||||
println('call_args $name $node.arg_types.len')
|
|
||||||
for t in node.arg_types {
|
|
||||||
sym := g.table.get_type_symbol(t)
|
|
||||||
print('$sym.name ')
|
|
||||||
}
|
|
||||||
println('')
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// ///////
|
|
||||||
g.call_args(node.args, node.expected_arg_types)
|
|
||||||
g.write(')')
|
|
||||||
// if node.or_block.stmts.len > 0 {
|
|
||||||
// g.or_block(node.or_block.stmts, node.return_type)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (g mut Gen) fn_call(node ast.CallExpr) {
|
|
||||||
mut name := node.name
|
|
||||||
is_print := name == 'println' || name == 'print'
|
|
||||||
print_method := if name == 'println' { 'println' } else { 'print' }
|
|
||||||
if node.is_c {
|
|
||||||
// Skip "C."
|
|
||||||
g.is_c_call = true
|
|
||||||
name = name[2..].replace('.', '__')
|
|
||||||
} else {
|
|
||||||
name = c_name(name)
|
|
||||||
}
|
|
||||||
// Generate tmp vars for values that have to be freed.
|
|
||||||
/*
|
|
||||||
mut tmps := []string
|
|
||||||
for arg in node.args {
|
|
||||||
if arg.typ == table.string_type_idx || is_print {
|
|
||||||
tmp := g.new_tmp_var()
|
|
||||||
tmps << tmp
|
|
||||||
g.write('string $tmp = ')
|
|
||||||
g.expr(arg.expr)
|
|
||||||
g.writeln('; //memory')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if is_print && node.args[0].typ != table.string_type {
|
|
||||||
typ := node.args[0].typ
|
|
||||||
mut styp := g.typ(typ)
|
|
||||||
sym := g.table.get_type_symbol(typ)
|
|
||||||
if table.type_is_ptr(typ) {
|
|
||||||
styp = styp.replace('*', '')
|
|
||||||
}
|
|
||||||
g.gen_str_for_type(sym, styp)
|
|
||||||
if g.autofree && !table.type_is(typ, .optional) {
|
|
||||||
// Create a temporary variable so that the value can be freed
|
|
||||||
tmp := g.new_tmp_var()
|
|
||||||
// tmps << tmp
|
|
||||||
g.write('string $tmp = ${styp}_str(')
|
|
||||||
g.expr(node.args[0].expr)
|
|
||||||
g.writeln('); ${print_method}($tmp); string_free($tmp); //MEM2 $styp')
|
|
||||||
} else {
|
|
||||||
expr := node.args[0].expr
|
|
||||||
is_var := match expr {
|
|
||||||
ast.SelectorExpr {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
ast.Ident {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if table.type_is_ptr(typ) && sym.kind != .struct_ {
|
|
||||||
// ptr_str() for pointers
|
|
||||||
styp = 'ptr'
|
|
||||||
}
|
|
||||||
if sym.kind == .enum_ {
|
|
||||||
if is_var {
|
|
||||||
g.write('${print_method}(${styp}_str(')
|
|
||||||
} else {
|
|
||||||
// when no var, print string directly
|
|
||||||
g.write('${print_method}(tos3("')
|
|
||||||
}
|
|
||||||
if table.type_is_ptr(typ) {
|
|
||||||
// dereference
|
|
||||||
g.write('*')
|
|
||||||
}
|
|
||||||
g.enum_expr(expr)
|
|
||||||
if !is_var {
|
|
||||||
// end of string
|
|
||||||
g.write('"')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.write('${print_method}(${styp}_str(')
|
|
||||||
if table.type_is_ptr(typ) && sym.kind == .struct_ {
|
|
||||||
// dereference
|
|
||||||
g.write('*')
|
|
||||||
}
|
|
||||||
g.expr(expr)
|
|
||||||
if sym.kind == .struct_ && styp != 'ptr' && !sym.has_method('str') {
|
|
||||||
g.write(', 0') // trailing 0 is initial struct indent count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.write('))')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.write('${name}(')
|
|
||||||
g.call_args(node.args, node.expected_arg_types)
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
// if node.or_block.stmts.len > 0 {
|
|
||||||
// g.or_block(node.or_block.stmts, node.return_type)
|
|
||||||
// }
|
|
||||||
g.is_c_call = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user is accessing the return value eg. in assigment, pass the variable name.
|
// If user is accessing the return value eg. in assigment, pass the variable name.
|
||||||
// If the user is not using the optional return value. We need to pass a temp var
|
// If the user is not using the optional return value. We need to pass a temp var
|
||||||
// to access its fields (`.ok`, `.error` etc)
|
// to access its fields (`.ok`, `.error` etc)
|
||||||
|
@ -3044,35 +2800,29 @@ fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
|
||||||
g.gen_str_for_struct(it, styp)
|
g.gen_str_for_struct(it, styp)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
verror('could not generate string method for type \'${styp}\'')
|
verror("could not generate string method for type \'${styp}\'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (g mut Gen) gen_str_default(sym table.TypeSymbol, styp string) {
|
fn (g mut Gen) gen_str_default(sym table.TypeSymbol, styp string) {
|
||||||
|
|
||||||
mut convertor := ''
|
mut convertor := ''
|
||||||
mut typename := ''
|
mut typename := ''
|
||||||
if sym.parent_idx in table.integer_type_idxs {
|
if sym.parent_idx in table.integer_type_idxs {
|
||||||
convertor = 'int'
|
convertor = 'int'
|
||||||
typename = 'int'
|
typename = 'int'
|
||||||
}
|
} else if sym.parent_idx == table.f32_type_idx {
|
||||||
else if sym.parent_idx == table.f32_type_idx {
|
|
||||||
convertor = 'float'
|
convertor = 'float'
|
||||||
typename = 'f32'
|
typename = 'f32'
|
||||||
}
|
} else if sym.parent_idx == table.f64_type_idx {
|
||||||
else if sym.parent_idx == table.f64_type_idx {
|
|
||||||
convertor = 'double'
|
convertor = 'double'
|
||||||
typename = 'f64'
|
typename = 'f64'
|
||||||
}
|
} else if sym.parent_idx == table.bool_type_idx {
|
||||||
else if sym.parent_idx == table.bool_type_idx {
|
|
||||||
convertor = 'bool'
|
convertor = 'bool'
|
||||||
typename = 'bool'
|
typename = 'bool'
|
||||||
|
} else {
|
||||||
|
verror("could not generate string method for type \'${styp}\'")
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
verror('could not generate string method for type \'${styp}\'')
|
|
||||||
}
|
|
||||||
|
|
||||||
g.definitions.writeln('string ${styp}_str($styp it) {')
|
g.definitions.writeln('string ${styp}_str($styp it) {')
|
||||||
if convertor == 'bool' {
|
if convertor == 'bool' {
|
||||||
g.definitions.writeln('\tstring tmp1 = string_add(tos3("${styp}("), (${convertor})it ? tos3("true") : tos3("false"));')
|
g.definitions.writeln('\tstring tmp1 = string_add(tos3("${styp}("), (${convertor})it ? tos3("true") : tos3("false"));')
|
||||||
|
|
263
vlib/v/gen/fn.v
263
vlib/v/gen/fn.v
|
@ -160,3 +160,266 @@ fn (g mut Gen) fn_args(args []table.Arg, is_variadic bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
|
gen_or := !g.is_assign_rhs && node.or_block.stmts.len > 0
|
||||||
|
tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
|
||||||
|
if gen_or {
|
||||||
|
styp := g.typ(node.return_type)
|
||||||
|
g.write('$styp $tmp_opt = ')
|
||||||
|
}
|
||||||
|
if node.is_method {
|
||||||
|
g.method_call(node)
|
||||||
|
} else {
|
||||||
|
g.fn_call(node)
|
||||||
|
}
|
||||||
|
if gen_or {
|
||||||
|
g.or_block(tmp_opt, node.or_block.stmts, node.return_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) method_call(node ast.CallExpr) {
|
||||||
|
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||||
|
if node.left_type == 0 {
|
||||||
|
verror('method receiver type is 0, this means there are some uchecked exprs')
|
||||||
|
}
|
||||||
|
typ_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
|
// rec_sym := g.table.get_type_symbol(node.receiver_type)
|
||||||
|
mut receiver_name := typ_sym.name
|
||||||
|
if typ_sym.kind == .array && node.name == 'filter' {
|
||||||
|
g.gen_filter(node)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// TODO performance, detect `array` method differently
|
||||||
|
if typ_sym.kind == .array && node.name in ['repeat', 'sort_with_compare', 'free', 'push_many',
|
||||||
|
'trim', 'first', 'last', 'clone', 'reverse', 'slice'] {
|
||||||
|
// && rec_sym.name == 'array' {
|
||||||
|
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||||
|
// `array_byte_clone` => `array_clone`
|
||||||
|
receiver_name = 'array'
|
||||||
|
if node.name in ['last', 'first'] {
|
||||||
|
return_type_str := g.typ(node.return_type)
|
||||||
|
g.write('*($return_type_str*)')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name := '${receiver_name}_$node.name'.replace('.', '__')
|
||||||
|
// if node.receiver_type != 0 {
|
||||||
|
// g.write('/*${g.typ(node.receiver_type)}*/')
|
||||||
|
// g.write('/*expr_type=${g.typ(node.left_type)} rec type=${g.typ(node.receiver_type)}*/')
|
||||||
|
// }
|
||||||
|
g.write('${name}(')
|
||||||
|
if table.type_is_ptr(node.receiver_type) && !table.type_is_ptr(node.left_type) {
|
||||||
|
// The receiver is a reference, but the caller provided a value
|
||||||
|
// Add `&` automatically.
|
||||||
|
// TODO same logic in call_args()
|
||||||
|
g.write('&')
|
||||||
|
} else if !table.type_is_ptr(node.receiver_type) && table.type_is_ptr(node.left_type) {
|
||||||
|
g.write('/*rec*/*')
|
||||||
|
}
|
||||||
|
g.expr(node.left)
|
||||||
|
is_variadic := node.expected_arg_types.len > 0 && table.type_is(node.expected_arg_types[node.expected_arg_types.len -
|
||||||
|
1], .variadic)
|
||||||
|
if node.args.len > 0 || is_variadic {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
|
// /////////
|
||||||
|
/*
|
||||||
|
if name.contains('subkeys') {
|
||||||
|
println('call_args $name $node.arg_types.len')
|
||||||
|
for t in node.arg_types {
|
||||||
|
sym := g.table.get_type_symbol(t)
|
||||||
|
print('$sym.name ')
|
||||||
|
}
|
||||||
|
println('')
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// ///////
|
||||||
|
g.call_args(node.args, node.expected_arg_types)
|
||||||
|
g.write(')')
|
||||||
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
|
mut name := node.name
|
||||||
|
is_print := name == 'println' || name == 'print'
|
||||||
|
print_method := if name == 'println' { 'println' } else { 'print' }
|
||||||
|
g.is_json_fn = name == 'json.encode'
|
||||||
|
mut json_type_str := ''
|
||||||
|
if g.is_json_fn {
|
||||||
|
g.write('json__json_print(')
|
||||||
|
g.gen_json_for_type(node.args[0].typ)
|
||||||
|
println('XAXAXAX')
|
||||||
|
json_type_str = g.table.get_type_symbol(node.args[0].typ).name
|
||||||
|
}
|
||||||
|
if node.is_c {
|
||||||
|
// Skip "C."
|
||||||
|
g.is_c_call = true
|
||||||
|
name = name[2..].replace('.', '__')
|
||||||
|
} else {
|
||||||
|
name = c_name(name)
|
||||||
|
}
|
||||||
|
if g.is_json_fn {
|
||||||
|
// `json__decode` => `json__decode_User`
|
||||||
|
name += '_' + json_type_str
|
||||||
|
}
|
||||||
|
// Generate tmp vars for values that have to be freed.
|
||||||
|
/*
|
||||||
|
mut tmps := []string
|
||||||
|
for arg in node.args {
|
||||||
|
if arg.typ == table.string_type_idx || is_print {
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
tmps << tmp
|
||||||
|
g.write('string $tmp = ')
|
||||||
|
g.expr(arg.expr)
|
||||||
|
g.writeln('; //memory')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if is_print && node.args[0].typ != table.string_type {
|
||||||
|
typ := node.args[0].typ
|
||||||
|
mut styp := g.typ(typ)
|
||||||
|
sym := g.table.get_type_symbol(typ)
|
||||||
|
if table.type_is_ptr(typ) {
|
||||||
|
styp = styp.replace('*', '')
|
||||||
|
}
|
||||||
|
g.gen_str_for_type(sym, styp)
|
||||||
|
if g.autofree && !table.type_is(typ, .optional) {
|
||||||
|
// Create a temporary variable so that the value can be freed
|
||||||
|
tmp := g.new_tmp_var()
|
||||||
|
// tmps << tmp
|
||||||
|
g.write('string $tmp = ${styp}_str(')
|
||||||
|
g.expr(node.args[0].expr)
|
||||||
|
g.writeln('); ${print_method}($tmp); string_free($tmp); //MEM2 $styp')
|
||||||
|
} else {
|
||||||
|
expr := node.args[0].expr
|
||||||
|
is_var := match expr {
|
||||||
|
ast.SelectorExpr {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
ast.Ident {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if table.type_is_ptr(typ) && sym.kind != .struct_ {
|
||||||
|
// ptr_str() for pointers
|
||||||
|
styp = 'ptr'
|
||||||
|
}
|
||||||
|
if sym.kind == .enum_ {
|
||||||
|
if is_var {
|
||||||
|
g.write('${print_method}(${styp}_str(')
|
||||||
|
} else {
|
||||||
|
// when no var, print string directly
|
||||||
|
g.write('${print_method}(tos3("')
|
||||||
|
}
|
||||||
|
if table.type_is_ptr(typ) {
|
||||||
|
// dereference
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
|
g.enum_expr(expr)
|
||||||
|
if !is_var {
|
||||||
|
// end of string
|
||||||
|
g.write('"')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.write('${print_method}(${styp}_str(')
|
||||||
|
if table.type_is_ptr(typ) && sym.kind == .struct_ {
|
||||||
|
// dereference
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
|
g.expr(expr)
|
||||||
|
if sym.kind == .struct_ && styp != 'ptr' && !sym.has_method('str') {
|
||||||
|
g.write(', 0') // trailing 0 is initial struct indent count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.write('))')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.write('${name}(')
|
||||||
|
g.call_args(node.args, node.expected_arg_types)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
// }
|
||||||
|
g.is_c_call = false
|
||||||
|
if g.is_json_fn {
|
||||||
|
g.write(')')
|
||||||
|
g.is_json_fn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||||
|
is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len -
|
||||||
|
1], .variadic)
|
||||||
|
mut arg_no := 0
|
||||||
|
for arg in args {
|
||||||
|
if is_variadic && arg_no == expected_types.len - 1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// some c fn definitions dont have args (cfns.v) or are not updated in checker
|
||||||
|
// when these are fixed we wont need this check
|
||||||
|
if arg_no < expected_types.len {
|
||||||
|
g.ref_or_deref_arg(arg, expected_types[arg_no])
|
||||||
|
} else {
|
||||||
|
g.expr(arg.expr)
|
||||||
|
}
|
||||||
|
if arg_no < args.len - 1 || is_variadic {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
|
arg_no++
|
||||||
|
}
|
||||||
|
if is_variadic {
|
||||||
|
varg_type := expected_types[expected_types.len - 1]
|
||||||
|
struct_name := 'varg_' + g.typ(varg_type).replace('*', '_ptr')
|
||||||
|
variadic_count := args.len - arg_no
|
||||||
|
varg_type_str := int(varg_type).str()
|
||||||
|
if variadic_count > g.variadic_args[varg_type_str] {
|
||||||
|
g.variadic_args[varg_type_str] = variadic_count
|
||||||
|
}
|
||||||
|
g.write('($struct_name){.len=$variadic_count,.args={')
|
||||||
|
if variadic_count > 0 {
|
||||||
|
for j in arg_no .. args.len {
|
||||||
|
g.ref_or_deref_arg(args[j], varg_type)
|
||||||
|
if j < args.len - 1 {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.write('0')
|
||||||
|
}
|
||||||
|
g.write('}}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (g mut Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) {
|
||||||
|
arg_is_ptr := table.type_is_ptr(expected_type) || table.type_idx(expected_type) in table.pointer_type_idxs
|
||||||
|
expr_is_ptr := table.type_is_ptr(arg.typ) || table.type_idx(arg.typ) in table.pointer_type_idxs
|
||||||
|
if arg.is_mut && !arg_is_ptr {
|
||||||
|
g.write('&/*mut*/')
|
||||||
|
} else if arg_is_ptr && !expr_is_ptr {
|
||||||
|
if arg.is_mut {
|
||||||
|
sym := g.table.get_type_symbol(expected_type)
|
||||||
|
if sym.kind == .array {
|
||||||
|
// Special case for mutable arrays. We can't `&` function
|
||||||
|
// results, have to use `(array[]){ expr }[0]` hack.
|
||||||
|
g.write('&/*111*/(array[]){')
|
||||||
|
g.expr(arg.expr)
|
||||||
|
g.write('}[0]')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !g.is_json_fn {
|
||||||
|
g.write('&/*qq*/')
|
||||||
|
}
|
||||||
|
} else if !arg_is_ptr && expr_is_ptr {
|
||||||
|
// Dereference a pointer if a value is required
|
||||||
|
g.write('*/*d*/')
|
||||||
|
}
|
||||||
|
g.expr_with_cast(arg.expr, arg.typ, expected_type)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
v.table
|
||||||
|
strings
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO replace with comptime code generation.
|
||||||
|
// TODO remove cJSON dependency.
|
||||||
|
// OLD: User decode_User(string js) {
|
||||||
|
// now it's
|
||||||
|
// User decode_User(cJSON* root) {
|
||||||
|
// User res;
|
||||||
|
// res.name = decode_string(js_get(root, "name"));
|
||||||
|
// res.profile = decode_Profile(js_get(root, "profile"));
|
||||||
|
// return res;
|
||||||
|
// }
|
||||||
|
// Codegen json_decode/encode funcs
|
||||||
|
fn (g mut Gen) gen_json_for_type(typ table.Type) {
|
||||||
|
mut dec := strings.new_builder(100)
|
||||||
|
mut enc := strings.new_builder(100)
|
||||||
|
sym := g.table.get_type_symbol(typ)
|
||||||
|
styp := g.typ(typ)
|
||||||
|
if sym.name in ['int', 'string', 'bool'] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
// 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
|
||||||
|
dec += '
|
||||||
|
//$t $dec_fn.name (cJSON* root) {
|
||||||
|
Option ${dec_fn.name}(cJSON* root, $t* res) {
|
||||||
|
// $t res;
|
||||||
|
if (!root) {
|
||||||
|
const char *error_ptr = cJSON_GetErrorPtr();
|
||||||
|
if (error_ptr != NULL) {
|
||||||
|
fprintf(stderr, "Error in decode() for $t error_ptr=: %%s\\n", error_ptr);
|
||||||
|
// printf("\\nbad js=%%s\\n", js.str);
|
||||||
|
return v_error(tos2(error_ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'
|
||||||
|
*/
|
||||||
|
// Code gen encoder
|
||||||
|
enc_fn_name := js_enc_name(sym.name)
|
||||||
|
enc.writeln('
|
||||||
|
cJSON* ${enc_fn_name}($styp val) {
|
||||||
|
\tcJSON *o = cJSON_CreateObject();')
|
||||||
|
// Handle arrays
|
||||||
|
if sym.kind == .array {
|
||||||
|
// dec += p.decode_array(t)
|
||||||
|
// enc += p.encode_array(t)
|
||||||
|
}
|
||||||
|
// Range through fields
|
||||||
|
info := sym.info as table.Struct
|
||||||
|
for field in info.fields {
|
||||||
|
if field.attr == 'skip' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := if field.attr.starts_with('json:') { field.attr[5..] } else { field.name }
|
||||||
|
field_type := g.typ(field.typ)
|
||||||
|
enc_name := js_enc_name(field_type)
|
||||||
|
if field.attr == 'raw' {
|
||||||
|
dec.writeln(' res->$field.name = tos2(cJSON_PrintUnformatted(' + 'js_get(root, "$name")));')
|
||||||
|
} else {
|
||||||
|
// Now generate decoders for all field types in this struct
|
||||||
|
// need to do it here so that these functions are generated first
|
||||||
|
g.gen_json_for_type(field.typ)
|
||||||
|
dec_name := js_dec_name(field_type)
|
||||||
|
if is_js_prim(field_type) {
|
||||||
|
dec.writeln(' res->$field.name = $dec_name (js_get(' + 'root, "$name"))')
|
||||||
|
} else {
|
||||||
|
dec.writeln(' $dec_name (js_get(root, "$name"), & (res->$field.name))')
|
||||||
|
}
|
||||||
|
dec.writeln(';')
|
||||||
|
}
|
||||||
|
enc.writeln('\tcJSON_AddItemToObject(o, "$name", ${enc_name}(val.$field.name));')
|
||||||
|
}
|
||||||
|
// cJSON_delete
|
||||||
|
// p.cgen.fns << '$dec return opt_ok(res); \n}'
|
||||||
|
dec.writeln('return opt_ok(res, sizeof(*res)); \n}')
|
||||||
|
enc.writeln('\treturn o;\n}')
|
||||||
|
// g.definitions.writeln(dec.str())
|
||||||
|
g.gowrappers.writeln(enc.str())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn js_enc_name(typ string) string {
|
||||||
|
name := 'json__encode_$typ'
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn js_dec_name(typ string) string {
|
||||||
|
name := 'json__decode_$typ'
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_js_prim(typ string) bool {
|
||||||
|
return typ == 'int' || typ == 'string' || typ == 'bool' || typ == 'f32' || typ == 'f64' ||
|
||||||
|
typ == 'i8' || typ == 'i16' || typ == 'i64' || typ == 'u16' || typ == 'u32' || typ == 'u64'
|
||||||
|
}
|
|
@ -9,7 +9,6 @@
|
||||||
// flag: (int(type)>>24) & 0xff
|
// flag: (int(type)>>24) & 0xff
|
||||||
// nr_muls: (int(type)>>16) & 0xff
|
// nr_muls: (int(type)>>16) & 0xff
|
||||||
// idx: u16(type) & 0xffff
|
// idx: u16(type) & 0xffff
|
||||||
|
|
||||||
module table
|
module table
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -19,8 +18,7 @@ import (
|
||||||
|
|
||||||
pub type Type int
|
pub type Type int
|
||||||
|
|
||||||
pub type TypeInfo = Array | ArrayFixed | Map | Struct |
|
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Alias | Enum | SumType | FnType
|
||||||
MultiReturn | Alias | Enum | SumType | FnType
|
|
||||||
|
|
||||||
pub struct TypeSymbol {
|
pub struct TypeSymbol {
|
||||||
pub:
|
pub:
|
||||||
|
@ -64,6 +62,7 @@ pub fn type_nr_muls(t Type) int {
|
||||||
pub fn type_is_ptr(t Type) bool {
|
pub fn type_is_ptr(t Type) bool {
|
||||||
return (int(t) >> 16) & 0xff > 0
|
return (int(t) >> 16) & 0xff > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// set nr_muls on `t` and return it
|
// set nr_muls on `t` and return it
|
||||||
[inline]
|
[inline]
|
||||||
pub fn type_set_nr_muls(t Type, nr_muls int) Type {
|
pub fn type_set_nr_muls(t Type, nr_muls int) Type {
|
||||||
|
@ -122,7 +121,7 @@ pub fn new_type(idx int) Type {
|
||||||
|
|
||||||
// return new type with TypeSymbol idx set to `idx` & nr_muls set to `nr_muls`
|
// return new type with TypeSymbol idx set to `idx` & nr_muls set to `nr_muls`
|
||||||
[inline]
|
[inline]
|
||||||
pub fn new_type_ptr(idx int, nr_muls int) Type {
|
pub fn new_type_ptr(idx, nr_muls int) Type {
|
||||||
if idx < 1 || idx > 65536 {
|
if idx < 1 || idx > 65536 {
|
||||||
panic('new_type_ptr: idx must be between 1 & 65536')
|
panic('new_type_ptr: idx must be between 1 & 65536')
|
||||||
}
|
}
|
||||||
|
@ -137,7 +136,6 @@ pub fn is_number(typ Type) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
// primitive types
|
|
||||||
void_type_idx = 1
|
void_type_idx = 1
|
||||||
voidptr_type_idx = 2
|
voidptr_type_idx = 2
|
||||||
byteptr_type_idx = 3
|
byteptr_type_idx = 3
|
||||||
|
@ -155,16 +153,17 @@ pub const (
|
||||||
char_type_idx = 15
|
char_type_idx = 15
|
||||||
bool_type_idx = 16
|
bool_type_idx = 16
|
||||||
none_type_idx = 17
|
none_type_idx = 17
|
||||||
// advanced / defined from v structs
|
|
||||||
string_type_idx = 18
|
string_type_idx = 18
|
||||||
array_type_idx = 19
|
array_type_idx = 19
|
||||||
map_type_idx = 20
|
map_type_idx = 20
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx]
|
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
||||||
|
u16_type_idx, u32_type_idx, u64_type_idx]
|
||||||
float_type_idxs = [f32_type_idx, f64_type_idx]
|
float_type_idxs = [f32_type_idx, f64_type_idx]
|
||||||
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, f32_type_idx, f64_type_idx]
|
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx, byte_type_idx,
|
||||||
|
u16_type_idx, u32_type_idx, u64_type_idx, f32_type_idx, f64_type_idx]
|
||||||
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -192,9 +191,9 @@ pub const (
|
||||||
)
|
)
|
||||||
|
|
||||||
pub const (
|
pub const (
|
||||||
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64',
|
builtin_type_names = ['void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64',
|
||||||
'f32', 'f64', 'string', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed', 'map', 'struct',
|
'u16', 'u32', 'u64', 'f32', 'f64', 'string', 'char', 'byte', 'bool', 'none', 'array', 'array_fixed',
|
||||||
'mapnode', 'ustring', 'size_t']
|
'map', 'struct', 'mapnode', 'ustring', 'size_t']
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct MultiReturn {
|
pub struct MultiReturn {
|
||||||
|
@ -311,8 +310,6 @@ pub fn (t TypeSymbol) str() string {
|
||||||
return t.name
|
return t.name
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
pub fn (t mut Table) register_builtin_type_symbols() {
|
pub fn (t mut Table) register_builtin_type_symbols() {
|
||||||
// reserve index 0 so nothing can go there
|
// reserve index 0 so nothing can go there
|
||||||
// save index check, 0 will mean not found
|
// save index check, 0 will mean not found
|
||||||
|
@ -523,7 +520,8 @@ pub fn (k Kind) str() string {
|
||||||
'enum'
|
'enum'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
'unknown'}
|
'unknown'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return k_str
|
return k_str
|
||||||
}
|
}
|
||||||
|
@ -564,6 +562,7 @@ mut:
|
||||||
default_expr ast.Expr
|
default_expr ast.Expr
|
||||||
has_default_expr bool
|
has_default_expr bool
|
||||||
default_val string
|
default_val string
|
||||||
|
attr string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Array {
|
pub struct Array {
|
||||||
|
@ -609,8 +608,7 @@ pub fn (table &Table) type_to_str(t Type) string {
|
||||||
mut res := sym.name
|
mut res := sym.name
|
||||||
if sym.kind == .array {
|
if sym.kind == .array {
|
||||||
res = res.replace('array_', '[]')
|
res = res.replace('array_', '[]')
|
||||||
}
|
} else if sym.kind == .map {
|
||||||
else if sym.kind == .map {
|
|
||||||
res = res.replace('map_string_', 'map[string]')
|
res = res.replace('map_string_', 'map[string]')
|
||||||
}
|
}
|
||||||
// mod.submod.submod2.Type => submod2.Type
|
// mod.submod.submod2.Type => submod2.Type
|
||||||
|
@ -635,6 +633,5 @@ pub fn (table &Table) type_to_str(t Type) string {
|
||||||
res = res[cur_mod.len+1.. ]
|
res = res[cur_mod.len+1.. ]
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,13 @@ pub fn (t &Table) find_fn(name string) ?Fn {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (t &Table) known_fn(name string) bool {
|
||||||
|
t.find_fn(name) or {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) register_fn(new_fn Fn) {
|
pub fn (t mut Table) register_fn(new_fn Fn) {
|
||||||
// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
|
// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
|
||||||
t.fns[new_fn.name] = new_fn
|
t.fns[new_fn.name] = new_fn
|
||||||
|
|
Loading…
Reference in New Issue