cgen: more fixes
This commit is contained in:
1 parent
d503144a37
commit
ee64e962b8
7 files changed
+134
-44
No files matched your search
@@ -986,8 +986,25 @@ fn (mut c Checker) symmetric_check(left ast.Type, right ast.Type) bool {
|
||||
}
|
||||
|
||||
fn (c &Checker) generic_type_args_and_parent_idx(typ ast.Type) ([]ast.Type, int) {
|
||||
base_typ := c.table.fully_unaliased_type(typ.clear_flags().clear_option_and_result())
|
||||
mut base_typ := c.table.fully_unaliased_type(typ.clear_flags().clear_option_and_result())
|
||||
if base_typ.nr_muls() > 0 {
|
||||
base_typ = base_typ.deref()
|
||||
}
|
||||
sym := c.table.sym(base_typ)
|
||||
parse_type_args_from_name := fn [c] (name string) []ast.Type {
|
||||
if !name.contains('[') || !name.ends_with(']') {
|
||||
return []ast.Type{}
|
||||
}
|
||||
mut parsed := []ast.Type{}
|
||||
for arg_name in ast.split_generic_args(name.all_after_last('[').trim_right(']')) {
|
||||
idx := c.table.find_type_idx(arg_name.trim_space())
|
||||
if idx <= 0 {
|
||||
return []ast.Type{}
|
||||
}
|
||||
parsed << ast.idx_to_type(idx)
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
match sym.info {
|
||||
ast.Struct {
|
||||
mut type_args := sym.info.concrete_types.clone()
|
||||
@@ -997,7 +1014,12 @@ fn (c &Checker) generic_type_args_and_parent_idx(typ ast.Type) ([]ast.Type, int)
|
||||
if type_args.len == 0 {
|
||||
type_args = sym.info.generic_types.clone()
|
||||
}
|
||||
parent_idx := if sym.info.parent_type != 0 {
|
||||
if type_args.len == 0 {
|
||||
type_args = parse_type_args_from_name(sym.name)
|
||||
}
|
||||
parent_idx := if sym.parent_idx > 0 {
|
||||
sym.parent_idx
|
||||
} else if sym.info.parent_type != 0 {
|
||||
sym.info.parent_type.clear_flags().idx()
|
||||
} else {
|
||||
base_typ.idx()
|
||||
@@ -1012,7 +1034,12 @@ fn (c &Checker) generic_type_args_and_parent_idx(typ ast.Type) ([]ast.Type, int)
|
||||
if type_args.len == 0 {
|
||||
type_args = sym.info.generic_types.clone()
|
||||
}
|
||||
parent_idx := if sym.info.parent_type != 0 {
|
||||
if type_args.len == 0 {
|
||||
type_args = parse_type_args_from_name(sym.name)
|
||||
}
|
||||
parent_idx := if sym.parent_idx > 0 {
|
||||
sym.parent_idx
|
||||
} else if sym.info.parent_type != 0 {
|
||||
sym.info.parent_type.clear_flags().idx()
|
||||
} else {
|
||||
base_typ.idx()
|
||||
@@ -1027,7 +1054,12 @@ fn (c &Checker) generic_type_args_and_parent_idx(typ ast.Type) ([]ast.Type, int)
|
||||
if type_args.len == 0 {
|
||||
type_args = sym.info.generic_types.clone()
|
||||
}
|
||||
parent_idx := if sym.info.parent_type != 0 {
|
||||
if type_args.len == 0 {
|
||||
type_args = parse_type_args_from_name(sym.name)
|
||||
}
|
||||
parent_idx := if sym.parent_idx > 0 {
|
||||
sym.parent_idx
|
||||
} else if sym.info.parent_type != 0 {
|
||||
sym.info.parent_type.clear_flags().idx()
|
||||
} else {
|
||||
base_typ.idx()
|
||||
@@ -1130,8 +1162,30 @@ fn (c &Checker) infer_composite_generic_type(gt_name string, generic_typ ast.Typ
|
||||
|
||||
expected_type_args, expected_parent_idx := c.generic_type_args_and_parent_idx(generic_typ)
|
||||
actual_type_args, actual_parent_idx := c.generic_type_args_and_parent_idx(concrete_typ)
|
||||
if expected_parent_idx == 0 || expected_parent_idx != actual_parent_idx
|
||||
|| expected_type_args.len == 0 || expected_type_args.len != actual_type_args.len {
|
||||
if expected_parent_idx == 0 || actual_parent_idx == 0 || expected_type_args.len == 0
|
||||
|| expected_type_args.len != actual_type_args.len {
|
||||
return ast.void_type
|
||||
}
|
||||
if expected_parent_idx != actual_parent_idx {
|
||||
expected_parent_sym := c.table.sym(ast.idx_to_type(expected_parent_idx))
|
||||
actual_parent_sym := c.table.sym(ast.idx_to_type(actual_parent_idx))
|
||||
expected_parent_name := if expected_parent_sym.ngname != '' {
|
||||
expected_parent_sym.ngname
|
||||
} else {
|
||||
ast.strip_generic_params(expected_parent_sym.name)
|
||||
}
|
||||
actual_parent_name := if actual_parent_sym.ngname != '' {
|
||||
actual_parent_sym.ngname
|
||||
} else {
|
||||
ast.strip_generic_params(actual_parent_sym.name)
|
||||
}
|
||||
if expected_parent_name != actual_parent_name
|
||||
&& expected_parent_sym.parent_idx != actual_parent_idx
|
||||
&& actual_parent_sym.parent_idx != expected_parent_idx {
|
||||
return ast.void_type
|
||||
}
|
||||
}
|
||||
if expected_type_args.len == 0 || expected_type_args.len != actual_type_args.len {
|
||||
return ast.void_type
|
||||
}
|
||||
for i, expected_type_arg in expected_type_args {
|
||||
@@ -1465,7 +1519,6 @@ fn (mut c Checker) infer_fn_generic_types(func &ast.Fn, mut node ast.CallExpr) {
|
||||
if !param_is_interface && param_sym.kind == .generic_inst {
|
||||
param_is_interface = c.table.type_symbols[(param_sym.info as ast.GenericInst).parent_idx].kind == .interface
|
||||
}
|
||||
|
||||
if (param_infer_typ.has_flag(.option) && arg.typ.has_flag(.option))
|
||||
|| (param_infer_typ.has_flag(.result) && arg.typ.has_flag(.result)) {
|
||||
param_inner := param_infer_typ.clear_option_and_result()
|
||||
@@ -1669,6 +1722,30 @@ fn (mut c Checker) infer_fn_generic_types(func &ast.Fn, mut node ast.CallExpr) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if typ == ast.void_type {
|
||||
typ = c.infer_composite_generic_type(gt_name, param_infer_typ, arg_typ)
|
||||
if typ == ast.void_type && arg.expr is ast.Ident && arg.expr.obj is ast.Var {
|
||||
init_expr := arg.expr.obj.expr
|
||||
if init_expr !is ast.EmptyExpr {
|
||||
init_typ := match init_expr {
|
||||
ast.CallExpr {
|
||||
if init_expr.return_type_generic != 0 {
|
||||
init_expr.return_type_generic
|
||||
} else {
|
||||
init_expr.return_type
|
||||
}
|
||||
}
|
||||
else {
|
||||
arg.expr.obj.typ
|
||||
}
|
||||
}
|
||||
if init_typ != 0 {
|
||||
typ = c.infer_composite_generic_type(gt_name, param_infer_typ,
|
||||
init_typ)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if typ != ast.void_type {
|
||||
arg_inferred << arg_i
|
||||
|
||||
+13
-26
@@ -1367,8 +1367,8 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
}
|
||||
g.writeln(';}')
|
||||
}
|
||||
} else if node.op == .assign && (is_fixed_array_init
|
||||
|| (unaliased_right_sym.kind == .array_fixed && val in [ast.Ident, ast.CastExpr])) {
|
||||
} else if node.op == .assign && (is_fixed_array_init || is_fixed_array_var
|
||||
|| (unaliased_right_sym.kind == .array_fixed && val is ast.CastExpr)) {
|
||||
// Fixed arrays
|
||||
if unaliased_left_sym.kind != .array_fixed && unaliased_right_sym.kind == .array_fixed
|
||||
&& (g.pref.translated || g.file.is_translated) {
|
||||
@@ -1399,37 +1399,24 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
g.writeln(', sizeof(${g.styp(var_type)}));')
|
||||
}
|
||||
} else {
|
||||
mut v_var := ''
|
||||
arr_typ := styp.trim('*')
|
||||
old_is_assign_lhs := g.is_assign_lhs
|
||||
g.is_assign_lhs = false
|
||||
left_expr := g.expr_string(left)
|
||||
mut fixed_right_expr := ''
|
||||
if is_fixed_array_init {
|
||||
right := val as ast.ArrayInit
|
||||
v_var = g.new_tmp_var()
|
||||
g.write('${arr_typ} ${v_var} = ')
|
||||
right_var := g.new_tmp_var()
|
||||
g.write('${arr_typ} ${right_var} = ')
|
||||
g.expr(right)
|
||||
g.writeln(';')
|
||||
fixed_right_expr = right_var
|
||||
} else {
|
||||
v_var = g.expr_string(val)
|
||||
}
|
||||
pos := g.out.len
|
||||
g.expr(left)
|
||||
|
||||
if g.is_arraymap_set && g.arraymap_set_pos >= 0 {
|
||||
if g.arraymap_set_pos > 0 {
|
||||
g.go_back_to(g.arraymap_set_pos)
|
||||
}
|
||||
g.write(', &${v_var})')
|
||||
g.is_arraymap_set = false
|
||||
g.arraymap_set_pos = 0
|
||||
} else {
|
||||
g.go_back_to(pos)
|
||||
is_var_mut := !is_decl && left.is_auto_deref_var()
|
||||
addr_left := if is_var_mut { '' } else { '&' }
|
||||
g.writeln('')
|
||||
g.write('memcpy(${addr_left}')
|
||||
g.expr(left)
|
||||
addr_val := if is_fixed_array_var { '' } else { '&' }
|
||||
g.writeln(', ${addr_val}${v_var}, sizeof(${arr_typ}));')
|
||||
fixed_right_expr = g.expr_string(val)
|
||||
}
|
||||
g.is_assign_lhs = old_is_assign_lhs
|
||||
g.writeln('')
|
||||
g.writeln('memcpy(${left_expr}, ${fixed_right_expr}, sizeof(${arr_typ}));')
|
||||
g.is_assign_lhs = false
|
||||
}
|
||||
} else {
|
||||
|
||||
+14
-6
@@ -4466,15 +4466,11 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
||||
// pointer-backed only when interface semantics require aliasing the
|
||||
// original storage. Plain value-to-interface conversions still need
|
||||
// a detached copy, even when the value itself lives in auto-heap storage.
|
||||
// The exception is values that already came from option/result unwrapping:
|
||||
// those are already detached heap objects and should be passed through
|
||||
// directly instead of being wrapped in HEAP(...) a second time.
|
||||
mut effective_got_is_ptr := got_is_ptr
|
||||
mut suppress_auto_heap_deref := false
|
||||
if !got_is_ptr && expr is ast.Ident && g.resolved_ident_is_auto_heap(expr)
|
||||
&& (g.expected_arg_mut
|
||||
|| g.interface_cast_requires_field_aliasing(expected_type, expr)
|
||||
|| g.ident_unwraps_option_or_result(expr)) {
|
||||
|| g.interface_cast_requires_field_aliasing(expected_type, expr)) {
|
||||
effective_got_is_ptr = true
|
||||
suppress_auto_heap_deref = true
|
||||
}
|
||||
@@ -9052,6 +9048,14 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||
type0 = type0.clear_flag(.result)
|
||||
}
|
||||
}
|
||||
if exprs_len > 0 && expr0 is ast.Ident && expr0.obj is ast.Var && expr0.obj.typ != 0 {
|
||||
resolved_obj_type := g.unwrap_generic(g.recheck_concrete_type(expr0.obj.typ))
|
||||
if resolved_obj_type != 0 && !resolved_obj_type.has_option_or_result()
|
||||
&& type0.has_option_or_result()
|
||||
&& type0.clear_option_and_result() == resolved_obj_type {
|
||||
type0 = resolved_obj_type
|
||||
}
|
||||
}
|
||||
|
||||
if exprs_len > 0 {
|
||||
// `$veb.html()` expands to statements, so the Result return
|
||||
@@ -11712,7 +11716,11 @@ return ${cast_shared_struct_str};
|
||||
mut adapter_params := ['void* _x']
|
||||
for i in 1 .. method.params.len {
|
||||
arg := method.params[i]
|
||||
arg_name := if arg.name.len > 0 { c_name(arg.name) } else { 'arg${i}' }
|
||||
arg_name := if arg.name.len > 0 && arg.name != '_' {
|
||||
c_name(arg.name)
|
||||
} else {
|
||||
'arg${i}'
|
||||
}
|
||||
adapter_params << '${g.styp(arg.typ)} ${arg_name}'
|
||||
adapter_args << arg_name
|
||||
}
|
||||
|
||||
@@ -43,7 +43,11 @@ fn (mut g Gen) comptime_call_expands_string_args(m &ast.Fn, node ast.ComptimeCal
|
||||
return false
|
||||
}
|
||||
array_decompose := node.args.last().expr as ast.ArrayDecompose
|
||||
if !g.is_string_array_type(array_decompose.expr_type) || m.params.len - 1 < node.args.len {
|
||||
mut array_type := g.resolved_expr_type(array_decompose.expr, array_decompose.expr_type)
|
||||
if array_type == ast.void_type {
|
||||
array_type = array_decompose.expr_type
|
||||
}
|
||||
if !g.is_string_array_type(array_type) || m.params.len - 1 < node.args.len {
|
||||
return false
|
||||
}
|
||||
return !g.is_string_array_type(m.params[node.args.len].typ)
|
||||
@@ -288,7 +292,7 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
|
||||
&& node.args[i - 1].expr is ast.ArrayDecompose {
|
||||
mut d_count := 0
|
||||
for d_i in i .. m.params.len {
|
||||
g.write('*(${g.styp(m.params[i].typ)}*)builtin__array_get(')
|
||||
g.write('*(${g.styp(m.params[d_i].typ)}*)builtin__array_get(')
|
||||
g.expr(ast.Expr(node.args[i - 1].expr))
|
||||
g.write(', ${d_count})')
|
||||
|
||||
|
||||
@@ -741,8 +741,11 @@ fn (mut g Gen) gen_simple_string_inter_literal(node ast.StringInterLiteral, fmts
|
||||
if i >= node.need_fmts.len || node.need_fmts[i] || i >= fmts.len || fmts[i] == `_` {
|
||||
return false
|
||||
}
|
||||
if node.expr_types[i].is_any_kind_of_pointer() || node.expr_types[i].is_int_valptr()
|
||||
|| node.expr_types[i].is_float_valptr() {
|
||||
normalized_expr_type := g.table.fully_unaliased_type(g.unwrap_generic(node.expr_types[i]))
|
||||
// Pointer aliases need the full `str_intp` path so nil formatting stays
|
||||
// consistent with plain pointer interpolation.
|
||||
if normalized_expr_type.is_any_kind_of_pointer() || normalized_expr_type.is_int_valptr()
|
||||
|| normalized_expr_type.is_float_valptr() {
|
||||
return false
|
||||
}
|
||||
// Interface types need the full str_intp path for vtable dispatch and
|
||||
|
||||
@@ -851,6 +851,16 @@ fn (mut g Gen) resolved_expr_type(expr ast.Expr, default_typ ast.Type) ast.Type
|
||||
mut resolved := g.resolved_expr_type(expr.obj.expr, expr.obj.typ)
|
||||
if resolved != 0 {
|
||||
resolved = g.unwrap_generic(g.recheck_concrete_type(resolved))
|
||||
if expr.obj.typ != 0 {
|
||||
resolved_obj_type :=
|
||||
g.unwrap_generic(g.recheck_concrete_type(expr.obj.typ))
|
||||
if resolved_obj_type != 0
|
||||
&& !g.type_has_unresolved_generic_parts(resolved_obj_type)
|
||||
&& resolved.has_option_or_result()
|
||||
&& resolved.clear_option_and_result() == resolved_obj_type {
|
||||
return resolved_obj_type
|
||||
}
|
||||
}
|
||||
if g.type_has_unresolved_generic_parts(resolved) {
|
||||
call_like_type := g.resolved_call_like_expr_type(expr.obj.expr)
|
||||
if call_like_type != 0 && !call_like_type.has_flag(.generic)
|
||||
|
||||
@@ -143,13 +143,14 @@ fn find_tmpl_complex_at_expr_end(line string, start int) int {
|
||||
for i < line.len && is_tmpl_ident_part(line[i]) {
|
||||
i++
|
||||
}
|
||||
mut has_complex_suffix := false
|
||||
for i + 1 < line.len && line[i] == `.` && is_tmpl_ident_start(line[i + 1]) {
|
||||
i += 2
|
||||
has_complex_suffix = true
|
||||
for i < line.len && is_tmpl_ident_part(line[i]) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
mut has_complex_suffix := false
|
||||
for i < line.len {
|
||||
if line[i] == `[` {
|
||||
expr_end := find_tmpl_balanced_end(line, i, `[`, `]`)
|
||||
|
||||
Reference in new issue
Block a user