ast: add has_option_or_result() and cleanup all the related calls (#20434)

This commit is contained in:
yuyi 2024-01-08 23:59:58 +08:00 committed by GitHub
parent 8af961faf6
commit 34da4c97ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 42 additions and 43 deletions

View File

@ -395,6 +395,11 @@ pub fn (t Type) has_flag(flag TypeFlag) bool {
return int(t) & (1 << (int(flag) + 24)) > 0
}
@[inline]
pub fn (t Type) has_option_or_result() bool {
return u32(t) & 0x0300_0000 != 0
}
// debug returns a verbose representation of the information in ts, useful for tracing/debugging
pub fn (ts TypeSymbol) debug() []string {
mut res := []string{}
@ -708,7 +713,7 @@ pub fn mktyp(typ Type) Type {
// returns TypeSymbol kind only if there are no type modifiers
pub fn (t &Table) type_kind(typ Type) Kind {
if typ.nr_muls() > 0 || typ.has_flag(.option) || typ.has_flag(.result) {
if typ.nr_muls() > 0 || typ.has_option_or_result() {
return Kind.placeholder
}
return t.sym(typ).kind
@ -1036,7 +1041,7 @@ pub fn (t &TypeSymbol) is_builtin() bool {
// type_size returns the size and alignment (in bytes) of `typ`, similarly to C's `sizeof()` and `alignof()`.
pub fn (t &Table) type_size(typ Type) (int, int) {
if typ.has_flag(.option) || typ.has_flag(.result) {
if typ.has_option_or_result() {
return t.type_size(ast.error_type_idx)
}
if typ.nr_muls() > 0 {

View File

@ -146,7 +146,7 @@ fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
if expected == ast.charptr_type && got == ast.char_type.ref() {
return true
}
if expected.has_flag(.option) || expected.has_flag(.result) {
if expected.has_option_or_result() {
sym := c.table.sym(got)
if ((sym.idx == ast.error_type_idx || got in [ast.none_type, ast.error_type])
&& expected.has_flag(.option))

View File

@ -1147,11 +1147,11 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast.
mut expr_ret_type := expr.return_type
if expr_ret_type != 0 && c.table.sym(expr_ret_type).kind == .alias {
unaliased_ret_type := c.table.unaliased_type(expr_ret_type)
if unaliased_ret_type.has_flag(.option) || unaliased_ret_type.has_flag(.result) {
if unaliased_ret_type.has_option_or_result() {
expr_ret_type = unaliased_ret_type
}
}
if expr_ret_type.has_flag(.option) || expr_ret_type.has_flag(.result) {
if expr_ret_type.has_option_or_result() {
return_modifier_kind := if expr_ret_type.has_flag(.option) {
'an Option'
} else {
@ -1179,7 +1179,7 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast.
}
ast.SelectorExpr {
if c.table.sym(ret_type).kind != .chan {
if expr.typ.has_flag(.option) || expr.typ.has_flag(.result) {
if expr.typ.has_option_or_result() {
with_modifier_kind := if expr.typ.has_flag(.option) {
'an Option'
} else {
@ -2671,11 +2671,11 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
mut ret_type := c.call_expr(mut node)
if ret_type != 0 && c.table.sym(ret_type).kind == .alias {
unaliased_type := c.table.unaliased_type(ret_type)
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
if unaliased_type.has_option_or_result() {
ret_type = unaliased_type
}
}
if !ret_type.has_flag(.option) && !ret_type.has_flag(.result) {
if !ret_type.has_option_or_result() {
c.expr_or_block_err(node.or_block.kind, node.name, node.or_block.pos,
false)
}
@ -3586,8 +3586,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
if c.inside_interface_deref && c.table.is_interface_var(obj) {
typ = typ.deref()
}
is_option := typ.has_flag(.option) || typ.has_flag(.result)
|| node.or_expr.kind != .absent
is_option := typ.has_option_or_result() || node.or_expr.kind != .absent
node.kind = .variable
node.info = ast.IdentVar{
typ: typ
@ -4297,7 +4296,7 @@ fn (mut c Checker) check_index(typ_sym &ast.TypeSymbol, index ast.Expr, index_ty
}
}
}
if index_type.has_flag(.option) || index_type.has_flag(.result) {
if index_type.has_option_or_result() {
type_str := if typ_sym.kind == .string {
'(type `${typ_sym.name}`)'
} else {

View File

@ -381,7 +381,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
node.is_expr = true
node.typ = c.expected_type
}
if c.expected_type.has_flag(.option) || c.expected_type.has_flag(.result) {
if c.expected_type.has_option_or_result() {
if node.typ == ast.void_type {
node.is_expr = true
node.typ = c.expected_type
@ -447,7 +447,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
if is_noreturn_callexpr(stmt.expr) {
continue
}
if (node.typ.has_flag(.option) || node.typ.has_flag(.result))
if (node.typ.has_option_or_result())
&& c.table.sym(stmt.typ).kind == .struct_
&& c.type_implements(stmt.typ, ast.error_type, node.pos) {
stmt.expr = ast.CastExpr{

View File

@ -397,7 +397,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
left_name := c.table.type_to_str(unwrapped_left_type)
right_name := c.table.type_to_str(unwrapped_right_type)
c.error('mismatched types `${left_name}` and `${right_name}`', left_right_pos)
} else if promoted_type.has_flag(.option) || promoted_type.has_flag(.result) {
} else if promoted_type.has_option_or_result() {
s := c.table.type_to_str(promoted_type)
c.error('`${node.op}` cannot be used with `${s}`', node.pos)
} else if promoted_type.is_float() {

View File

@ -29,7 +29,7 @@ fn (mut c Checker) return_stmt(mut node ast.Return) {
mut expected_type := c.unwrap_generic(c.expected_type)
if expected_type != 0 && c.table.sym(expected_type).kind == .alias {
unaliased_type := c.table.unaliased_type(expected_type)
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
if unaliased_type.has_option_or_result() {
expected_type = unaliased_type
}
}

View File

@ -7,7 +7,7 @@ import v.ast
import v.token
fn (mut c Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
if ftyp.has_flag(.option) || ftyp.has_flag(.result) {
if ftyp.has_option_or_result() {
return `s`
} else if typ.is_float() {
return `g`
@ -32,7 +32,7 @@ fn (mut c Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
}
if ftyp in [ast.string_type, ast.bool_type]
|| sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .interface_, .none_]
|| ftyp.has_flag(.option) || ftyp.has_flag(.result) || sym.has_method('str') {
|| ftyp.has_option_or_result() || sym.has_method('str') {
return `s`
} else {
return `_`

View File

@ -330,7 +330,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
}
// TODO: no buffer fiddling
ast.AnonFn {
if !(var_type.has_flag(.option) || var_type.has_flag(.result)) {
if !var_type.has_option_or_result() {
if blank_assign {
g.write('{')
}
@ -376,8 +376,8 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
g.is_assign_lhs = true
g.assign_op = node.op
g.left_is_opt = var_type.has_flag(.option) || var_type.has_flag(.result)
g.right_is_opt = val_type.has_flag(.option) || val_type.has_flag(.result)
g.left_is_opt = var_type.has_option_or_result()
g.right_is_opt = val_type.has_option_or_result()
defer {
g.left_is_opt = false
g.right_is_opt = false

View File

@ -1094,7 +1094,7 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, lang ast.Language, _field_type ast.
return '${fn_name}(${deref}it.${final_field_name}${sufix})', false
} else {
mut method_str := ''
if !field_type.is_ptr() && (field_type.has_flag(.option) || field_type.has_flag(.result)) {
if !field_type.is_ptr() && field_type.has_option_or_result() {
method_str = '(*(${sym.name}*)it.${final_field_name}.data)'
} else {
method_str = 'it.${final_field_name}'

View File

@ -2559,7 +2559,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
got_deref_type := got_type.deref()
deref_sym := g.table.sym(got_deref_type)
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
got_is_opt_or_res := got_type.has_flag(.option) || got_type.has_flag(.result)
got_is_opt_or_res := got_type.has_option_or_result()
if deref_will_match || got_is_opt_or_res || expr.is_auto_deref_var() {
g.write('*')
}
@ -3701,8 +3701,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
}
// if node expr is a root ident and an optional
mut is_opt_or_res := node.expr is ast.Ident
&& (node.expr_type.has_flag(.option) || node.expr_type.has_flag(.result))
mut is_opt_or_res := node.expr is ast.Ident && node.expr_type.has_option_or_result()
if is_opt_or_res {
opt_base_typ := g.base_type(node.expr_type)
g.write('(*(${opt_base_typ}*)')
@ -4957,7 +4956,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
mut fn_ret_type := g.fn_decl.return_type
if sym.kind == .alias {
unaliased_type := g.table.unaliased_type(fn_ret_type)
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
if unaliased_type.has_option_or_result() {
fn_ret_type = unaliased_type
}
}
@ -6521,7 +6520,7 @@ fn c_fn_name(name_ string) string {
fn (mut g Gen) type_default(typ_ ast.Type) string {
typ := g.unwrap_generic(typ_)
if typ.has_flag(.option) || typ.has_flag(.result) {
if typ.has_option_or_result() {
return '{0}'
}
// Always set pointers to 0

View File

@ -150,8 +150,7 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
}
}
if !g.inside_call && node.or_block.kind != .block
&& (m.return_type.has_flag(.option) || m.return_type.has_flag(.result)) {
if !g.inside_call && node.or_block.kind != .block && m.return_type.has_option_or_result() {
g.write('(*(${g.base_type(m.return_type)}*)')
}
// TODO: check argument types
@ -212,12 +211,10 @@ fn (mut g Gen) comptime_call(mut node ast.ComptimeCall) {
}
}
g.write(')')
if !g.inside_call && node.or_block.kind != .block
&& (m.return_type.has_flag(.option) || m.return_type.has_flag(.result)) {
if !g.inside_call && node.or_block.kind != .block && m.return_type.has_option_or_result() {
g.write('.data)')
}
if node.or_block.kind != .absent
&& (m.return_type.has_flag(.option) || m.return_type.has_flag(.result)) {
if node.or_block.kind != .absent && m.return_type.has_option_or_result() {
if !g.inside_assign {
cur_line := g.go_before_last_stmt()
tmp_var := g.new_tmp_var()
@ -304,7 +301,7 @@ fn (mut g Gen) comptime_if(node ast.IfExpr) {
}
}
tmp_var := g.new_tmp_var()
is_opt_or_result := node.typ.has_flag(.option) || node.typ.has_flag(.result)
is_opt_or_result := node.typ.has_option_or_result()
line := if node.is_expr {
stmt_str := g.go_before_last_stmt()
g.write(util.tabs(g.indent))

View File

@ -769,7 +769,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
mut ret_typ := node.return_type
if g.table.sym(ret_typ).kind == .alias {
unaliased_type := g.table.unaliased_type(ret_typ)
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
if unaliased_type.has_option_or_result() {
ret_typ = unaliased_type
}
}
@ -808,7 +808,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
mut unwrapped_typ := node.return_type.clear_flags(.option, .result)
if g.table.sym(unwrapped_typ).kind == .alias {
unaliased_type := g.table.unaliased_type(unwrapped_typ)
if unaliased_type.has_flag(.option) || unaliased_type.has_flag(.result) {
if unaliased_type.has_option_or_result() {
unwrapped_typ = unaliased_type.clear_flags(.option, .result)
}
}

View File

@ -7,8 +7,7 @@ import v.ast
fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool {
if node.is_expr && g.inside_ternary == 0 {
if g.is_autofree || node.typ.has_flag(.option) || node.typ.has_flag(.result)
|| node.is_comptime {
if g.is_autofree || node.typ.has_option_or_result() || node.is_comptime {
return true
}
for branch in node.branches {
@ -97,7 +96,7 @@ fn (mut g Gen) need_tmp_var_in_expr(expr ast.Expr) bool {
ast.ConcatExpr {
for val in expr.vals {
if val is ast.CallExpr {
if val.return_type.has_flag(.option) || val.return_type.has_flag(.result) {
if val.return_type.has_option_or_result() {
return true
}
}

View File

@ -8,7 +8,7 @@ import v.ast
fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool {
if node.is_expr && node.return_type != ast.void_type && node.return_type != 0 {
if g.table.sym(node.return_type).kind in [.sum_type, .multi_return]
|| node.return_type.has_flag(.option) || node.return_type.has_flag(.result) {
|| node.return_type.has_option_or_result() {
return true
}
if g.table.final_sym(node.cond_type).kind == .enum_ && node.branches.len > 5 {

View File

@ -13,7 +13,7 @@ import v.ast
import v.util
fn (mut g Gen) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
if ftyp.has_flag(.option) || ftyp.has_flag(.result) {
if ftyp.has_option_or_result() {
return `s`
} else if typ.is_float() {
return `g`
@ -38,7 +38,7 @@ fn (mut g Gen) get_default_fmt(ftyp ast.Type, typ ast.Type) u8 {
}
if ftyp in [ast.string_type, ast.bool_type]
|| sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .interface_, .none_]
|| ftyp.has_flag(.option) || ftyp.has_flag(.result) || sym.has_method('str') {
|| ftyp.has_option_or_result() || sym.has_method('str') {
return `s`
} else {
return `_`

View File

@ -147,7 +147,7 @@ pub fn (mut g Gen) fn_external_import(node ast.FnDecl) {
if node.language == .js && g.pref.os == .wasi {
g.v_error('javascript interop functions are not allowed in a `wasi` build', node.pos)
}
if node.return_type.has_flag(.option) || node.return_type.has_flag(.result) {
if node.return_type.has_option_or_result() {
g.v_error('interop functions must not return option or result', node.pos)
}

View File

@ -248,7 +248,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
return ast.StructDecl{}
}
field_pos = field_start_pos.extend(p.prev_tok.pos())
if typ.has_flag(.option) || typ.has_flag(.result) {
if typ.has_option_or_result() {
option_pos = p.peek_token(-2).pos()
}
}