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: comptime refactor #20196

Merged
merged 24 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
16 changes: 8 additions & 8 deletions vlib/v/checker/assign.v
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Loading
Loading