Skip to content

Commit

Permalink
v: comptime refactor and cleanup (#20196)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp committed Dec 19, 2023
1 parent 9ea039e commit 9c4e494
Show file tree
Hide file tree
Showing 20 changed files with 689 additions and 595 deletions.
16 changes: 8 additions & 8 deletions vlib/v/checker/assign.v
Expand Up @@ -142,8 +142,8 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
&& ((left.info as ast.IdentVar).share == .shared_t || left_type.has_flag(.shared_f))
&& c.table.sym(left_type).kind in [.array, .map, .struct_]
}
if c.inside_comptime_for_field && mut left is ast.ComptimeSelector {
left_type = c.comptime_fields_default_type
if c.comptime.comptime_for_field_var != '' && mut left is ast.ComptimeSelector {
left_type = c.comptime.comptime_for_field_type
c.expected_type = c.unwrap_generic(left_type)
}
if node.right_types.len < node.left.len { // first type or multi return types added above
Expand Down Expand Up @@ -183,7 +183,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
right_type = right_type.clear_flag(.option)
}
} else if right is ast.ComptimeSelector {
right_type = c.comptime_fields_default_type
right_type = c.comptime.comptime_for_field_type
}
if is_decl || is_shared_re_assign {
// check generic struct init and return unwrap generic struct type
Expand Down Expand Up @@ -351,12 +351,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if right is ast.ComptimeSelector {
if is_decl {
left.obj.ct_type_var = .field_var
left.obj.typ = c.comptime_fields_default_type
left.obj.typ = c.comptime.comptime_for_field_type
}
} else if mut right is ast.Ident && right.obj is ast.Var
&& right.or_expr.kind == .absent {
if (right.obj as ast.Var).ct_type_var != .no_comptime {
ctyp := c.get_comptime_var_type(right)
ctyp := c.comptime.get_comptime_var_type(right)
if ctyp != ast.void_type {
left.obj.ct_type_var = (right.obj as ast.Var).ct_type_var
left.obj.typ = ctyp
Expand All @@ -365,7 +365,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
} else if right is ast.DumpExpr
&& right.expr is ast.ComptimeSelector {
left.obj.ct_type_var = .field_var
left.obj.typ = c.comptime_fields_default_type
left.obj.typ = c.comptime.comptime_for_field_type
}
}
ast.GlobalField {
Expand Down Expand Up @@ -766,8 +766,8 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
}
} else {
// allow `t.$(field.name) = 0` where `t.$(field.name)` is a enum
if c.inside_comptime_for_field && left is ast.ComptimeSelector {
field_sym := c.table.sym(c.unwrap_generic(c.comptime_fields_default_type))
if c.comptime.comptime_for_field_var != '' && left is ast.ComptimeSelector {
field_sym := c.table.sym(c.unwrap_generic(c.comptime.comptime_for_field_type))

if field_sym.kind == .enum_ && !right_type.is_int() {
c.error('enums can only be assigned `int` values', right.pos())
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/checker/check_types.v
Expand Up @@ -235,7 +235,7 @@ fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, lan
}

if !expected.has_flag(.option) && got.has_flag(.option) && (arg.expr !is ast.Ident
|| (arg.expr is ast.Ident && c.get_ct_type_var(arg.expr) != .field_var)) {
|| (arg.expr is ast.Ident && c.comptime.get_ct_type_var(arg.expr) != .field_var)) {
got_typ_str, expected_typ_str := c.get_string_names_of(got, expected)
return error('cannot use `${got_typ_str}` as `${expected_typ_str}`, it must be unwrapped first')
}
Expand Down Expand Up @@ -919,9 +919,9 @@ fn (mut c Checker) infer_fn_generic_types(func ast.Fn, mut node ast.CallExpr) {
func_.name = ''
idx := c.table.find_or_register_fn_type(func_, true, false)
typ = ast.new_type(idx).derive(arg.typ)
} else if c.inside_comptime_for_field && sym.kind in [.struct_, .any]
} else if c.comptime.comptime_for_field_var != '' && sym.kind in [.struct_, .any]
&& arg.expr is ast.ComptimeSelector {
comptime_typ := c.get_comptime_selector_type(arg.expr, ast.void_type)
comptime_typ := c.comptime.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
48 changes: 23 additions & 25 deletions vlib/v/checker/checker.v
Expand Up @@ -12,6 +12,7 @@ import v.util.version
import v.errors
import v.pkgconfig
import v.transformer
import v.comptime

const int_min = int(0x80000000)
const int_max = int(0x7FFFFFFF)
Expand Down Expand Up @@ -82,7 +83,6 @@ pub mut:
inside_fn_arg bool // `a`, `b` in `a.f(b)`
inside_ct_attr bool // true inside `[if expr]`
inside_x_is_type bool // true inside the Type expression of `if x is Type {`
inside_comptime_for_field bool
inside_generic_struct_init bool
cur_struct_generic_types []ast.Type
cur_struct_concrete_types []ast.Type
Expand All @@ -108,16 +108,8 @@ mut:
loop_label string // set when inside a labelled for loop
vweb_gen_types []ast.Type // vweb route checks
timers &util.Timers = util.get_timers()
comptime_for_field_var string
comptime_for_variant_var string
comptime_fields_default_type ast.Type
comptime_fields_type map[string]ast.Type
comptime_for_field_value ast.StructField // value of the field variable
comptime_enum_field_value string // current enum value name
comptime_for_method string // $for method in T.methods {}
comptime_for_method_var string // $for method in T.methods {}; the variable name
comptime_for_method_ret_type ast.Type // $for method - current method.return_type field
comptime_values_stack []CurrentComptimeValues // stores the values from the above on each $for loop, to make nesting them easier
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 }
main_fn_decl_node ast.FnDecl
match_exhaustive_cutoff_limit int = 10
Expand Down Expand Up @@ -150,13 +142,18 @@ pub fn new_checker(table &ast.Table, pref_ &pref.Preferences) &Checker {
$if time_checking ? {
timers_should_print = true
}
return &Checker{
mut checker := &Checker{
table: table
pref: pref_
timers: util.new_timers(should_print: timers_should_print, label: 'checker')
match_exhaustive_cutoff_limit: pref_.checker_match_exhaustive_cutoff_limit
v_current_commit_hash: version.githash(pref_.building_v)
}
checker.comptime = &comptime.ComptimeInfo{
resolver: checker
table: table
}
return checker
}

fn (mut c Checker) reset_checker_state_at_start_of_new_file() {
Expand Down Expand Up @@ -1448,8 +1445,8 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
}
}
// evaluates comptime field.<name> (from T.fields)
if c.check_comptime_is_field_selector(node) {
if c.check_comptime_is_field_selector_bool(node) {
if c.comptime.check_comptime_is_field_selector(node) {
if c.comptime.check_comptime_is_field_selector_bool(node) {
node.expr_type = ast.bool_type
return node.expr_type
}
Expand All @@ -1472,9 +1469,10 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
c.error('`${node.expr}` does not return a value', node.pos)
node.expr_type = ast.void_type
return ast.void_type
} else if c.inside_comptime_for_field && typ == c.enum_data_type && node.field_name == 'value' {
} 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_fields_type['${c.comptime_for_field_var}.typ']
node.expr_type = c.comptime.type_map['${c.comptime.comptime_for_enum_var}.typ']
node.typ = typ
return node.expr_type
}
Expand Down Expand Up @@ -2169,7 +2167,7 @@ fn (mut c Checker) branch_stmt(node ast.BranchStmt) {
c.error('`${node.kind.str()}` is not allowed in defer statements', node.pos)
}
if c.in_for_count == 0 {
if c.inside_comptime_for_field {
if c.comptime.inside_comptime_for {
c.error('${node.kind.str()} is not allowed within a compile-time loop', node.pos)
} else {
c.error('${node.kind.str()} statement not within a loop', node.pos)
Expand Down Expand Up @@ -2712,11 +2710,11 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
c.expected_type = ast.string_type
node.expr_type = c.expr(mut node.expr)

if c.inside_comptime_for_field && node.expr is ast.Ident {
if c.table.is_comptime_var(node.expr) {
node.expr_type = c.get_comptime_var_type(node.expr as ast.Ident)
} else if (node.expr as ast.Ident).name in c.comptime_fields_type {
node.expr_type = c.comptime_fields_type[(node.expr as ast.Ident).name]
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)
} 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]
}
}
c.check_expr_opt_call(node.expr, node.expr_type)
Expand Down Expand Up @@ -2986,7 +2984,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
node.expr_type = c.expr(mut node.expr) // type to be casted

if mut node.expr is ast.ComptimeSelector {
node.expr_type = c.get_comptime_selector_type(node.expr, node.expr_type)
node.expr_type = c.comptime.get_comptime_selector_type(node.expr, node.expr_type)
}

mut from_type := c.unwrap_generic(node.expr_type)
Expand Down Expand Up @@ -3476,8 +3474,8 @@ 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 := if c.table.is_comptime_var(node) {
ctype := c.get_comptime_var_type(node)
typ := if c.comptime.is_comptime_var(node) {
ctype := c.comptime.get_comptime_var_type(node)
if ctype != ast.void_type {
ctype
} else {
Expand Down

0 comments on commit 9c4e494

Please sign in to comment.