mirror of
https://github.com/vlang/v.git
synced 2025-08-04 10:17:22 -04:00
This commit is contained in:
parent
bd6005ed73
commit
d9c3ac5ce6
@ -399,7 +399,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
&& right.or_expr.kind == .absent {
|
||||
right_obj_var := right.obj as ast.Var
|
||||
if right_obj_var.ct_type_var != .no_comptime {
|
||||
ctyp := c.comptime.get_comptime_var_type(right)
|
||||
ctyp := c.comptime.get_type(right)
|
||||
if ctyp != ast.void_type {
|
||||
left.obj.ct_type_var = right_obj_var.ct_type_var
|
||||
left.obj.typ = ctyp
|
||||
@ -421,11 +421,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
fn_ret_type := c.resolve_return_type(right)
|
||||
if fn_ret_type != ast.void_type
|
||||
&& c.table.final_sym(fn_ret_type).kind != .multi_return {
|
||||
c.comptime.type_map['g.${left.name}.${left.obj.pos.pos}'] = if right.or_block.kind == .absent {
|
||||
var_type := if right.or_block.kind == .absent {
|
||||
fn_ret_type
|
||||
} else {
|
||||
fn_ret_type.clear_option_and_result()
|
||||
}
|
||||
c.comptime.type_map['g.${left.name}.${left.obj.pos.pos}'] = var_type
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -505,7 +506,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
}
|
||||
|
||||
if right is ast.Ident && c.comptime.is_comptime_var(right) {
|
||||
right_type = c.comptime.get_comptime_var_type(right)
|
||||
right_type = c.comptime.get_type(right)
|
||||
}
|
||||
}
|
||||
if mut left is ast.InfixExpr {
|
||||
|
@ -2928,7 +2928,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
|
||||
|
||||
if c.comptime.inside_comptime_for && node.expr is ast.Ident {
|
||||
if c.comptime.is_comptime_var(node.expr) {
|
||||
node.expr_type = c.comptime.get_comptime_var_type(node.expr as ast.Ident)
|
||||
node.expr_type = c.comptime.get_type(node.expr as ast.Ident)
|
||||
} else if (node.expr as ast.Ident).name in c.comptime.type_map {
|
||||
node.expr_type = c.comptime.type_map[(node.expr as ast.Ident).name]
|
||||
}
|
||||
@ -3805,7 +3805,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
|
||||
if node.kind in [.constant, .global, .variable] {
|
||||
info := node.info as ast.IdentVar
|
||||
typ := if c.comptime.is_comptime_var(node) {
|
||||
ctype := c.comptime.get_comptime_var_type(node)
|
||||
ctype := c.comptime.get_type(node)
|
||||
if ctype != ast.void_type {
|
||||
ctype
|
||||
} else {
|
||||
|
@ -134,7 +134,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
||||
node.args[i].typ = c.expr(mut arg.expr)
|
||||
}
|
||||
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
|
||||
return c.comptime.get_comptime_var_type(node)
|
||||
return c.comptime.get_type(node)
|
||||
}
|
||||
if node.method_name == 'res' {
|
||||
if !c.inside_defer {
|
||||
@ -790,7 +790,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
|
||||
if mut cond.left is ast.SelectorExpr && cond.right is ast.ComptimeType {
|
||||
comptime_type := cond.right as ast.ComptimeType
|
||||
if c.comptime.is_comptime_selector_type(cond.left) {
|
||||
checked_type := c.comptime.get_comptime_var_type(cond.left)
|
||||
checked_type := c.comptime.get_type(cond.left)
|
||||
return if c.comptime.is_comptime_type(checked_type, comptime_type) {
|
||||
.eval
|
||||
} else {
|
||||
|
@ -1807,7 +1807,7 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
|
||||
if call_arg.expr is ast.Ident {
|
||||
if call_arg.expr.obj is ast.Var {
|
||||
if call_arg.expr.obj.ct_type_var !in [.generic_var, .generic_param, .no_comptime] {
|
||||
mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr)
|
||||
mut ctyp := c.comptime.get_type(call_arg.expr)
|
||||
if ctyp != ast.void_type {
|
||||
arg_sym := c.table.sym(ctyp)
|
||||
param_sym := c.table.final_sym(param_typ)
|
||||
@ -1830,7 +1830,7 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
|
||||
comptime_args[k] = ctyp
|
||||
}
|
||||
} else if call_arg.expr.obj.ct_type_var == .generic_param {
|
||||
mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr)
|
||||
mut ctyp := c.comptime.get_type(call_arg.expr)
|
||||
if ctyp != ast.void_type {
|
||||
arg_sym := c.table.final_sym(call_arg.typ)
|
||||
param_typ_sym := c.table.sym(param_typ)
|
||||
@ -1893,7 +1893,10 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
|
||||
}
|
||||
}
|
||||
} else if call_arg.expr.obj.ct_type_var == .generic_var {
|
||||
mut ctyp := c.comptime.get_comptime_var_type(call_arg.expr)
|
||||
mut ctyp := c.comptime.get_type(call_arg.expr)
|
||||
if node_.args[i].expr.is_auto_deref_var() {
|
||||
ctyp = ctyp.deref()
|
||||
}
|
||||
if ctyp.nr_muls() > 0 && param_typ.nr_muls() > 0 {
|
||||
ctyp = ctyp.set_nr_muls(0)
|
||||
}
|
||||
@ -1902,14 +1905,14 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
|
||||
}
|
||||
} else if call_arg.expr is ast.PrefixExpr {
|
||||
if call_arg.expr.right is ast.ComptimeSelector {
|
||||
comptime_args[k] = c.comptime.get_comptime_var_type(call_arg.expr.right)
|
||||
comptime_args[k] = c.comptime.get_type(call_arg.expr.right)
|
||||
comptime_args[k] = comptime_args[k].deref()
|
||||
if comptime_args[k].nr_muls() > 0 && param_typ.nr_muls() > 0 {
|
||||
comptime_args[k] = comptime_args[k].set_nr_muls(0)
|
||||
}
|
||||
}
|
||||
} else if call_arg.expr is ast.ComptimeSelector {
|
||||
ct_value := c.comptime.get_comptime_var_type(call_arg.expr)
|
||||
ct_value := c.comptime.get_type(call_arg.expr)
|
||||
param_typ_sym := c.table.sym(param_typ)
|
||||
if ct_value != ast.void_type {
|
||||
arg_sym := c.table.final_sym(call_arg.typ)
|
||||
@ -1934,7 +1937,7 @@ fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concr
|
||||
}
|
||||
}
|
||||
} else if call_arg.expr is ast.ComptimeCall {
|
||||
comptime_args[k] = c.comptime.get_comptime_var_type(call_arg.expr)
|
||||
comptime_args[k] = c.comptime.get_type(call_arg.expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
mut is_comptime := false
|
||||
if (node.cond is ast.Ident && c.comptime.is_comptime_var(node.cond))
|
||||
|| node.cond is ast.ComptimeSelector {
|
||||
ctyp := c.comptime.get_comptime_var_type(node.cond)
|
||||
ctyp := c.comptime.get_type(node.cond)
|
||||
if ctyp != ast.void_type {
|
||||
is_comptime = true
|
||||
typ = ctyp
|
||||
|
@ -557,7 +557,7 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope, co
|
||||
c.smartcast_if_conds(mut node.right, mut scope, control_expr)
|
||||
} else if node.left is ast.Ident && node.op == .ne && node.right is ast.None {
|
||||
if node.left is ast.Ident && c.comptime.get_ct_type_var(node.left) == .smartcast {
|
||||
node.left_type = c.comptime.get_comptime_var_type(node.left)
|
||||
node.left_type = c.comptime.get_type(node.left)
|
||||
c.smartcast(mut node.left, node.left_type, node.left_type.clear_flag(.option), mut
|
||||
scope, true)
|
||||
} else {
|
||||
@ -566,7 +566,7 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope, co
|
||||
}
|
||||
} else if node.op == .key_is {
|
||||
if node.left is ast.Ident && c.comptime.is_comptime_var(node.left) {
|
||||
node.left_type = c.comptime.get_comptime_var_type(node.left)
|
||||
node.left_type = c.comptime.get_type(node.left)
|
||||
} else {
|
||||
node.left_type = c.expr(mut node.left)
|
||||
}
|
||||
@ -650,7 +650,7 @@ fn (mut c Checker) smartcast_if_conds(mut node ast.Expr, mut scope ast.Scope, co
|
||||
if first_cond.left is ast.Ident && first_cond.op == .eq && first_cond.right is ast.None {
|
||||
if first_cond.left is ast.Ident
|
||||
&& c.comptime.get_ct_type_var(first_cond.left) == .smartcast {
|
||||
first_cond.left_type = c.comptime.get_comptime_var_type(first_cond.left)
|
||||
first_cond.left_type = c.comptime.get_type(first_cond.left)
|
||||
c.smartcast(mut first_cond.left, first_cond.left_type, first_cond.left_type.clear_flag(.option), mut
|
||||
scope, true)
|
||||
} else {
|
||||
|
@ -26,7 +26,7 @@ fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type {
|
||||
if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) {
|
||||
if c.comptime.comptime_for_field_var != '' {
|
||||
if c.comptime.is_comptime_var(node.expr) || node.expr is ast.ComptimeSelector {
|
||||
node.typ = c.unwrap_generic(c.comptime.get_comptime_var_type(node.expr))
|
||||
node.typ = c.unwrap_generic(c.comptime.get_type(node.expr))
|
||||
if node.op == .question {
|
||||
node.typ = node.typ.clear_flag(.option)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
|
||||
mut ftyp := c.expr(mut expr)
|
||||
ftyp = c.check_expr_option_or_result_call(expr, ftyp)
|
||||
if c.comptime.is_comptime_var(expr) {
|
||||
ctyp := c.comptime.get_comptime_var_type(expr)
|
||||
ctyp := c.comptime.get_type(expr)
|
||||
if ctyp != ast.void_type {
|
||||
ftyp = ctyp
|
||||
}
|
||||
@ -79,8 +79,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
|
||||
c.error('no known default format for type `${c.table.get_type_name(ftyp)}`',
|
||||
node.fmt_poss[i])
|
||||
}
|
||||
} else if c.comptime.is_comptime_var(expr)
|
||||
&& c.comptime.get_comptime_var_type(expr) != ast.void_type {
|
||||
} else if c.comptime.is_comptime_var(expr) && c.comptime.get_type(expr) != ast.void_type {
|
||||
// still `_` placeholder for comptime variable without specifier
|
||||
node.need_fmts[i] = false
|
||||
} else {
|
||||
|
@ -28,6 +28,14 @@ pub fn (mut ct ComptimeInfo) get_comptime_selector_key_type(val ast.ComptimeSele
|
||||
return ''
|
||||
}
|
||||
|
||||
// is_comptime_expr checks if the node is related to a comptime expr
|
||||
@[inline]
|
||||
pub fn (mut ct ComptimeInfo) is_comptime_expr(node ast.Expr) bool {
|
||||
return (node is ast.Ident && ct.get_ct_type_var(node) != .no_comptime)
|
||||
|| (node is ast.IndexExpr && ct.is_comptime_expr(node.left))
|
||||
|| node is ast.ComptimeSelector
|
||||
}
|
||||
|
||||
// is_comptime_var checks if the node is related to a comptime variable
|
||||
@[inline]
|
||||
pub fn (mut ct ComptimeInfo) is_comptime_var(node ast.Expr) bool {
|
||||
@ -45,6 +53,8 @@ pub fn (mut ct ComptimeInfo) is_comptime_variant_var(node ast.Ident) bool {
|
||||
pub fn (mut ct ComptimeInfo) get_ct_type_var(node ast.Expr) ast.ComptimeVarKind {
|
||||
return if node is ast.Ident && node.obj is ast.Var {
|
||||
(node.obj as ast.Var).ct_type_var
|
||||
} else if node is ast.IndexExpr {
|
||||
return ct.get_ct_type_var(node.left)
|
||||
} else {
|
||||
.no_comptime
|
||||
}
|
||||
@ -56,9 +66,23 @@ pub fn (mut ct ComptimeInfo) is_generic_param_var(node ast.Expr) bool {
|
||||
&& (node.obj as ast.Var).ct_type_var == .generic_param
|
||||
}
|
||||
|
||||
// get_comptime_var_type retrieves the actual type from a comptime related ast node
|
||||
// get_expr_type computes the ast node type regarding its or_expr
|
||||
pub fn (mut ct ComptimeInfo) get_expr_type(node ast.Expr) ast.Type {
|
||||
ctyp := ct.get_type(node)
|
||||
match node {
|
||||
ast.Ident {
|
||||
if ctyp.has_flag(.option) && node.or_expr.kind != .absent {
|
||||
return ctyp.clear_flag(.option)
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
return ctyp
|
||||
}
|
||||
|
||||
// get_type retrieves the actual type from a comptime related ast node
|
||||
@[inline]
|
||||
pub fn (mut ct ComptimeInfo) get_comptime_var_type(node ast.Expr) ast.Type {
|
||||
pub fn (mut ct ComptimeInfo) get_type(node ast.Expr) ast.Type {
|
||||
if node is ast.Ident {
|
||||
if node.obj is ast.Var {
|
||||
return match node.obj.ct_type_var {
|
||||
@ -109,6 +133,8 @@ pub fn (mut ct ComptimeInfo) get_comptime_var_type(node ast.Expr) ast.Type {
|
||||
return ast.void_type
|
||||
}
|
||||
return f.return_type
|
||||
} else if node is ast.IndexExpr && ct.is_comptime_var(node.left) {
|
||||
return ct.table.value_type(ct.resolver.unwrap_generic(ct.get_type(node.left)))
|
||||
}
|
||||
return ast.void_type
|
||||
}
|
||||
@ -304,16 +330,16 @@ pub fn (mut ct ComptimeInfo) unwrap_generic_expr(expr ast.Expr, default_typ ast.
|
||||
}
|
||||
ast.InfixExpr {
|
||||
if ct.is_comptime_var(expr.left) {
|
||||
return ct.resolver.unwrap_generic(ct.get_comptime_var_type(expr.left))
|
||||
return ct.resolver.unwrap_generic(ct.get_type(expr.left))
|
||||
}
|
||||
if ct.is_comptime_var(expr.right) {
|
||||
return ct.resolver.unwrap_generic(ct.get_comptime_var_type(expr.right))
|
||||
return ct.resolver.unwrap_generic(ct.get_type(expr.right))
|
||||
}
|
||||
return default_typ
|
||||
}
|
||||
ast.Ident {
|
||||
return if ct.is_comptime_var(expr) {
|
||||
ct.resolver.unwrap_generic(ct.get_comptime_var_type(expr))
|
||||
ct.resolver.unwrap_generic(ct.get_type(expr))
|
||||
} else {
|
||||
default_typ
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
|
||||
// value.map(Type(it)) when `value` is a comptime var
|
||||
if expr.expr is ast.Ident && node.left is ast.Ident
|
||||
&& g.comptime.is_comptime_var(node.left) {
|
||||
ctyp := g.comptime.get_comptime_var_type(node.left)
|
||||
ctyp := g.comptime.get_type(node.left)
|
||||
if ctyp != ast.void_type {
|
||||
expr.expr_type = g.table.value_type(ctyp)
|
||||
}
|
||||
|
@ -151,12 +151,22 @@ fn (mut g Gen) gen_assert_metainfo(node ast.AssertStmt, kind AssertMetainfoKind)
|
||||
g.writeln('\t${metaname}.op = ${expr_op_str};')
|
||||
g.writeln('\t${metaname}.llabel = ${expr_left_str};')
|
||||
g.writeln('\t${metaname}.rlabel = ${expr_right_str};')
|
||||
left_type := if g.comptime.is_comptime_expr(node.expr.left) {
|
||||
g.comptime.get_type(node.expr.left)
|
||||
} else {
|
||||
node.expr.left_type
|
||||
}
|
||||
right_type := if g.comptime.is_comptime_expr(node.expr.right) {
|
||||
g.comptime.get_type(node.expr.right)
|
||||
} else {
|
||||
node.expr.right_type
|
||||
}
|
||||
if kind != .pass {
|
||||
g.write('\t${metaname}.lvalue = ')
|
||||
g.gen_assert_single_expr(node.expr.left, node.expr.left_type)
|
||||
g.gen_assert_single_expr(node.expr.left, left_type)
|
||||
g.writeln(';')
|
||||
g.write('\t${metaname}.rvalue = ')
|
||||
g.gen_assert_single_expr(node.expr.right, node.expr.right_type)
|
||||
g.gen_assert_single_expr(node.expr.right, right_type)
|
||||
g.writeln(';')
|
||||
}
|
||||
}
|
||||
@ -207,6 +217,8 @@ fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ ast.Type) {
|
||||
// vlib/builtin/map_test.v (a map of &int, set to &int(0)) fails
|
||||
// without special casing ast.CastExpr here
|
||||
g.write(ctoslit(expr_str))
|
||||
} else if expr.right is ast.Ident {
|
||||
g.write(ctoslit(expr_str))
|
||||
} else {
|
||||
g.gen_expr_to_string(expr, typ)
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
}
|
||||
if mut left.obj is ast.Var {
|
||||
if val is ast.Ident && g.comptime.is_comptime_var(val) {
|
||||
ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(val))
|
||||
ctyp := g.unwrap_generic(g.comptime.get_type(val))
|
||||
if ctyp != ast.void_type {
|
||||
var_type = ctyp
|
||||
val_type = var_type
|
||||
|
@ -191,8 +191,9 @@ mut:
|
||||
array_index_types []ast.Type
|
||||
auto_fn_definitions []string // auto generated functions definition list
|
||||
sumtype_casting_fns []SumtypeCastingFn
|
||||
anon_fn_definitions []string // anon generated functions definition list
|
||||
sumtype_definitions map[int]bool // `_TypeA_to_sumtype_TypeB()` fns that have been generated
|
||||
anon_fn_definitions []string // anon generated functions definition list
|
||||
anon_fns shared []string // remove duplicate anon generated functions
|
||||
sumtype_definitions map[int]bool // `_TypeA_to_sumtype_TypeB()` fns that have been generated
|
||||
trace_fn_definitions []string
|
||||
json_types []ast.Type // to avoid json gen duplicates
|
||||
pcs []ProfileCounterMeta // -prof profile counter fn_names => fn counter name
|
||||
@ -713,6 +714,7 @@ fn cgen_process_one_file_cb(mut p pool.PoolProcessor, idx int, wid int) &Gen {
|
||||
waiter_fns: global_g.waiter_fns
|
||||
threaded_fns: global_g.threaded_fns
|
||||
str_fn_names: global_g.str_fn_names
|
||||
anon_fns: global_g.anon_fns
|
||||
options_forward: global_g.options_forward
|
||||
results_forward: global_g.results_forward
|
||||
done_options: global_g.done_options
|
||||
@ -3895,6 +3897,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
if node.expr_type == 0 {
|
||||
g.checker_bug('unexpected SelectorExpr.expr_type = 0', node.pos)
|
||||
}
|
||||
|
||||
sym := g.table.sym(g.unwrap_generic(node.expr_type))
|
||||
field_name := if sym.language == .v { c_name(node.field_name) } else { node.field_name }
|
||||
is_as_cast := node.expr is ast.AsCast
|
||||
@ -4033,53 +4036,13 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
}
|
||||
receiver := m.params[0]
|
||||
expr_styp := g.styp(g.unwrap_generic(node.expr_type).idx_type())
|
||||
data_styp := g.styp(receiver.typ.idx_type())
|
||||
mut sb := strings.new_builder(256)
|
||||
name := '_V_closure_${expr_styp}_${m.name}_${node.pos.pos}'
|
||||
sb.write_string('${g.styp(m.return_type)} ${name}(')
|
||||
for i in 1 .. m.params.len {
|
||||
param := m.params[i]
|
||||
if i != 1 {
|
||||
sb.write_string(', ')
|
||||
}
|
||||
sb.write_string('${g.styp(param.typ)} a${i}')
|
||||
}
|
||||
sb.writeln(') {')
|
||||
sb.writeln('\t${data_styp}* a0 = __CLOSURE_GET_DATA();')
|
||||
if m.return_type != ast.void_type {
|
||||
sb.write_string('\treturn ')
|
||||
} else {
|
||||
sb.write_string('\t')
|
||||
}
|
||||
mut method_name := m.name
|
||||
rec_sym := g.table.sym(receiver.typ)
|
||||
if rec_sym.info is ast.Struct {
|
||||
if rec_sym.info.concrete_types.len > 0 {
|
||||
method_name = g.generic_fn_name(rec_sym.info.concrete_types, m.name)
|
||||
lock g.anon_fns {
|
||||
if name !in g.anon_fns {
|
||||
g.anon_fns << name
|
||||
g.gen_closure_fn(expr_styp, m, name)
|
||||
}
|
||||
}
|
||||
if rec_sym.info is ast.Interface {
|
||||
left_cc_type := g.cc_type(g.table.unaliased_type(receiver.typ), false)
|
||||
left_type_name := util.no_dots(left_cc_type)
|
||||
sb.write_string('${c_name(left_type_name)}_name_table[a0->_typ]._method_${method_name}(')
|
||||
} else {
|
||||
sb.write_string('${expr_styp}_${method_name}(')
|
||||
if !receiver.typ.is_ptr() {
|
||||
sb.write_string('*')
|
||||
}
|
||||
}
|
||||
for i in 0 .. m.params.len {
|
||||
if i != 0 {
|
||||
sb.write_string(', ')
|
||||
}
|
||||
sb.write_string('a${i}')
|
||||
}
|
||||
sb.writeln(');')
|
||||
sb.writeln('}')
|
||||
|
||||
g.anon_fn_definitions << sb.str()
|
||||
g.nr_closures++
|
||||
|
||||
g.write('__closure_create(${name}, ')
|
||||
if !receiver.typ.is_ptr() {
|
||||
g.write('memdup_uncollectable(')
|
||||
@ -4191,6 +4154,56 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_closure_fn(expr_styp string, m ast.Fn, name string) {
|
||||
receiver := m.params[0]
|
||||
data_styp := g.styp(receiver.typ.idx_type())
|
||||
|
||||
mut sb := strings.new_builder(256)
|
||||
sb.write_string('${g.styp(m.return_type)} ${name}(')
|
||||
for i in 1 .. m.params.len {
|
||||
param := m.params[i]
|
||||
if i != 1 {
|
||||
sb.write_string(', ')
|
||||
}
|
||||
sb.write_string('${g.styp(param.typ)} a${i}')
|
||||
}
|
||||
sb.writeln(') {')
|
||||
sb.writeln('\t${data_styp}* a0 = __CLOSURE_GET_DATA();')
|
||||
if m.return_type != ast.void_type {
|
||||
sb.write_string('\treturn ')
|
||||
} else {
|
||||
sb.write_string('\t')
|
||||
}
|
||||
mut method_name := m.name
|
||||
rec_sym := g.table.sym(receiver.typ)
|
||||
if rec_sym.info is ast.Struct {
|
||||
if rec_sym.info.concrete_types.len > 0 {
|
||||
method_name = g.generic_fn_name(rec_sym.info.concrete_types, m.name)
|
||||
}
|
||||
}
|
||||
if rec_sym.info is ast.Interface {
|
||||
left_cc_type := g.cc_type(g.table.unaliased_type(receiver.typ), false)
|
||||
left_type_name := util.no_dots(left_cc_type)
|
||||
sb.write_string('${c_name(left_type_name)}_name_table[a0->_typ]._method_${method_name}(')
|
||||
} else {
|
||||
sb.write_string('${expr_styp}_${method_name}(')
|
||||
if !receiver.typ.is_ptr() {
|
||||
sb.write_string('*')
|
||||
}
|
||||
}
|
||||
for i in 0 .. m.params.len {
|
||||
if i != 0 {
|
||||
sb.write_string(', ')
|
||||
}
|
||||
sb.write_string('a${i}')
|
||||
}
|
||||
sb.writeln(');')
|
||||
sb.writeln('}')
|
||||
|
||||
g.anon_fn_definitions << sb.str()
|
||||
g.nr_closures++
|
||||
}
|
||||
|
||||
fn (mut g Gen) write_selector_expr_embed_name(node ast.SelectorExpr, embed_types []ast.Type) {
|
||||
for i, embed in embed_types {
|
||||
embed_sym := g.table.sym(embed)
|
||||
@ -4261,7 +4274,7 @@ fn (mut g Gen) debugger_stmt(node ast.DebuggerStmt) {
|
||||
if obj is ast.Var && g.check_var_scope(obj, node.pos.pos) {
|
||||
keys.write_string('_SLIT("${obj.name}")')
|
||||
var_typ := if obj.ct_type_var != .no_comptime {
|
||||
g.comptime.get_comptime_var_type(ast.Ident{ obj: obj })
|
||||
g.comptime.get_type(ast.Ident{ obj: obj })
|
||||
} else if obj.smartcasts.len > 0 {
|
||||
obj.smartcasts.last()
|
||||
} else {
|
||||
@ -4858,7 +4871,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
if node.obj is ast.Var {
|
||||
if !g.is_assign_lhs
|
||||
&& node.obj.ct_type_var !in [.smartcast, .generic_param, .no_comptime] {
|
||||
comptime_type := g.comptime.get_comptime_var_type(node)
|
||||
comptime_type := g.comptime.get_type(node)
|
||||
if comptime_type.has_flag(.option) {
|
||||
if (g.inside_opt_or_res || g.left_is_opt) && node.or_expr.kind == .absent {
|
||||
if !g.is_assign_lhs && is_auto_heap {
|
||||
@ -4876,7 +4889,11 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.write(name)
|
||||
if is_auto_heap {
|
||||
g.write2('*', name)
|
||||
} else {
|
||||
g.write(name)
|
||||
}
|
||||
}
|
||||
if node.or_expr.kind != .absent && !(g.inside_opt_or_res && g.inside_assign
|
||||
&& !g.is_assign_lhs) {
|
||||
@ -4944,7 +4961,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
if node.obj.smartcasts.len > 0 {
|
||||
obj_sym := g.table.sym(g.unwrap_generic(node.obj.typ))
|
||||
if node.obj.ct_type_var == .smartcast {
|
||||
ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(node))
|
||||
ctyp := g.unwrap_generic(g.comptime.get_type(node))
|
||||
cur_variant_sym := g.table.sym(ctyp)
|
||||
variant_name := g.get_sumtype_variant_name(ctyp, cur_variant_sym)
|
||||
g.write('._${variant_name}')
|
||||
@ -4980,7 +4997,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
is_option_unwrap := is_option && typ == node.obj.typ.clear_flag(.option)
|
||||
g.write('(')
|
||||
if i == 0 && node.obj.is_unwrapped {
|
||||
ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(node))
|
||||
ctyp := g.unwrap_generic(g.comptime.get_type(node))
|
||||
g.write('*(${g.base_type(ctyp)}*)(')
|
||||
}
|
||||
if obj_sym.kind == .sum_type && !is_auto_heap {
|
||||
@ -5036,7 +5053,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
}
|
||||
}
|
||||
if node.obj.ct_type_var == .smartcast {
|
||||
mut ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(node))
|
||||
mut ctyp := g.unwrap_generic(g.comptime.get_type(node))
|
||||
cur_variant_sym := g.table.sym(ctyp)
|
||||
if node.obj.is_unwrapped {
|
||||
ctyp = ctyp.set_flag(.option)
|
||||
@ -5111,9 +5128,8 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||
node_typ := g.unwrap_generic(node.typ)
|
||||
mut expr_type := node.expr_type
|
||||
sym := g.table.sym(node_typ)
|
||||
if (node.expr is ast.Ident && g.comptime.is_comptime_var(node.expr))
|
||||
|| node.expr is ast.ComptimeSelector {
|
||||
expr_type = g.unwrap_generic(g.comptime.get_comptime_var_type(node.expr))
|
||||
if g.comptime.is_comptime_expr(node.expr) {
|
||||
expr_type = g.unwrap_generic(g.comptime.get_type(node.expr))
|
||||
}
|
||||
if sym.kind in [.sum_type, .interface] {
|
||||
if node.typ.has_flag(.option) && node.expr is ast.None {
|
||||
|
@ -460,7 +460,7 @@ fn (mut g Gen) get_expr_type(cond ast.Expr) ast.Type {
|
||||
match cond {
|
||||
ast.Ident {
|
||||
return if g.comptime.is_comptime_var(cond) {
|
||||
g.unwrap_generic(g.comptime.get_comptime_var_type(cond))
|
||||
g.unwrap_generic(g.comptime.get_type(cond))
|
||||
} else {
|
||||
g.unwrap_generic(cond.obj.typ)
|
||||
}
|
||||
@ -800,8 +800,8 @@ fn (mut g Gen) pop_comptime_info() {
|
||||
}
|
||||
|
||||
fn (mut g Gen) resolve_comptime_type(node ast.Expr, default_type ast.Type) ast.Type {
|
||||
if (node is ast.Ident && g.comptime.is_comptime_var(node)) || node is ast.ComptimeSelector {
|
||||
return g.comptime.get_comptime_var_type(node)
|
||||
if g.comptime.is_comptime_expr(node) {
|
||||
return g.comptime.get_type(node)
|
||||
} else if node is ast.SelectorExpr && node.expr_type != 0 {
|
||||
if node.expr is ast.Ident && g.comptime.is_comptime_selector_type(node) {
|
||||
return g.comptime.get_type_from_comptime_var(node.expr)
|
||||
@ -1062,6 +1062,100 @@ fn (mut g Gen) comptime_for(node ast.ComptimeFor) {
|
||||
g.writeln('}// \$for')
|
||||
}
|
||||
|
||||
// comptime_selector_type computes the selector type from an comptime var
|
||||
fn (mut g Gen) comptime_selector_type(node ast.SelectorExpr) ast.Type {
|
||||
if !(node.expr is ast.Ident && g.comptime.is_comptime_var(node.expr)) {
|
||||
return node.expr_type
|
||||
}
|
||||
prevent_sum_type_unwrapping_once := g.prevent_sum_type_unwrapping_once
|
||||
g.prevent_sum_type_unwrapping_once = false
|
||||
|
||||
mut typ := g.comptime.get_type(node.expr)
|
||||
if node.expr.is_auto_deref_var() {
|
||||
if node.expr is ast.Ident {
|
||||
if node.expr.obj is ast.Var {
|
||||
typ = node.expr.obj.typ
|
||||
}
|
||||
}
|
||||
}
|
||||
if g.comptime.inside_comptime_for && typ == g.enum_data_type && node.field_name == 'value' {
|
||||
// for comp-time enum.values
|
||||
return g.comptime.type_map['${g.comptime.comptime_for_enum_var}.typ']
|
||||
}
|
||||
field_name := node.field_name
|
||||
sym := g.table.sym(typ)
|
||||
final_sym := g.table.final_sym(typ)
|
||||
if (typ.has_flag(.variadic) || final_sym.kind == .array_fixed) && field_name == 'len' {
|
||||
return ast.int_type
|
||||
}
|
||||
if sym.kind == .chan {
|
||||
if field_name == 'closed' {
|
||||
return ast.bool_type
|
||||
} else if field_name in ['len', 'cap'] {
|
||||
return ast.u32_type
|
||||
}
|
||||
}
|
||||
mut has_field := false
|
||||
mut field := ast.StructField{}
|
||||
if field_name.len > 0 && field_name[0].is_capital() && sym.info is ast.Struct
|
||||
&& sym.language == .v {
|
||||
// x.Foo.y => access the embedded struct
|
||||
for embed in sym.info.embeds {
|
||||
embed_sym := g.table.sym(embed)
|
||||
if embed_sym.embed_name() == field_name {
|
||||
return embed
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if f := g.table.find_field(sym, field_name) {
|
||||
has_field = true
|
||||
field = f
|
||||
} else {
|
||||
// look for embedded field
|
||||
has_field = true
|
||||
g.table.find_field_from_embeds(sym, field_name) or { has_field = false }
|
||||
}
|
||||
if typ.has_flag(.generic) && !has_field {
|
||||
gs := g.table.sym(g.unwrap_generic(typ))
|
||||
if f := g.table.find_field(gs, field_name) {
|
||||
has_field = true
|
||||
field = f
|
||||
} else {
|
||||
// look for embedded field
|
||||
has_field = true
|
||||
g.table.find_field_from_embeds(gs, field_name) or { has_field = false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if has_field {
|
||||
field_sym := g.table.sym(field.typ)
|
||||
if field_sym.kind in [.sum_type, .interface] {
|
||||
if !prevent_sum_type_unwrapping_once {
|
||||
if scope_field := node.scope.find_struct_field(node.expr.str(), typ, field_name) {
|
||||
return scope_field.smartcasts.last()
|
||||
}
|
||||
}
|
||||
}
|
||||
return field.typ
|
||||
}
|
||||
if mut method := g.table.sym(g.unwrap_generic(typ)).find_method_with_generic_parent(field_name) {
|
||||
method.params = method.params[1..]
|
||||
method.name = ''
|
||||
fn_type := ast.new_type(g.table.find_or_register_fn_type(method, false, true))
|
||||
return fn_type
|
||||
}
|
||||
if sym.kind !in [.struct, .aggregate, .interface, .sum_type] {
|
||||
if sym.kind != .placeholder {
|
||||
unwrapped_sym := g.table.sym(g.unwrap_generic(typ))
|
||||
if unwrapped_sym.kind == .array_fixed && node.field_name == 'len' {
|
||||
return ast.int_type
|
||||
}
|
||||
}
|
||||
}
|
||||
return node.expr_type
|
||||
}
|
||||
|
||||
fn (mut g Gen) comptime_if_to_ifdef(name string, is_comptime_option bool) !string {
|
||||
match name {
|
||||
// platforms/os-es:
|
||||
|
@ -44,9 +44,13 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if node.expr is ast.Ident && g.comptime.inside_comptime_for
|
||||
&& g.comptime.is_comptime_var(node.expr) {
|
||||
expr_type = g.comptime.get_comptime_var_type(node.expr)
|
||||
} else if node.expr is ast.Ident && g.comptime.is_comptime_var(node.expr) {
|
||||
expr_type = g.comptime.get_type(node.expr)
|
||||
name = g.styp(g.unwrap_generic(expr_type.clear_flags(.shared_f, .result))).replace('*',
|
||||
'')
|
||||
} else if node.expr is ast.SelectorExpr && node.expr.expr is ast.Ident
|
||||
&& g.comptime.is_comptime_var(node.expr.expr) {
|
||||
expr_type = g.comptime_selector_type(node.expr)
|
||||
name = g.styp(g.unwrap_generic(expr_type.clear_flags(.shared_f, .result))).replace('*',
|
||||
'')
|
||||
}
|
||||
|
@ -1294,7 +1294,7 @@ fn (mut g Gen) gen_to_str_method_call(node ast.CallExpr) bool {
|
||||
} else if left_node is ast.Ident {
|
||||
if left_node.obj is ast.Var {
|
||||
if left_node.obj.ct_type_var != .no_comptime {
|
||||
rec_type = g.comptime.get_comptime_var_type(left_node)
|
||||
rec_type = g.comptime.get_type(left_node)
|
||||
g.gen_expr_to_string(left_node, rec_type)
|
||||
return true
|
||||
} else if left_node.obj.smartcasts.len > 0 {
|
||||
@ -1456,7 +1456,7 @@ fn (mut g Gen) resolve_comptime_args(func &ast.Fn, mut node_ ast.CallExpr, concr
|
||||
if mut call_arg.expr.obj is ast.Var {
|
||||
node_.args[i].typ = call_arg.expr.obj.typ
|
||||
if call_arg.expr.obj.ct_type_var !in [.generic_var, .generic_param, .no_comptime] {
|
||||
mut ctyp := g.comptime.get_comptime_var_type(call_arg.expr)
|
||||
mut ctyp := g.comptime.get_type(call_arg.expr)
|
||||
if ctyp != ast.void_type {
|
||||
arg_sym := g.table.sym(ctyp)
|
||||
param_sym := g.table.final_sym(param_typ)
|
||||
@ -1490,7 +1490,7 @@ fn (mut g Gen) resolve_comptime_args(func &ast.Fn, mut node_ ast.CallExpr, concr
|
||||
comptime_args[k] = ctyp
|
||||
}
|
||||
} else if call_arg.expr.obj.ct_type_var == .generic_param {
|
||||
mut ctyp := g.comptime.get_comptime_var_type(call_arg.expr)
|
||||
mut ctyp := g.comptime.get_type(call_arg.expr)
|
||||
if ctyp != ast.void_type {
|
||||
arg_sym := g.table.final_sym(call_arg.typ)
|
||||
param_typ_sym := g.table.sym(param_typ)
|
||||
@ -1561,7 +1561,7 @@ fn (mut g Gen) resolve_comptime_args(func &ast.Fn, mut node_ ast.CallExpr, concr
|
||||
}
|
||||
} else if mut call_arg.expr.right is ast.Ident {
|
||||
if g.comptime.get_ct_type_var(call_arg.expr.right) != .generic_var {
|
||||
mut ctyp := g.comptime.get_comptime_var_type(call_arg.expr.right)
|
||||
mut ctyp := g.comptime.get_type(call_arg.expr.right)
|
||||
if ctyp != ast.void_type {
|
||||
comptime_args[k] = ctyp
|
||||
if param_typ.nr_muls() > 0 && comptime_args[k].nr_muls() > 0 {
|
||||
@ -1658,7 +1658,7 @@ fn (mut g Gen) unwrap_receiver_type(node ast.CallExpr) (ast.Type, &ast.TypeSymbo
|
||||
if node.left.obj is ast.Var {
|
||||
if node.left.obj.smartcasts.len > 0 {
|
||||
if node.left.obj.ct_type_var == .smartcast {
|
||||
unwrapped_rec_type = g.unwrap_generic(g.comptime.get_comptime_var_type(node.left))
|
||||
unwrapped_rec_type = g.unwrap_generic(g.comptime.get_type(node.left))
|
||||
} else {
|
||||
unwrapped_rec_type = g.unwrap_generic(node.left.obj.smartcasts.last())
|
||||
cast_sym := g.table.sym(unwrapped_rec_type)
|
||||
@ -2171,7 +2171,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||
}
|
||||
mut typ := node.args[0].typ
|
||||
if g.comptime.is_comptime_var(node.args[0].expr) {
|
||||
ctyp := g.comptime.get_comptime_var_type(node.args[0].expr)
|
||||
ctyp := g.comptime.get_type(node.args[0].expr)
|
||||
if ctyp != ast.void_type {
|
||||
typ = ctyp
|
||||
}
|
||||
@ -2223,7 +2223,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
||||
if cast_sym.info is ast.Aggregate {
|
||||
typ = cast_sym.info.types[g.aggregate_type_idx]
|
||||
} else if expr.obj.ct_type_var == .smartcast {
|
||||
typ = g.unwrap_generic(g.comptime.get_comptime_var_type(expr))
|
||||
typ = g.unwrap_generic(g.comptime.get_type(expr))
|
||||
}
|
||||
}
|
||||
// handling println( var or { ... })
|
||||
@ -2575,7 +2575,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
|
||||
if i < node.expected_arg_types.len && node.expected_arg_types[i].has_flag(.generic)
|
||||
&& arg.expr.obj.ct_type_var !in [.generic_param, .no_comptime] {
|
||||
exp_option := node.expected_arg_types[i].has_flag(.option)
|
||||
expected_types[i] = g.unwrap_generic(g.comptime.get_comptime_var_type(arg.expr))
|
||||
expected_types[i] = g.unwrap_generic(g.comptime.get_type(arg.expr))
|
||||
if !exp_option {
|
||||
expected_types[i] = expected_types[i].clear_flag(.option)
|
||||
}
|
||||
@ -2609,7 +2609,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
|
||||
} else if arg.expr is ast.ComptimeSelector && i < node.expected_arg_types.len
|
||||
&& node.expected_arg_types[i].has_flag(.generic) {
|
||||
exp_option := node.expected_arg_types[i].has_flag(.option)
|
||||
expected_types[i] = g.unwrap_generic(g.comptime.get_comptime_var_type(arg.expr))
|
||||
expected_types[i] = g.unwrap_generic(g.comptime.get_type(arg.expr))
|
||||
if !exp_option {
|
||||
expected_types[i] = expected_types[i].clear_flag(.option)
|
||||
}
|
||||
@ -2776,7 +2776,7 @@ fn (mut g Gen) keep_alive_call_postgen(node ast.CallExpr, tmp_cnt_save int) {
|
||||
@[inline]
|
||||
fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang ast.Language, is_smartcast bool) {
|
||||
arg_typ := if arg.expr is ast.ComptimeSelector {
|
||||
g.unwrap_generic(g.comptime.get_comptime_var_type(arg.expr))
|
||||
g.unwrap_generic(g.comptime.get_type(arg.expr))
|
||||
} else {
|
||||
g.unwrap_generic(arg.typ)
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
|
||||
if (node.cond is ast.Ident && g.comptime.is_comptime_var(node.cond))
|
||||
|| node.cond is ast.ComptimeSelector {
|
||||
mut unwrapped_typ := g.unwrap_generic(node.cond_type)
|
||||
ctyp := g.comptime.get_comptime_var_type(node.cond)
|
||||
ctyp := g.comptime.get_type(node.cond)
|
||||
if ctyp != ast.void_type {
|
||||
unwrapped_typ = g.unwrap_generic(ctyp)
|
||||
is_comptime = true
|
||||
@ -223,7 +223,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
|
||||
|
||||
if is_comptime && g.comptime.is_comptime_var(node.cond) {
|
||||
mut unwrapped_typ := g.unwrap_generic(node.cond_type)
|
||||
ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(node.cond))
|
||||
ctyp := g.unwrap_generic(g.comptime.get_type(node.cond))
|
||||
if ctyp != ast.void_type {
|
||||
unwrapped_typ = ctyp
|
||||
}
|
||||
|
@ -96,13 +96,13 @@ fn (mut g Gen) infix_expr_arrow_op(node ast.InfixExpr) {
|
||||
|
||||
// infix_expr_eq_op generates code for `==` and `!=`
|
||||
fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) {
|
||||
left_type := if node.left is ast.ComptimeSelector {
|
||||
g.comptime.get_comptime_var_type(node.left)
|
||||
left_type := if g.comptime.is_comptime_expr(node.left) {
|
||||
g.comptime.get_expr_type(node.left)
|
||||
} else {
|
||||
node.left_type
|
||||
}
|
||||
right_type := if node.right is ast.ComptimeSelector {
|
||||
g.comptime.get_comptime_var_type(node.right)
|
||||
right_type := if g.comptime.is_comptime_expr(node.right) {
|
||||
g.comptime.get_expr_type(node.right)
|
||||
} else {
|
||||
node.right_type
|
||||
}
|
||||
@ -796,7 +796,7 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, left_type ast.Type, rig
|
||||
// infix_expr_is_op generates code for `is` and `!is`
|
||||
fn (mut g Gen) infix_expr_is_op(node ast.InfixExpr) {
|
||||
mut left_sym := if g.comptime.is_comptime_var(node.left) {
|
||||
g.table.sym(g.unwrap_generic(g.comptime.get_comptime_var_type(node.left)))
|
||||
g.table.sym(g.unwrap_generic(g.comptime.get_type(node.left)))
|
||||
} else {
|
||||
g.table.sym(node.left_type)
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ fn (mut g Gen) str_val(node ast.StringInterLiteral, i int, fmts []u8) {
|
||||
mut exp_typ := typ
|
||||
if expr is ast.Ident {
|
||||
if g.comptime.get_ct_type_var(expr) == .smartcast {
|
||||
exp_typ = g.comptime.get_comptime_var_type(expr)
|
||||
exp_typ = g.comptime.get_type(expr)
|
||||
} else if expr.obj is ast.Var {
|
||||
if expr.obj.smartcasts.len > 0 {
|
||||
exp_typ = g.unwrap_generic(expr.obj.smartcasts.last())
|
||||
@ -245,7 +245,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
||||
mut fmts := node_.fmts.clone()
|
||||
for i, mut expr in node_.exprs {
|
||||
if g.comptime.is_comptime_var(expr) {
|
||||
ctyp := g.comptime.get_comptime_var_type(expr)
|
||||
ctyp := g.comptime.get_type(expr)
|
||||
if ctyp != ast.void_type {
|
||||
node_.expr_types[i] = ctyp
|
||||
if node_.fmts[i] == `_` {
|
||||
|
@ -53,6 +53,7 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
if mut sym.info is ast.Struct {
|
||||
is_anon = sym.info.is_anon
|
||||
}
|
||||
is_generic_default := sym.kind !in [.struct, .array_fixed] && node.typ.has_flag(.generic) // T{}
|
||||
is_array := sym.kind in [.array_fixed, .array]
|
||||
if sym.kind == .array_fixed {
|
||||
arr_info := sym.array_fixed_info()
|
||||
@ -63,7 +64,7 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
// detect if we need type casting on msvc initialization
|
||||
const_msvc_init := g.is_cc_msvc && g.inside_const && !g.inside_cast && g.inside_array_item
|
||||
|
||||
if !g.inside_cinit && !is_anon && !is_array && !const_msvc_init {
|
||||
if !g.inside_cinit && !is_anon && !is_generic_default && !is_array && !const_msvc_init {
|
||||
g.write('(')
|
||||
defer {
|
||||
g.write(')')
|
||||
@ -128,6 +129,8 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
}
|
||||
} else if is_multiline {
|
||||
g.writeln('(${styp}){')
|
||||
} else if is_generic_default {
|
||||
g.write(g.type_default(node.typ))
|
||||
} else {
|
||||
g.write('(${styp}){')
|
||||
}
|
||||
@ -356,7 +359,7 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
g.indent--
|
||||
}
|
||||
|
||||
if !initialized {
|
||||
if !initialized && !is_generic_default {
|
||||
if nr_fields > 0 {
|
||||
g.write('0')
|
||||
} else {
|
||||
@ -364,7 +367,7 @@ fn (mut g Gen) struct_init(node ast.StructInit) {
|
||||
}
|
||||
}
|
||||
|
||||
if !is_array_fixed_struct_init {
|
||||
if !is_array_fixed_struct_init && !is_generic_default {
|
||||
g.write('}')
|
||||
}
|
||||
if g.is_shared && !g.inside_opt_data && !g.is_arraymap_set {
|
||||
|
@ -0,0 +1,56 @@
|
||||
module main
|
||||
|
||||
struct Decoder {
|
||||
json string
|
||||
}
|
||||
|
||||
pub fn decode[T](val string) !T {
|
||||
mut decoder := Decoder{
|
||||
json: val
|
||||
}
|
||||
|
||||
mut result := T{}
|
||||
decoder.decode_value(mut &result)!
|
||||
return result
|
||||
}
|
||||
|
||||
fn (mut decoder Decoder) decode_value[T](mut val T) ! {
|
||||
$if T.unaliased_typ is $array {
|
||||
mut array_element := create_array_element(val)
|
||||
|
||||
decoder.decode_value(mut array_element)!
|
||||
|
||||
val << array_element
|
||||
|
||||
assert val.len == 1
|
||||
assert val[0] == array_element
|
||||
} $else $if T.unaliased_typ is $map {
|
||||
mut map_value := create_map_value(val)
|
||||
|
||||
decoder.decode_value(mut map_value)!
|
||||
|
||||
val['key'] = map_value
|
||||
|
||||
assert val.len == 1
|
||||
assert val['key'] == map_value
|
||||
}
|
||||
}
|
||||
|
||||
fn create_array_element[T](array []T) T {
|
||||
return T{}
|
||||
}
|
||||
|
||||
fn create_map_value[K, V](map_ map[K]V) V {
|
||||
return V{}
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
assert decode[[]int]('[1, 2, 3]')! == [0]
|
||||
assert decode[[]string]('["1", "2", "3"]')! == ['']
|
||||
assert decode[map[string]int]('{"a": 1}')! == {
|
||||
'key': 0
|
||||
}
|
||||
assert decode[map[string]string]('{"val": "2"}')! == {
|
||||
'key': ''
|
||||
}
|
||||
}
|
64
vlib/v/tests/comptime/comptime_default_value_test.v
Normal file
64
vlib/v/tests/comptime/comptime_default_value_test.v
Normal file
@ -0,0 +1,64 @@
|
||||
module main
|
||||
|
||||
struct Decoder {
|
||||
json string
|
||||
}
|
||||
|
||||
pub fn decode[T](val string) !T {
|
||||
mut decoder := Decoder{
|
||||
json: val
|
||||
}
|
||||
|
||||
mut result := T{}
|
||||
decoder.decode_value(mut &result)!
|
||||
return result
|
||||
}
|
||||
|
||||
fn (mut decoder Decoder) decode_value[T](mut val T) ! {
|
||||
$if T is $array {
|
||||
mut array_element := create_array_element(val)
|
||||
|
||||
decoder.decode_value(mut array_element)!
|
||||
println(array_element)
|
||||
dump(array_element)
|
||||
assert &array_element != unsafe { nil }
|
||||
|
||||
val << array_element
|
||||
} $else $if T is $map {
|
||||
mut map_value := create_map_value(val)
|
||||
|
||||
decoder.decode_value(mut map_value)!
|
||||
println(map_value)
|
||||
dump(map_value)
|
||||
assert &map_value != unsafe { nil }
|
||||
|
||||
val['key'] = map_value
|
||||
}
|
||||
}
|
||||
|
||||
fn create_array_element[T](array []T) T {
|
||||
a := T{}
|
||||
dump(a)
|
||||
dump(a.str)
|
||||
assert a.str != unsafe { nil }
|
||||
return a
|
||||
}
|
||||
|
||||
fn create_map_value[K, V](map_ map[K]V) V {
|
||||
a := V{}
|
||||
dump(a)
|
||||
dump(a.str)
|
||||
assert a.str != unsafe { nil }
|
||||
return a
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
assert decode[[]string]('["1", "2", "3"]')! == ['']
|
||||
assert decode[[]int]('[1, 2, 3]')! == [0]
|
||||
assert decode[map[string]string]('{"val": "2"}')! == {
|
||||
'key': ''
|
||||
}
|
||||
assert decode[map[string]int]('{"a": 1}')! == {
|
||||
'key': 0
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user