Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v: refactor type resolver (split comptimeinfo logic) #23295

Merged
merged 3 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions vlib/v/checker/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,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_type(right)
ctyp := c.type_resolver.get_type(right)
if ctyp != ast.void_type {
left.obj.ct_type_var = right_obj_var.ct_type_var
left.obj.typ = ctyp
Expand All @@ -407,7 +407,8 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if left.obj.ct_type_var in [.generic_var, .no_comptime]
&& c.table.cur_fn != unsafe { nil }
&& c.table.cur_fn.generic_names.len != 0
&& !right.comptime_ret_val && c.is_generic_expr(right) {
&& !right.comptime_ret_val
&& c.type_resolver.is_generic_expr(right) {
// mark variable as generic var because its type changes according to fn return generic resolution type
left.obj.ct_type_var = .generic_var
if right.return_type_generic.has_flag(.generic) {
Expand All @@ -419,7 +420,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
} else {
fn_ret_type.clear_option_and_result()
}
c.comptime.type_map['g.${left.name}.${left.obj.pos.pos}'] = var_type
c.type_resolver.type_map['g.${left.name}.${left.obj.pos.pos}'] = var_type
}
} else if right.is_static_method
&& right.left_type.has_flag(.generic) {
Expand All @@ -429,7 +430,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
} else {
fn_ret_type.clear_option_and_result()
}
c.comptime.type_map['g.${left.name}.${left.obj.pos.pos}'] = var_type
c.type_resolver.type_map['g.${left.name}.${left.obj.pos.pos}'] = var_type
}
}
}
Expand Down Expand Up @@ -505,7 +506,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if (left.is_map || left.is_farray) && left.is_setter {
left.recursive_mapset_is_setter(true)
}
right_type = c.comptime.get_type_or_default(right, right_type)
right_type = c.type_resolver.get_type_or_default(right, right_type)
}
if mut left is ast.InfixExpr {
c.error('cannot use infix expression on the left side of `${node.op}`',
Expand Down
6 changes: 4 additions & 2 deletions vlib/v/checker/check_types.v
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,8 @@ fn (mut c Checker) infer_fn_generic_types(func &ast.Fn, mut node ast.CallExpr) {
typ = ast.new_type(idx).derive(arg.typ)
} else if c.comptime.comptime_for_field_var != '' && sym.kind in [.struct, .any]
&& arg.expr is ast.ComptimeSelector {
comptime_typ := c.comptime.get_comptime_selector_type(arg.expr, ast.void_type)
comptime_typ := c.type_resolver.get_comptime_selector_type(arg.expr,
ast.void_type)
if comptime_typ != ast.void_type {
typ = comptime_typ
if func.return_type.has_flag(.generic)
Expand Down Expand Up @@ -1121,7 +1122,8 @@ fn (mut c Checker) infer_fn_generic_types(func &ast.Fn, mut node ast.CallExpr) {
}
// resolve lambda with generic return type
if arg.expr is ast.LambdaExpr && typ.has_flag(.generic) {
typ = c.comptime.unwrap_generic_expr(arg.expr.expr, typ)
typ = c.type_resolver.unwrap_generic_expr(arg.expr.expr,
typ)
if typ.has_flag(.generic) {
lambda_ret_gt_name := c.table.type_to_str(typ)
idx := func.generic_names.index(lambda_ret_gt_name)
Expand Down
28 changes: 13 additions & 15 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import v.util.version
import v.errors
import v.pkgconfig
import v.transformer
import v.comptime
import v.type_resolver

// prevent stack overflows by restricting too deep recursion:
const expr_level_cutoff_limit = 40
Expand Down Expand Up @@ -116,9 +116,9 @@ mut:
loop_labels []string // filled, when inside labelled for loops: `a_label: for x in 0..10 {`
vweb_gen_types []ast.Type // vweb route checks
timers &util.Timers = util.get_timers()
comptime_info_stack []comptime.ComptimeInfo // stores the values from the above on each $for loop, to make nesting them easier
comptime comptime.ComptimeInfo
fn_scope &ast.Scope = unsafe { nil }
type_resolver type_resolver.TypeResolver
comptime &type_resolver.ResolverInfo = unsafe { nil }
fn_scope &ast.Scope = unsafe { nil }
main_fn_decl_node ast.FnDecl
match_exhaustive_cutoff_limit int = 10
is_last_stmt bool
Expand Down Expand Up @@ -164,10 +164,8 @@ pub fn new_checker(table &ast.Table, pref_ &pref.Preferences) &Checker {
v_current_commit_hash: if pref_.building_v { version.githash(pref_.vroot) or {
@VCURRENTHASH} } else { @VCURRENTHASH }
}
checker.comptime = &comptime.ComptimeInfo{
resolver: checker
table: table
}
checker.type_resolver = type_resolver.TypeResolver.new(table, checker)
checker.comptime = &checker.type_resolver.info
return checker
}

Expand Down Expand Up @@ -1674,7 +1672,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
} else if c.comptime.inside_comptime_for && typ == c.enum_data_type
&& node.field_name == 'value' {
// for comp-time enum.values
node.expr_type = c.comptime.type_map['${c.comptime.comptime_for_enum_var}.typ']
node.expr_type = c.type_resolver.type_map['${c.comptime.comptime_for_enum_var}.typ']
node.typ = typ
return node.expr_type
}
Expand Down Expand Up @@ -3056,9 +3054,9 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
}
if c.comptime.inside_comptime_for && mut node.expr is ast.Ident {
if node.expr.ct_expr {
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]
node.expr_type = c.type_resolver.get_type(node.expr as ast.Ident)
} else if (node.expr as ast.Ident).name in c.type_resolver.type_map {
node.expr_type = c.type_resolver.type_map[(node.expr as ast.Ident).name]
}
}
c.check_expr_option_or_result_call(node.expr, node.expr_type)
Expand Down Expand Up @@ -3348,9 +3346,9 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
c.inside_integer_literal_cast = old_inside_integer_literal_cast

if mut node.expr is ast.ComptimeSelector {
node.expr_type = c.comptime.get_comptime_selector_type(node.expr, node.expr_type)
node.expr_type = c.type_resolver.get_comptime_selector_type(node.expr, node.expr_type)
} else if node.expr is ast.Ident && c.comptime.is_comptime_variant_var(node.expr) {
node.expr_type = c.comptime.type_map['${c.comptime.comptime_for_variant_var}.typ']
node.expr_type = c.type_resolver.type_map['${c.comptime.comptime_for_variant_var}.typ']
}
mut from_type := c.unwrap_generic(node.expr_type)
from_sym := c.table.sym(from_type)
Expand Down Expand Up @@ -3960,7 +3958,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
// second use
if node.kind in [.constant, .global, .variable] {
info := node.info as ast.IdentVar
typ := c.comptime.get_type_or_default(node, info.typ)
typ := c.type_resolver.get_type_or_default(node, info.typ)
// Got a var with type T, return current generic type
if node.or_expr.kind != .absent {
if !typ.has_flag(.option) {
Expand Down
50 changes: 24 additions & 26 deletions vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import v.pref
import v.token
import v.util
import v.pkgconfig
import v.comptime
import v.type_resolver

fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
if node.left !is ast.EmptyExpr {
Expand Down Expand Up @@ -160,7 +160,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
}
}
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
return c.comptime.get_type(node)
return c.type_resolver.get_type(node)
}
if node.method_name == 'res' {
if !c.inside_defer {
Expand Down Expand Up @@ -240,17 +240,17 @@ fn (mut c Checker) comptime_selector(mut node ast.ComptimeSelector) ast.Type {
}
if mut node.field_expr is ast.SelectorExpr {
left_pos := node.field_expr.expr.pos()
if c.comptime.type_map.len == 0 {
if c.type_resolver.type_map.len == 0 {
c.error('compile time field access can only be used when iterating over `T.fields`',
left_pos)
}
expr_type = c.comptime.get_comptime_selector_type(node, ast.void_type)
expr_type = c.type_resolver.get_comptime_selector_type(node, ast.void_type)
if expr_type != ast.void_type {
return expr_type
}
expr_name := node.field_expr.expr.str()
if expr_name in c.comptime.type_map {
return c.comptime.type_map[expr_name]
if expr_name in c.type_resolver.type_map {
return c.type_resolver.type_map[expr_name]
}
c.error('unknown `\$for` variable `${expr_name}`', left_pos)
} else {
Expand Down Expand Up @@ -300,8 +300,8 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
}
c.comptime.comptime_for_field_value = field
c.comptime.comptime_for_field_var = node.val_var
c.comptime.type_map[node.val_var] = c.field_data_type
c.comptime.type_map['${node.val_var}.typ'] = node.typ
c.type_resolver.type_map[node.val_var] = c.field_data_type
c.type_resolver.type_map['${node.val_var}.typ'] = node.typ
c.comptime.comptime_for_field_type = field.typ
c.stmts(mut node.stmts)

Expand Down Expand Up @@ -345,8 +345,8 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
c.enum_data_type = c.table.find_type('EnumData')
}
c.comptime.comptime_for_enum_var = node.val_var
c.comptime.type_map[node.val_var] = c.enum_data_type
c.comptime.type_map['${node.val_var}.typ'] = node.typ
c.type_resolver.type_map[node.val_var] = c.enum_data_type
c.type_resolver.type_map['${node.val_var}.typ'] = node.typ
c.stmts(mut node.stmts)
c.pop_comptime_info()
c.table.used_features.comptime_for = true
Expand All @@ -363,7 +363,7 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
c.comptime.comptime_for_method = unsafe { &method }
c.comptime.comptime_for_method_var = node.val_var
c.comptime.comptime_for_method_ret_type = method.return_type
c.comptime.type_map['${node.val_var}.return_type'] = method.return_type
c.type_resolver.type_map['${node.val_var}.return_type'] = method.return_type
c.stmts(mut node.stmts)
c.pop_comptime_info()
}
Expand Down Expand Up @@ -398,8 +398,8 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
c.push_new_comptime_info()
c.comptime.inside_comptime_for = true
c.comptime.comptime_for_variant_var = node.val_var
c.comptime.type_map[node.val_var] = c.variant_data_type
c.comptime.type_map['${node.val_var}.typ'] = variant
c.type_resolver.type_map[node.val_var] = c.variant_data_type
c.type_resolver.type_map['${node.val_var}.typ'] = variant
c.stmts(mut node.stmts)
c.pop_comptime_info()
}
Expand Down Expand Up @@ -833,7 +833,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
} else if cond.left is ast.TypeNode && mut cond.right is ast.ComptimeType {
left := cond.left as ast.TypeNode
checked_type := c.unwrap_generic(left.typ)
return if c.comptime.is_comptime_type(checked_type, cond.right) {
return if c.type_resolver.is_comptime_type(checked_type, cond.right) {
.eval
} else {
.skip
Expand All @@ -844,8 +844,10 @@ 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_type(cond.left)
return if c.comptime.is_comptime_type(checked_type, comptime_type) {
checked_type := c.type_resolver.get_type(cond.left)
return if c.type_resolver.is_comptime_type(checked_type,
comptime_type)
{
.eval
} else {
.skip
Expand All @@ -854,7 +856,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
&& cond.left.name_type != 0 {
// T.unaliased_typ
checked_type := c.unwrap_generic(cond.left.name_type)
return if c.comptime.is_comptime_type(c.table.unaliased_type(checked_type),
return if c.type_resolver.is_comptime_type(c.table.unaliased_type(checked_type),
comptime_type)
{
.eval
Expand Down Expand Up @@ -1085,7 +1087,7 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr
ast.SelectorExpr {
if c.comptime.check_comptime_is_field_selector(cond) {
if c.comptime.check_comptime_is_field_selector_bool(cond) {
ret_bool := c.comptime.get_comptime_selector_bool_field(cond.field_name)
ret_bool := c.type_resolver.get_comptime_selector_bool_field(cond.field_name)
return if ret_bool { .eval } else { .skip }
}
c.error('unknown field `${cond.field_name}` from ${c.comptime.comptime_for_field_var}',
Expand All @@ -1102,10 +1104,8 @@ fn (mut c Checker) comptime_if_cond(mut cond ast.Expr, pos token.Pos) ComptimeBr

// push_new_comptime_info saves the current comptime information
fn (mut c Checker) push_new_comptime_info() {
c.comptime_info_stack << comptime.ComptimeInfo{
resolver: c.comptime.resolver
table: c.comptime.table
type_map: c.comptime.type_map.clone()
c.type_resolver.info_stack << type_resolver.ResolverInfo{
saved_type_map: c.type_resolver.type_map.clone()
inside_comptime_for: c.comptime.inside_comptime_for
comptime_for_variant_var: c.comptime.comptime_for_variant_var
comptime_for_field_var: c.comptime.comptime_for_field_var
Expand All @@ -1120,10 +1120,8 @@ fn (mut c Checker) push_new_comptime_info() {

// pop_comptime_info pops the current comptime information frame
fn (mut c Checker) pop_comptime_info() {
old := c.comptime_info_stack.pop()
c.comptime.resolver = old.resolver
c.comptime.table = old.table
c.comptime.type_map = old.type_map.clone()
old := c.type_resolver.info_stack.pop()
c.type_resolver.type_map = old.saved_type_map.clone()
c.comptime.inside_comptime_for = old.inside_comptime_for
c.comptime.comptime_for_variant_var = old.comptime_for_variant_var
c.comptime.comptime_for_field_var = old.comptime_for_field_var
Expand Down
46 changes: 7 additions & 39 deletions vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -1805,7 +1805,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
continue
}
c.check_expected_call_arg(utyp, unwrap_typ, node.language, call_arg) or {
if c.comptime.type_map.len > 0 {
if c.type_resolver.type_map.len > 0 {
continue
}
if mut call_arg.expr is ast.LambdaExpr {
Expand Down Expand Up @@ -1885,38 +1885,6 @@ fn (mut c Checker) register_trace_call(node &ast.CallExpr, func &ast.Fn) {
}
}

// is_generic_expr checks if the expr relies on fn generic argument
fn (mut c Checker) is_generic_expr(node ast.Expr) bool {
return match node {
ast.Ident {
// variable declared as generic type
c.comptime.is_generic_param_var(node)
}
ast.IndexExpr {
// generic_var[N]
c.comptime.is_generic_param_var(node.left)
}
ast.CallExpr {
// fn which has any generic dependent expr
if node.args.any(c.comptime.is_generic_param_var(it.expr)) {
return true
}
if node.is_static_method && node.left_type.has_flag(.generic) {
return true
}
// fn[T]() or generic_var.fn[T]()
node.concrete_types.any(it.has_flag(.generic))
}
ast.SelectorExpr {
// generic_var.property
c.comptime.is_generic_param_var(node.expr)
}
else {
false
}
}
}

fn (mut c Checker) resolve_comptime_args(func &ast.Fn, node_ ast.CallExpr, concrete_types []ast.Type) map[int]ast.Type {
mut comptime_args := map[int]ast.Type{}
has_dynamic_vars := (c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len > 0)
Expand All @@ -1938,7 +1906,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_type(call_arg.expr)
mut ctyp := c.type_resolver.get_type(call_arg.expr)
if ctyp != ast.void_type {
arg_sym := c.table.sym(ctyp)
param_sym := c.table.final_sym(param_typ)
Expand All @@ -1961,7 +1929,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_type(call_arg.expr)
mut ctyp := c.type_resolver.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)
Expand Down Expand Up @@ -2024,7 +1992,7 @@ 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_type(call_arg.expr)
mut ctyp := c.type_resolver.get_type(call_arg.expr)
if node_.args[i].expr.is_auto_deref_var() {
ctyp = ctyp.deref()
}
Expand All @@ -2036,14 +2004,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_type(call_arg.expr.right)
comptime_args[k] = c.type_resolver.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_type(call_arg.expr)
ct_value := c.type_resolver.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)
Expand All @@ -2068,7 +2036,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_type(call_arg.expr)
comptime_args[k] = c.type_resolver.get_type(call_arg.expr)
}
}
}
Expand Down
Loading
Loading