table: allow type hold 8 flags at once
parent
2230cbae01
commit
edd56bc080
|
@ -19,7 +19,7 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool {
|
|||
// and the other is not, is this correct behaviour?
|
||||
return true
|
||||
}
|
||||
if got_idx == table.none_type_idx && expected.flag_is(.optional) {
|
||||
if got_idx == table.none_type_idx && expected.has_flag(.optional) {
|
||||
return true
|
||||
}
|
||||
// allow pointers to be initialized with 0. TODO: use none instead
|
||||
|
|
|
@ -826,7 +826,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
c.expected_type = exp_arg_typ
|
||||
got_arg_typ := c.expr(arg.expr)
|
||||
call_expr.args[i].typ = got_arg_typ
|
||||
if method.is_variadic && got_arg_typ.flag_is(.variadic) && call_expr.args.len -
|
||||
if method.is_variadic && got_arg_typ.has_flag(.variadic) && call_expr.args.len -
|
||||
1 > i {
|
||||
c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
|
||||
}
|
||||
|
@ -1027,7 +1027,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
call_expr.args[i].typ = typ
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
arg_typ_sym := c.table.get_type_symbol(arg.typ)
|
||||
if f.is_variadic && typ.flag_is(.variadic) && call_expr.args.len - 1 > i {
|
||||
if f.is_variadic && typ.has_flag(.variadic) && call_expr.args.len - 1 > i {
|
||||
c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos)
|
||||
}
|
||||
if arg.is_mut && !call_arg.is_mut {
|
||||
|
@ -1100,7 +1100,7 @@ fn (mut c Checker) type_implements(typ, inter_typ table.Type, pos token.Position
|
|||
pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) table.Type {
|
||||
if expr is ast.CallExpr {
|
||||
call_expr := expr as ast.CallExpr
|
||||
if call_expr.return_type.flag_is(.optional) {
|
||||
if call_expr.return_type.has_flag(.optional) {
|
||||
if call_expr.or_block.kind == .absent {
|
||||
if ret_type != table.void_type {
|
||||
c.error('${call_expr.name}() returns an option, but you missed to add an `or {}` block to it',
|
||||
|
@ -1110,7 +1110,7 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
|||
c.check_or_expr(call_expr.or_block, ret_type)
|
||||
}
|
||||
// remove optional flag
|
||||
return ret_type.set_flag(.unset)
|
||||
return ret_type.clear_flag(.optional)
|
||||
} else if call_expr.or_block.kind == .block {
|
||||
c.error('unexpected `or` block, the function `$call_expr.name` does not return an optional',
|
||||
call_expr.pos)
|
||||
|
@ -1124,7 +1124,7 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
|||
|
||||
pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type) {
|
||||
if or_expr.kind == .propagate {
|
||||
if !c.cur_fn.return_type.flag_is(.optional) && c.cur_fn.name != 'main' {
|
||||
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main' {
|
||||
c.error('to propagate the optional call, `${c.cur_fn.name}` must itself return an optional',
|
||||
or_expr.pos)
|
||||
}
|
||||
|
@ -1193,7 +1193,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
|
|||
sym := c.table.get_type_symbol(c.unwrap_generic(typ))
|
||||
field_name := selector_expr.field_name
|
||||
// variadic
|
||||
if typ.flag_is(.variadic) {
|
||||
if typ.has_flag(.variadic) {
|
||||
if field_name == 'len' {
|
||||
return table.int_type
|
||||
}
|
||||
|
@ -1228,7 +1228,7 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
|||
}
|
||||
expected_type := c.expected_type
|
||||
expected_type_sym := c.table.get_type_symbol(expected_type)
|
||||
exp_is_optional := expected_type.flag_is(.optional)
|
||||
exp_is_optional := expected_type.has_flag(.optional)
|
||||
mut expected_types := [expected_type]
|
||||
if expected_type_sym.kind == .multi_return {
|
||||
mr_info := expected_type_sym.info as table.MultiReturn
|
||||
|
@ -1258,8 +1258,8 @@ pub fn (mut c Checker) return_stmt(mut return_stmt ast.Return) {
|
|||
}
|
||||
for i, exp_type in expected_types {
|
||||
got_typ := got_types[i]
|
||||
if got_typ.flag_is(.optional) &&
|
||||
(!exp_type.flag_is(.optional) || c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) {
|
||||
if got_typ.has_flag(.optional) &&
|
||||
(!exp_type.has_flag(.optional) || c.table.type_to_str(got_typ) != c.table.type_to_str(exp_type)) {
|
||||
pos := return_stmt.exprs[i].position()
|
||||
c.error('cannot use `${c.table.type_to_str(got_typ)}` as type `${c.table.type_to_str(exp_type)}` in return argument', pos)
|
||||
}
|
||||
|
@ -1977,7 +1977,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
|||
}
|
||||
typ = c.expr(it.expr)
|
||||
}
|
||||
is_optional := typ.flag_is(.optional)
|
||||
is_optional := typ.has_flag(.optional)
|
||||
ident.kind = .variable
|
||||
ident.info = ast.IdentVar{
|
||||
typ: typ
|
||||
|
@ -1993,7 +1993,7 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
|
|||
it.typ = typ
|
||||
// unwrap optional (`println(x)`)
|
||||
if is_optional {
|
||||
return typ.set_flag(.unset)
|
||||
return typ.clear_flag(.optional)
|
||||
}
|
||||
return typ
|
||||
}
|
||||
|
|
|
@ -324,7 +324,7 @@ fn (g &Gen) typ(t table.Type) string {
|
|||
// T => int etc
|
||||
return g.typ(g.cur_generic_type)
|
||||
}
|
||||
if t.flag_is(.optional) {
|
||||
if t.has_flag(.optional) {
|
||||
// Register an optional if it's not registered yet
|
||||
return g.register_optional(t)
|
||||
}
|
||||
|
@ -844,7 +844,7 @@ fn (mut g Gen) for_in(it ast.ForInStmt) {
|
|||
}
|
||||
g.stmts(it.stmts)
|
||||
g.writeln('}')
|
||||
} else if it.cond_type.flag_is(.variadic) {
|
||||
} else if it.cond_type.has_flag(.variadic) {
|
||||
g.writeln('// FOR IN cond_type/variadic')
|
||||
i := if it.key_var in ['', '_'] { g.new_tmp_var() } else { it.key_var }
|
||||
styp := g.typ(it.cond_type)
|
||||
|
@ -901,7 +901,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type)
|
|||
got_deref_type := got_type.deref()
|
||||
deref_sym := g.table.get_type_symbol(got_deref_type)
|
||||
deref_will_match := expected_type in [got_type, got_deref_type, deref_sym.parent_idx]
|
||||
got_is_opt := got_type.flag_is(.optional)
|
||||
got_is_opt := got_type.has_flag(.optional)
|
||||
if deref_will_match || got_is_opt {
|
||||
g.write('*')
|
||||
}
|
||||
|
@ -1015,7 +1015,7 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
1 {
|
||||
// multi return
|
||||
// TODO Handle in if_expr
|
||||
is_optional := return_type.flag_is(.optional)
|
||||
is_optional := return_type.has_flag(.optional)
|
||||
mr_var_name := 'mr_$assign_stmt.pos.pos'
|
||||
mr_styp := g.typ(return_type)
|
||||
g.write('$mr_styp $mr_var_name = ')
|
||||
|
@ -1289,7 +1289,7 @@ fn (mut g Gen) autofree_scope_vars(pos int) string {
|
|||
// continue
|
||||
// }
|
||||
v := *it
|
||||
is_optional := v.typ.flag_is(.optional)
|
||||
is_optional := v.typ.has_flag(.optional)
|
||||
if is_optional {
|
||||
// TODO: free optionals
|
||||
continue
|
||||
|
@ -1644,7 +1644,7 @@ fn (mut g Gen) assign_expr(node ast.AssignExpr) {
|
|||
}
|
||||
else {}
|
||||
}
|
||||
gen_or := is_call && return_type.flag_is(.optional)
|
||||
gen_or := is_call && return_type.has_flag(.optional)
|
||||
tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
|
||||
if gen_or {
|
||||
rstyp := g.typ(return_type)
|
||||
|
@ -1662,7 +1662,7 @@ fn (mut g Gen) assign_expr(node ast.AssignExpr) {
|
|||
}
|
||||
} else {
|
||||
g.is_assign_lhs = true
|
||||
if node.right_type.flag_is(.optional) {
|
||||
if node.right_type.has_flag(.optional) {
|
||||
g.right_is_opt = true
|
||||
}
|
||||
mut str_add := false
|
||||
|
@ -1719,7 +1719,7 @@ fn (mut g Gen) assign_expr(node ast.AssignExpr) {
|
|||
if gen_or {
|
||||
// g.write('/*777 $tmp_opt*/')
|
||||
g.or_block(tmp_opt, or_block, return_type)
|
||||
unwrapped_type_str := g.typ(return_type.set_flag(.unset))
|
||||
unwrapped_type_str := g.typ(return_type.clear_flag(.optional))
|
||||
ident := node.left as ast.Ident
|
||||
if ident.kind != .blank_ident && ident.info is ast.IdentVar {
|
||||
ident_var := ident.info as ast.IdentVar
|
||||
|
@ -2207,7 +2207,7 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) {
|
|||
if !is_range {
|
||||
sym := g.table.get_type_symbol(node.left_type)
|
||||
left_is_ptr := node.left_type.is_ptr()
|
||||
if node.left_type.flag_is(.variadic) {
|
||||
if node.left_type.has_flag(.variadic) {
|
||||
g.expr(node.left)
|
||||
g.write('.args')
|
||||
g.write('[')
|
||||
|
@ -2339,7 +2339,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
// got to do a correct check for multireturn
|
||||
sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
||||
fn_return_is_multi := sym.kind == .multi_return
|
||||
fn_return_is_optional := g.fn_decl.return_type.flag_is(.optional)
|
||||
fn_return_is_optional := g.fn_decl.return_type.has_flag(.optional)
|
||||
// handle promoting none/error/function returning 'Option'
|
||||
if fn_return_is_optional {
|
||||
optional_none := node.exprs[0] is ast.None
|
||||
|
@ -2418,7 +2418,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
|||
// normal return
|
||||
return_sym := g.table.get_type_symbol(node.types[0])
|
||||
// `return opt_ok(expr)` for functions that expect an optional
|
||||
if fn_return_is_optional && !node.types[0].flag_is(.optional) && return_sym.name !=
|
||||
if fn_return_is_optional && !node.types[0].has_flag(.optional) && return_sym.name !=
|
||||
'Option' {
|
||||
styp := g.base_type(g.fn_decl.return_type)
|
||||
opt_type := g.typ(g.fn_decl.return_type)
|
||||
|
@ -2631,7 +2631,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
|
|||
// unions thould have exactly one explicit initializer
|
||||
continue
|
||||
}
|
||||
if field.typ.flag_is(.optional) {
|
||||
if field.typ.has_flag(.optional) {
|
||||
// TODO handle/require optionals in inits
|
||||
continue
|
||||
}
|
||||
|
@ -2813,7 +2813,7 @@ fn (mut g Gen) write_types(types []table.TypeSymbol) {
|
|||
// if this is the case then we are going to
|
||||
// buffer manip out in front of the struct
|
||||
// write the optional in and then continue
|
||||
if field.typ.flag_is(.optional) {
|
||||
if field.typ.has_flag(.optional) {
|
||||
// Dont use g.typ() here becuase it will register
|
||||
// optional and we dont want that
|
||||
last_text := g.type_definitions.after(start_pos).clone()
|
||||
|
@ -3102,7 +3102,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
|
|||
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) ?bool {
|
||||
sym := g.table.get_type_symbol(etype)
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||
if etype.flag_is(.variadic) {
|
||||
if etype.has_flag(.variadic) {
|
||||
str_fn_name := g.gen_str_for_type(etype)
|
||||
g.write('${str_fn_name}(')
|
||||
g.expr(expr)
|
||||
|
@ -3294,7 +3294,7 @@ fn (mut g Gen) or_block(var_name string, or_block ast.OrExpr, return_type table.
|
|||
expr_stmt := stmt as ast.ExprStmt
|
||||
g.stmt_path_pos << g.out.len
|
||||
g.write('*(${mr_styp}*) ${cvar_name}.data = ')
|
||||
is_opt_call := expr_stmt.expr is ast.CallExpr && expr_stmt.typ.flag_is(.optional)
|
||||
is_opt_call := expr_stmt.expr is ast.CallExpr && expr_stmt.typ.has_flag(.optional)
|
||||
if is_opt_call {
|
||||
g.write('*(${mr_styp}*) ')
|
||||
}
|
||||
|
@ -3858,7 +3858,7 @@ fn (mut g Gen) gen_str_for_type_with_styp(typ table.Type, styp string) string {
|
|||
}
|
||||
}
|
||||
// if varg, generate str for varg
|
||||
if typ.flag_is(.variadic) {
|
||||
if typ.has_flag(.variadic) {
|
||||
varg_already_generated_key := 'varg_$already_generated_key'
|
||||
if varg_already_generated_key !in g.str_types {
|
||||
g.gen_str_for_varg(styp, str_fn_name, sym_has_str_method)
|
||||
|
|
|
@ -430,7 +430,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
|||
}
|
||||
g.expr(node.left)
|
||||
is_variadic := node.expected_arg_types.len > 0 && node.expected_arg_types[node.expected_arg_types.len -
|
||||
1].flag_is(.variadic)
|
||||
1].has_flag(.variadic)
|
||||
if node.args.len > 0 || is_variadic {
|
||||
g.write(', ')
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
styp = styp.replace('*', '')
|
||||
}
|
||||
mut str_fn_name := g.gen_str_for_type_with_styp(typ, styp)
|
||||
if g.autofree && !typ.flag_is(.optional) {
|
||||
if g.autofree && !typ.has_flag(.optional) {
|
||||
// Create a temporary variable so that the value can be freed
|
||||
tmp := g.new_tmp_var()
|
||||
// tmps << tmp
|
||||
|
@ -565,7 +565,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
g.write('*')
|
||||
}
|
||||
g.expr(expr)
|
||||
if !typ.flag_is(.variadic) && sym.kind == .struct_ && styp != 'ptr' && !sym.has_method('str') {
|
||||
if !typ.has_flag(.variadic) && sym.kind == .struct_ && styp != 'ptr' && !sym.has_method('str') {
|
||||
g.write(', 0') // trailing 0 is initial struct indent count
|
||||
}
|
||||
}
|
||||
|
@ -599,8 +599,8 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
}
|
||||
|
||||
fn (mut g Gen) call_args(args []ast.CallArg, expected_types []table.Type) {
|
||||
is_variadic := expected_types.len > 0 && expected_types[expected_types.len - 1].flag_is(.variadic)
|
||||
is_forwarding_varg := args.len > 0 && args[args.len - 1].typ.flag_is(.variadic)
|
||||
is_variadic := expected_types.len > 0 && expected_types[expected_types.len - 1].has_flag(.variadic)
|
||||
is_forwarding_varg := args.len > 0 && args[args.len - 1].typ.has_flag(.variadic)
|
||||
gen_vargs := is_variadic && !is_forwarding_varg
|
||||
for i, arg in args {
|
||||
if gen_vargs && i == expected_types.len - 1 {
|
||||
|
|
|
@ -908,7 +908,7 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
|
|||
g.inside_loop = false
|
||||
g.stmts(it.stmts)
|
||||
g.writeln('}')
|
||||
} else if it.kind == .array || it.cond_type.flag_is(.variadic) {
|
||||
} else if it.kind == .array || it.cond_type.has_flag(.variadic) {
|
||||
// `for num in nums {`
|
||||
i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var }
|
||||
// styp := g.typ(it.val_type)
|
||||
|
|
|
@ -36,8 +36,8 @@ pub mut:
|
|||
is_public bool
|
||||
}
|
||||
|
||||
// max of 8
|
||||
pub enum TypeFlag {
|
||||
unset
|
||||
optional
|
||||
variadic
|
||||
generic
|
||||
|
@ -99,29 +99,33 @@ pub fn (t Type) deref() Type {
|
|||
return (((int(t) >> 24) & 0xff) << 24) | ((nr_muls - 1) << 16) | (u16(t) & 0xffff)
|
||||
}
|
||||
|
||||
// return the flag that is set on `t`
|
||||
[inline]
|
||||
pub fn (t Type) flag() TypeFlag {
|
||||
return (int(t) >> 24) & 0xff
|
||||
}
|
||||
|
||||
// set the flag on `t` to `flag` and return it
|
||||
// set `flag` on `t` and return `t`
|
||||
[inline]
|
||||
pub fn (t Type) set_flag(flag TypeFlag) Type {
|
||||
return (int(flag) << 24) | (((int(t) >> 16) & 0xff) << 16) | (u16(t) & 0xffff)
|
||||
return ((((int(t) >> 24) & 0xff) | 1 << int(flag)) << 24) | (((int(t) >> 16) & 0xff) << 16) | (u16(t) & 0xffff)
|
||||
}
|
||||
|
||||
// return true if the flag set on `t` is `flag`
|
||||
// clear `flag` on `t` and return `t`
|
||||
pub fn (t Type) clear_flag(flag TypeFlag) Type {
|
||||
return (((((int(t) >> 24) & 0xff) & ~(1 << int(flag))) << 24) ) | (((int(t) >> 16) & 0xff) << 16) | (u16(t) & 0xffff)
|
||||
}
|
||||
|
||||
// clear all flags
|
||||
pub fn (t Type) clear_flags() Type {
|
||||
return 0 | (((int(t) >> 16) & 0xff) << 16) | (u16(t) & 0xffff)
|
||||
}
|
||||
|
||||
// return true if `flag` is set in `t`
|
||||
[inline]
|
||||
pub fn (t Type) flag_is(flag TypeFlag) bool {
|
||||
return (int(t) >> 24) & 0xff == flag
|
||||
pub fn (t Type) has_flag(flag TypeFlag) bool {
|
||||
return (((int(t) >> 24) & 0xff) >> int(flag)) & 1 == 1
|
||||
}
|
||||
|
||||
// return new type with TypeSymbol idx set to `idx`
|
||||
[inline]
|
||||
pub fn new_type(idx int) Type {
|
||||
if idx < 1 || idx > 65536 {
|
||||
panic('new_type_id: idx must be between 1 & 65536')
|
||||
if idx < 1 || idx > 65535 {
|
||||
panic('new_type_id: idx must be between 1 & 65535')
|
||||
}
|
||||
return idx
|
||||
}
|
||||
|
@ -129,8 +133,8 @@ pub fn new_type(idx int) Type {
|
|||
// return new type with TypeSymbol idx set to `idx` & nr_muls set to `nr_muls`
|
||||
[inline]
|
||||
pub fn new_type_ptr(idx, nr_muls int) Type {
|
||||
if idx < 1 || idx > 65536 {
|
||||
panic('new_type_ptr: idx must be between 1 & 65536')
|
||||
if idx < 1 || idx > 65535 {
|
||||
panic('new_type_ptr: idx must be between 1 & 65535')
|
||||
}
|
||||
if nr_muls < 0 || nr_muls > 255 {
|
||||
panic('new_type_ptr: nr_muls must be between 0 & 255')
|
||||
|
@ -673,7 +677,7 @@ pub fn (table &Table) type_to_str(t Type) string {
|
|||
mut res := sym.name
|
||||
if sym.kind == .multi_return {
|
||||
res = '('
|
||||
if t.flag_is(.optional) {
|
||||
if t.has_flag(.optional) {
|
||||
res = '?' + res
|
||||
}
|
||||
mr_info := sym.info as MultiReturn
|
||||
|
@ -706,7 +710,7 @@ pub fn (table &Table) type_to_str(t Type) string {
|
|||
if nr_muls > 0 {
|
||||
res = strings.repeat(`&`, nr_muls) + res
|
||||
}
|
||||
if t.flag_is(.optional) {
|
||||
if t.has_flag(.optional) {
|
||||
if sym.kind == .void {
|
||||
res = '?'
|
||||
} else {
|
||||
|
|
|
@ -417,9 +417,9 @@ pub fn (mut t Table) add_placeholder_type(name string) int {
|
|||
[inline]
|
||||
pub fn (t &Table) value_type(typ Type) Type {
|
||||
typ_sym := t.get_type_symbol(typ)
|
||||
if typ.flag_is(.variadic) {
|
||||
if typ.has_flag(.variadic) {
|
||||
// ...string => string
|
||||
return typ.set_flag(.unset)
|
||||
return typ.clear_flag(.variadic)
|
||||
}
|
||||
if typ_sym.kind == .array {
|
||||
// Check index type
|
||||
|
|
Loading…
Reference in New Issue