mirror of
https://github.com/vlang/v.git
synced 2025-09-14 09:56:16 -04:00
ast: add has_option_or_result() and cleanup all the related calls (#20434)
This commit is contained in:
parent
8af961faf6
commit
34da4c97ea
@ -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 {
|
||||
|
@ -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))
|
||||
|
@ -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 {
|
||||
|
@ -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{
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 `_`
|
||||
|
@ -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
|
||||
|
@ -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}'
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 `_`
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user