Skip to content

Commit

Permalink
ast: add Type.clear_option_and_result() and cleanup all the related c…
Browse files Browse the repository at this point in the history
…alls (#20443)
  • Loading branch information
yuyi98 committed Jan 9, 2024
1 parent 3635772 commit ee95e23
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 42 deletions.
6 changes: 6 additions & 0 deletions vlib/v/ast/types.v
Expand Up @@ -389,6 +389,12 @@ pub fn (t Type) clear_flags(flags ...TypeFlag) Type {
}
}

// clear option and result flags
@[inline]
pub fn (t Type) clear_option_and_result() Type {
return u32(t) & ~0x0300_0000
}

// return true if `flag` is set on `t`
@[inline]
pub fn (t Type) has_flag(flag TypeFlag) bool {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/check_types.v
Expand Up @@ -154,7 +154,7 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
&& expected.has_flag(.result)) {
// IError
return true
} else if !c.check_basic(got, expected.clear_flags(.option, .result)) {
} else if !c.check_basic(got, expected.clear_option_and_result()) {
return false
}
}
Expand Down
29 changes: 12 additions & 17 deletions vlib/v/checker/checker.v
Expand Up @@ -1271,22 +1271,20 @@ fn (mut c Checker) check_or_expr(node ast.OrExpr, ret_type ast.Type, expr_return
return
}
mut last_stmt := node.stmts.last()
c.check_or_last_stmt(mut last_stmt, ret_type, expr_return_type.clear_flags(.option,
.result))
c.check_or_last_stmt(mut last_stmt, ret_type, expr_return_type.clear_option_and_result())
}

fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, expr_return_type ast.Type) {
if ret_type != ast.void_type {
match mut stmt {
ast.ExprStmt {
c.expected_type = ret_type
c.expected_or_type = ret_type.clear_flags(.option, .result)
c.expected_or_type = ret_type.clear_option_and_result()
last_stmt_typ := c.expr(mut stmt.expr)

if last_stmt_typ.has_flag(.option) || last_stmt_typ == ast.none_type {
if stmt.expr in [ast.Ident, ast.SelectorExpr, ast.CallExpr, ast.None, ast.CastExpr] {
expected_type_name := c.table.type_to_str(ret_type.clear_flags(.option,
.result))
expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result())
got_type_name := c.table.type_to_str(last_stmt_typ)
c.error('`or` block must provide a value of type `${expected_type_name}`, not `${got_type_name}`',
stmt.expr.pos())
Expand Down Expand Up @@ -1319,8 +1317,7 @@ fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, expr
}
return
}
expected_type_name := c.table.type_to_str(ret_type.clear_flags(.option,
.result))
expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result())
c.error('`or` block must provide a default value of type `${expected_type_name}`, or return/continue/break or call a [noreturn] function like panic(err) or exit(1)',
stmt.expr.pos())
} else {
Expand All @@ -1332,8 +1329,7 @@ fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, expr
return
}
type_name := c.table.type_to_str(last_stmt_typ)
expected_type_name := c.table.type_to_str(ret_type.clear_flags(.option,
.result))
expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result())
c.error('wrong return type `${type_name}` in the `or {}` block, expected `${expected_type_name}`',
stmt.expr.pos())
}
Expand All @@ -1347,8 +1343,7 @@ fn (mut c Checker) check_or_last_stmt(mut stmt ast.Stmt, ret_type ast.Type, expr
}
ast.Return {}
else {
expected_type_name := c.table.type_to_str(ret_type.clear_flags(.option,
.result))
expected_type_name := c.table.type_to_str(ret_type.clear_option_and_result())
c.error('last statement in the `or {}` block should be an expression of type `${expected_type_name}` or exit parent scope',
stmt.pos)
}
Expand Down Expand Up @@ -1600,7 +1595,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
}
node.typ = field.typ
if node.or_block.kind == .block {
c.expected_or_type = node.typ.clear_flags(.option, .result)
c.expected_or_type = node.typ.clear_option_and_result()
c.stmts_ending_with_expression(mut node.or_block.stmts)
c.check_or_expr(node.or_block, node.typ, c.expected_or_type, node)
c.expected_or_type = ast.void_type
Expand Down Expand Up @@ -3509,7 +3504,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
c.error('cannot use `or {}` block on non-option variable', node.pos)
}
}
unwrapped_typ := typ.clear_flags(.option, .result)
unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
Expand Down Expand Up @@ -3583,7 +3578,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
}
}
} else {
typ = obj.expr.expr_type.clear_flags(.option, .result)
typ = obj.expr.expr_type.clear_option_and_result()
}
} else if obj.expr is ast.EmptyExpr {
c.error('invalid variable `${node.name}`', node.pos)
Expand Down Expand Up @@ -3618,7 +3613,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
node.pos)
}
}
unwrapped_typ := typ.clear_flags(.option, .result)
unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
Expand Down Expand Up @@ -3663,7 +3658,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {

if mut obj.expr is ast.CallExpr {
if obj.expr.or_block.kind != .absent {
typ = typ.clear_flags(.option, .result)
typ = typ.clear_option_and_result()
}
}
}
Expand All @@ -3676,7 +3671,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
node.obj = obj

