From c9e290b36fb5996414df267f34a8d2dc7924db39 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Sat, 4 Apr 2020 16:37:11 +1100 Subject: [PATCH] table: simplify/generalise type fns & remove calls --- vlib/v/checker/checker.v | 11 +++-- vlib/v/gen/cgen.v | 29 ++++++------ vlib/v/parser/fn.v | 4 +- vlib/v/parser/parse_type.v | 2 +- vlib/v/table/atypes.v | 96 ++++++++++++++++---------------------- vlib/v/table/table.v | 4 +- 6 files changed, 65 insertions(+), 81 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 88aa94fca7..b3a0639925 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -372,7 +372,7 @@ pub fn (c mut Checker) selector_expr(selector_expr mut ast.SelectorExpr) table.T typ_sym := c.table.get_type_symbol(typ) field_name := selector_expr.field // variadic - if table.type_is_variadic(typ) { + if table.type_is(typ, .variadic) { if field_name == 'len' { return table.int_type } @@ -401,7 +401,7 @@ pub fn (c mut Checker) return_stmt(return_stmt mut ast.Return) { } expected_type := c.fn_return_type expected_type_sym := c.table.get_type_symbol(expected_type) - exp_is_optional := table.type_is_optional(expected_type) + exp_is_optional := table.type_is(expected_type, .optional) mut expected_types := [expected_type] if expected_type_sym.kind == .multi_return { mr_info := expected_type_sym.info as table.MultiReturn @@ -874,14 +874,15 @@ pub fn (c mut Checker) ident(ident mut ast.Ident) table.Type { if typ == 0 { typ = c.expr(var.expr) } + is_optional := table.type_is(typ, .optional) ident.kind = .variable ident.info = ast.IdentVar{ typ: typ - is_optional: table.type_is_optional(typ) + is_optional: is_optional } // unwrap optional (`println(x)`) - if table.type_is_optional(typ) { - return table.type_clear_extra(typ) + if is_optional { + return table.type_set(typ, .unset) } return typ } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index abf8bc8d16..30e5f4aad4 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -162,7 +162,7 @@ pub fn (g mut Gen) typ(t table.Type) string { styp = 'struct $styp' } } - if table.type_is_optional(t) { + if table.type_is(t, .optional) { styp = 'Option_' + styp if !(styp in g.optionals) { g.definitions.writeln('typedef Option $styp;') @@ -506,7 +506,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) { g.stmts(it.stmts) g.writeln('}') } - else if table.type_is_variadic(it.cond_type) { + else if table.type_is(it.cond_type, .variadic) { g.writeln('// FOR IN') i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var } styp := g.typ(it.cond_type) @@ -597,7 +597,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } else {} } - is_optional := table.type_is_optional(return_type) + is_optional := table.type_is(return_type, .optional) mr_var_name := 'mr_$assign_stmt.pos.pos' mr_styp := g.typ(return_type) g.write('$mr_styp $mr_var_name = ') @@ -644,7 +644,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } else {} } - gen_or := is_call && table.type_is_optional(return_type) + gen_or := is_call && table.type_is(return_type, .optional) g.is_assign_rhs = true if ident.kind == .blank_ident { if is_call { @@ -846,10 +846,11 @@ fn (g mut Gen) free_scope_vars(pos int) { // } var := *it sym := g.table.get_type_symbol(var.typ) - if sym.kind == .array && !table.type_is_optional(var.typ) { + is_optional := table.type_is(var.typ, .optional) + if sym.kind == .array && !is_optional { g.writeln('array_free($var.name); // autofreed') } - if sym.kind == .string && !table.type_is_optional(var.typ) { + if sym.kind == .string && !is_optional { // Don't free simple string literals. t := typeof(var.expr) match var.expr { @@ -1220,7 +1221,7 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { } else {} } - gen_or := is_call && table.type_is_optional(return_type) + gen_or := is_call && table.type_is(return_type, .optional) tmp_opt := if gen_or { g.new_tmp_var() } else { '' } if gen_or { rstyp := g.typ(return_type) @@ -1239,7 +1240,7 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) { } else { g.is_assign_lhs = true - if table.type_is_optional(node.right_type) { + if table.type_is(node.right_type, .optional) { g.right_is_opt = true } mut str_add := false @@ -1672,7 +1673,7 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) { if !is_range { sym := g.table.get_type_symbol(node.left_type) left_is_ptr := table.type_is_ptr(node.left_type) - if table.type_is_variadic(node.left_type) { + if table.type_is(node.left_type, .variadic) { g.expr(node.left) g.write('.args') g.write('[') @@ -1778,7 +1779,7 @@ fn (g mut Gen) return_statement(node ast.Return) { g.writeln(' 0;') return } - fn_return_is_optional := table.type_is_optional(g.fn_decl.return_type) + fn_return_is_optional := table.type_is(g.fn_decl.return_type, .optional) // multiple returns if node.exprs.len > 1 { g.write(' ') @@ -1806,7 +1807,7 @@ fn (g mut Gen) return_statement(node ast.Return) { else if node.exprs.len == 1 { g.write(' ') // `return opt_ok(expr)` for functions that expect an optional - if fn_return_is_optional && !table.type_is_optional(node.types[0]) { + if fn_return_is_optional && !table.type_is(node.types[0], .optional) { mut is_none := false mut is_error := false expr0 := node.exprs[0] @@ -1958,7 +1959,7 @@ fn (g mut Gen) assoc(node ast.Assoc) { } fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { - is_variadic := expected_types.len > 0 && table.type_is_variadic(expected_types[expected_types.len - 1]) + is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len - 1], .variadic) mut arg_no := 0 for arg in args { if is_variadic && arg_no == expected_types.len - 1 { @@ -2371,7 +2372,7 @@ fn (g mut Gen) method_call(node ast.CallExpr) { } g.expr(node.left) is_variadic := node.expected_arg_types.len > 0 && - table.type_is_variadic(node.expected_arg_types[node.expected_arg_types.len - 1]) + table.type_is(node.expected_arg_types[node.expected_arg_types.len - 1], .variadic) if node.args.len > 0 || is_variadic { g.write(', ') } @@ -2436,7 +2437,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { g.str_types << styp g.gen_str_for_type(sym, styp) } - if g.autofree && !table.type_is_optional(typ) { + if g.autofree && !table.type_is(typ, .optional) { // Create a temporary variable so that the value can be freed tmp := g.new_tmp_var() // tmps << tmp diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 5c232c7a0e..c78068d837 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -202,7 +202,7 @@ fn (p mut Parser) fn_args() ([]table.Arg,bool) { } mut arg_type := p.parse_type() if is_variadic { - arg_type = table.type_to_variadic(arg_type) + arg_type = table.type_set(arg_type, .variadic) } if p.tok.kind == .comma { if is_variadic { @@ -236,7 +236,7 @@ fn (p mut Parser) fn_args() ([]table.Arg,bool) { } mut typ := p.parse_type() if is_variadic { - typ = table.type_to_variadic(typ) + typ = table.type_set(typ, .variadic) } for arg_name in arg_names { args << table.Arg{ diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index f6331f9991..346cde8891 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -115,7 +115,7 @@ pub fn (p mut Parser) parse_type() table.Type { } mut typ := p.parse_any_type(is_c, nr_muls > 0) if is_optional { - typ = table.type_to_optional(typ) + typ = table.type_set(typ, .optional) } if nr_muls > 0 { typ = table.type_set_nr_muls(typ, nr_muls) diff --git a/vlib/v/table/atypes.v b/vlib/v/table/atypes.v index 2e292bcaec..6dbe77a67a 100644 --- a/vlib/v/table/atypes.v +++ b/vlib/v/table/atypes.v @@ -1,3 +1,15 @@ +// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved. +// Use of this source code is governed by an MIT license +// that can be found in the LICENSE file. +// +// Type layout information (32 bits) +// flag (8 bits) | nr_muls (8 bits) | idx (16 bits) +// pack: (int(flag)<<24) | (nr_muls<<16) | u16(idx) +// unpack: +// flag: (int(type)>>24) & 0xff +// nr_muls: (int(type)>>16) & 0xff +// idx: u16(type) & 0xffff + module table import ( @@ -17,10 +29,9 @@ mut: kind Kind name string methods []Fn - // is_sum bool } -pub enum TypeExtra { +pub enum TypeFlag { unset optional variadic @@ -35,90 +46,71 @@ pub fn (types []Type) contains(typ Type) bool { return false } -// return underlying TypeSymbol idx +// return TypeSymbol idx for `t` [inline] pub fn type_idx(t Type) int { return u16(t) & 0xffff } -// return nr_muls +// return nr_muls for `t` [inline] pub fn type_nr_muls(t Type) int { return (int(t)>>16) & 0xff } -// return true if pointer (nr_muls>0) +// return true if `t` is a pointer (nr_muls>0) [inline] pub fn type_is_ptr(t Type) bool { - return type_nr_muls(t) > 0 // || t == voidptr_type_idx + return (int(t)>>16) & 0xff > 0 } -// set nr_muls on Type and return it +// set nr_muls on `t` and return it [inline] pub fn type_set_nr_muls(t Type, nr_muls int) Type { if nr_muls < 0 || nr_muls > 255 { panic('typ_set_nr_muls: nr_muls must be between 0 & 255') } - return (int(type_extra(t))<<24) | (nr_muls<<16) | u16(type_idx(t)) + return (((int(t)>>24) & 0xff)<<24) | (nr_muls<<16) | (u16(t) & 0xffff) } -// increments nr_nuls on Type and return it +// increments nr_nuls on `t` and return it [inline] pub fn type_to_ptr(t Type) Type { - nr_muls := type_nr_muls(t) + nr_muls := (int(t)>>16) & 0xff if nr_muls == 255 { panic('type_to_pre: nr_muls is already at max of 255') } - return (int(type_extra(t))<<24) | ((nr_muls + 1)<<16) | u16(type_idx(t)) + return (((int(t)>>24) & 0xff)<<24) | ((nr_muls + 1)<<16) | (u16(t) & 0xffff) } -// decrement nr_muls on Type and return it +// decrement nr_muls on `t` and return it [inline] pub fn type_deref(t Type) Type { - nr_muls := type_nr_muls(t) + nr_muls := (int(t)>>16) & 0xff if nr_muls == 0 { panic('deref: type `$t` is not a pointer') } - return (int(type_extra(t))<<24) | ((nr_muls - 1)<<16) | u16(type_idx(t)) + return (((int(t)>>24) & 0xff)<<24) | ((nr_muls - 1)<<16) | (u16(t) & 0xffff) } +// return the flag that is set on `t` [inline] -pub fn type_clear_extra(t Type) Type { - return type_set_extra(t, .unset) -} - -// return extra info -[inline] -pub fn type_extra(t Type) TypeExtra { +pub fn type_flag(t Type) TypeFlag { return (int(t)>>24) & 0xff } -// set extra info +// set the flag on `t` to `flag` and return it [inline] -pub fn type_set_extra(t Type, extra TypeExtra) Type { - return (int(extra)<<24) | (type_nr_muls(t)<<16) | u16(type_idx(t)) +pub fn type_set(t Type, flag TypeFlag) Type { + return (int(flag)<<24) | (((int(t)>>16) & 0xff)<<16) | (u16(t) & 0xffff) } +// return true if the flag set on `t` is `flag` [inline] -pub fn type_is_optional(t Type) bool { - return type_extra(t) == .optional +pub fn type_is(t Type, flag TypeFlag) bool { + return (int(t)>>24) & 0xff == flag } -[inline] -pub fn type_to_optional(t Type) Type { - return type_set_extra(t, .optional) -} - -[inline] -pub fn type_is_variadic(t Type) bool { - return type_extra(t) == .variadic -} - -[inline] -pub fn type_to_variadic(t Type) Type { - return type_set_extra(t, .variadic) -} - -// new type with idx of TypeSymbol, not pointer (nr_muls=0) +// return new type with TypeSymbol idx set to `idx` [inline] pub fn new_type(idx int) Type { if idx < 1 || idx > 65536 { @@ -127,34 +119,24 @@ pub fn new_type(idx int) Type { return idx } -// return Type idx of TypeSymbol & specify if ptr (nr_muls) +// return new type with TypeSymbol idx set to `idx` & nr_muls set to `nr_muls` [inline] pub fn new_type_ptr(idx int, nr_muls int) Type { if idx < 1 || idx > 65536 { - panic('typ_ptr: idx must be between 1 & 65536') + panic('new_type_ptr: idx must be between 1 & 65536') } if nr_muls < 0 || nr_muls > 255 { - panic('typ_ptr: nr_muls must be between 0 & 255') + panic('new_type_ptr: nr_muls must be between 0 & 255') } return (nr_muls<<16) | u16(idx) } -/* -pub fn is_number(typ Type) bool { - typ_sym := c.table.get_type_symbol(typ) - return typ_sym.is_int() - //idx := type_idx(typ) - //return idx in [int_type_idx, byte_type_idx, u64_type_idx] -} -*/ - - pub fn is_number(typ Type) bool { return type_idx(typ) in number_type_idxs } pub const ( -// primitive types + // primitive types void_type_idx = 1 voidptr_type_idx = 2 byteptr_type_idx = 3 @@ -630,7 +612,7 @@ pub fn (table &Table) type_to_str(t Type) string { res = vals[vals.len - 2] + '.' + vals[vals.len - 1] } } - if type_is_optional(t) { + if type_is(t, .optional) { res = '?' + res } nr_muls := type_nr_muls(t) diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 3c85a1ba70..65a95d19ea 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -385,9 +385,9 @@ pub fn (t mut 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 type_is_variadic(typ) { + if type_is(typ, .variadic) { // ...string => string - return type_clear_extra(typ) + return type_set(typ, .unset) } else if typ_sym.kind == .array { // Check index type