if node.or_expr.kind != .absent {
unwrapped_typ := typ.clear_flags(.option, .result)
unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/checker/containers.v
Expand Up @@ -132,7 +132,7 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
c.expected_type.clear_flag(.shared_f).deref()
} else {
c.expected_type
}.clear_flags(.option, .result)
}.clear_option_and_result()
}
// `[1,2,3]`
if node.exprs.len > 0 && node.elem_type == ast.void_type {
Expand Down Expand Up @@ -366,7 +366,7 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
sym := c.table.sym(c.expected_type)
if sym.kind == .map {
info := sym.map_info()
node.typ = c.expected_type.clear_flags(.option, .result)
node.typ = c.expected_type.clear_option_and_result()
node.key_type = info.key_type
node.value_type = info.value_type
return node.typ
Expand Down
4 changes: 2 additions & 2 deletions vlib/v/checker/fn.v
Expand Up @@ -504,7 +504,7 @@ fn (mut c Checker) anon_fn(mut node ast.AnonFn) ast.Type {
}
}
} else {
var.typ = parent_var.expr.expr_type.clear_flags(.option, .result)
var.typ = parent_var.expr.expr_type.clear_option_and_result()
}
} else {
var.typ = parent_var.typ
Expand Down Expand Up @@ -2644,7 +2644,7 @@ fn (mut c Checker) check_map_and_filter(is_map bool, elem_typ ast.Type, node ast
} else if !is_map && arg_expr.return_type != ast.bool_type {
if arg_expr.or_block.kind != .absent && (arg_expr.return_type.has_flag(.option)
|| arg_expr.return_type.has_flag(.result))
&& arg_expr.return_type.clear_flags(.option, .result) == ast.bool_type {
&& arg_expr.return_type.clear_option_and_result() == ast.bool_type {
return
}
c.error('type mismatch, `${arg_expr.name}` must return a bool', arg_expr.pos)
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/for.v
Expand Up @@ -120,7 +120,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
if next_fn.params.len != 1 {
c.error('iterator method `next()` must have 0 parameters', node.cond.pos())
}
mut val_type := next_fn.return_type.clear_flags(.option, .result)
mut val_type := next_fn.return_type.clear_option_and_result()
if node.val_is_mut {
val_type = val_type.ref()
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/if.v
Expand Up @@ -70,7 +70,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
}
}
if mut branch.cond is ast.IfGuardExpr {
if branch.cond.expr_type.clear_flags(.option, .result) == ast.void_type
if branch.cond.expr_type.clear_option_and_result() == ast.void_type
&& !(branch.cond.vars.len == 1 && branch.cond.vars[0].name == '_') {
c.error('if guard expects non-propagate option or result', branch.pos)
continue
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/lambda_expr.v
Expand Up @@ -63,7 +63,7 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as

mut stmts := []ast.Stmt{}
mut has_return := false
if return_type.clear_flags(.option, .result) == ast.void_type {
if return_type.clear_option_and_result() == ast.void_type {
stmts << ast.ExprStmt{
pos: node.pos
expr: node.expr
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/assign.v
Expand Up @@ -775,7 +775,7 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
mut mr_styp := g.typ(return_type.clear_flag(.result))
if node.right[0] is ast.CallExpr && node.right[0].or_block.kind != .absent {
is_option = false
mr_styp = g.typ(return_type.clear_flags(.option, .result))
mr_styp = g.typ(return_type.clear_option_and_result())
}
g.write('${mr_styp} ${mr_var_name} = ')
g.expr(node.right[0])
Expand Down
20 changes: 9 additions & 11 deletions vlib/v/gen/c/cgen.v
Expand Up @@ -1467,7 +1467,7 @@ pub fn (mut g Gen) write_typedef_types() {
g.type_definitions.writeln(def_str)
} else if !info.is_fn_ret && len.int() > 0 {
g.type_definitions.writeln('typedef ${fixed} ${styp} [${len}];')
base := g.typ(info.elem_type.clear_flags(.option, .result))
base := g.typ(info.elem_type.clear_option_and_result())
if info.elem_type.has_flag(.option) && base !in g.options_forward {
g.options_forward << base
} else if info.elem_type.has_flag(.result) && base !in g.results_forward {
Expand Down Expand Up @@ -3197,7 +3197,7 @@ fn (mut g Gen) expr(node_ ast.Expr) {
ret_type := if node.or_block.kind == .absent {
node.return_type
} else {
node.return_type.clear_flags(.option, .result)
node.return_type.clear_option_and_result()
}
mut shared_styp := ''
if g.is_shared && !ret_type.has_flag(.shared_f) && !g.inside_or_block {
Expand Down Expand Up @@ -3694,7 +3694,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
g.or_block(tmp_var, node.or_block, node.typ)
g.write(stmt_str)
g.write(' ')
unwrapped_typ := node.typ.clear_flags(.option, .result)
unwrapped_typ := node.typ.clear_option_and_result()
unwrapped_styp := g.typ(unwrapped_typ)
g.write('(*(${unwrapped_styp}*)${tmp_var}.data)')
return
Expand Down Expand Up @@ -4713,11 +4713,11 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
}

fn (mut g Gen) concat_expr(node ast.ConcatExpr) {
mut styp := g.typ(node.return_type.clear_flags(.option, .result))
mut styp := g.typ(node.return_type.clear_option_and_result())
if g.inside_return {
styp = g.typ(g.fn_decl.return_type.clear_flags(.option, .result))
styp = g.typ(g.fn_decl.return_type.clear_option_and_result())
} else if g.inside_or_block {
styp = g.typ(g.or_expr_return_type.clear_flags(.option, .result))
styp = g.typ(g.or_expr_return_type.clear_option_and_result())
}
sym := g.table.sym(node.return_type)
is_multi := sym.kind == .multi_return
Expand Down Expand Up @@ -5209,8 +5209,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
if return_sym.kind == .array_fixed && expr !is ast.ArrayInit {
g.fixed_array_var_init(expr, (return_sym.info as ast.ArrayFixed).size)
} else {
g.expr_with_cast(expr, node.types[i], fn_ret_type.clear_flags(.option,
.result))
g.expr_with_cast(expr, node.types[i], fn_ret_type.clear_option_and_result())
}
if i < node.exprs.len - 1 {
g.write(', ')
Expand Down Expand Up @@ -6382,8 +6381,7 @@ fn (mut g Gen) gen_or_block_stmts(cvar_name string, cast_typ string, stmts []ast
}
old_inside_opt_data := g.inside_opt_data
g.inside_opt_data = true
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_flags(.option,
.result))
g.expr_with_cast(expr_stmt.expr, expr_stmt.typ, return_type.clear_option_and_result())
g.inside_opt_data = old_inside_opt_data
g.writeln(';')
g.stmt_path_pos.delete_last()
Expand Down Expand Up @@ -6419,7 +6417,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type ast.Ty
}
}
if or_block.kind == .block {
g.or_expr_return_type = return_type.clear_flags(.option, .result)
g.or_expr_return_type = return_type.clear_option_and_result()
g.writeln('\tIError err = ${cvar_name}.err;')

g.inside_or_block = true
Expand Down
7 changes: 3 additions & 4 deletions vlib/v/gen/c/fn.v
Expand Up @@ -805,11 +805,11 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
}
if gen_or {
g.or_block(tmp_opt, node.or_block, node.return_type)
mut unwrapped_typ := node.return_type.clear_flags(.option, .result)
mut unwrapped_typ := node.return_type.clear_option_and_result()
if g.table.sym(unwrapped_typ).kind == .alias {
unaliased_type := g.table.unaliased_type(unwrapped_typ)
if unaliased_type.has_option_or_result() {
unwrapped_typ = unaliased_type.clear_flags(.option, .result)
unwrapped_typ = unaliased_type.clear_option_and_result()
}
}
mut unwrapped_styp := g.typ(unwrapped_typ)
Expand All @@ -824,8 +824,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
if !g.inside_const_opt_or_res {
if g.assign_ct_type != 0
&& node.or_block.kind in [.propagate_option, .propagate_result] {
unwrapped_styp = g.typ(g.assign_ct_type.derive(node.return_type).clear_flags(.option,
.result))
unwrapped_styp = g.typ(g.assign_ct_type.derive(node.return_type).clear_option_and_result())
}
if g.table.sym(node.return_type).kind == .array_fixed
&& unwrapped_styp.starts_with('_v_') {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/gen/c/orm.v
Expand Up @@ -38,7 +38,7 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) {
result_c_typ := g.typ(node.typ)
g.writeln('${result_c_typ} ${result_var};')
g.write_orm_select(node, connection_var_name, result_var)
unwrapped_c_typ := g.typ(node.typ.clear_flags(.result))
unwrapped_c_typ := g.typ(node.typ.clear_flag(.result))
g.write('${left} *(${unwrapped_c_typ}*)${result_var}.data')
}

Expand Down

0 comments on commit ee95e23

Please sign in to comment.