table: simplify/generalise type fns & remove calls
parent
bf59828897
commit
c9e290b36f
|
@ -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)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
field_name := selector_expr.field
|
field_name := selector_expr.field
|
||||||
// variadic
|
// variadic
|
||||||
if table.type_is_variadic(typ) {
|
if table.type_is(typ, .variadic) {
|
||||||
if field_name == 'len' {
|
if field_name == 'len' {
|
||||||
return table.int_type
|
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 := c.fn_return_type
|
||||||
expected_type_sym := c.table.get_type_symbol(expected_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]
|
mut expected_types := [expected_type]
|
||||||
if expected_type_sym.kind == .multi_return {
|
if expected_type_sym.kind == .multi_return {
|
||||||
mr_info := expected_type_sym.info as table.MultiReturn
|
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 {
|
if typ == 0 {
|
||||||
typ = c.expr(var.expr)
|
typ = c.expr(var.expr)
|
||||||
}
|
}
|
||||||
|
is_optional := table.type_is(typ, .optional)
|
||||||
ident.kind = .variable
|
ident.kind = .variable
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
typ: typ
|
||||||
is_optional: table.type_is_optional(typ)
|
is_optional: is_optional
|
||||||
}
|
}
|
||||||
// unwrap optional (`println(x)`)
|
// unwrap optional (`println(x)`)
|
||||||
if table.type_is_optional(typ) {
|
if is_optional {
|
||||||
return table.type_clear_extra(typ)
|
return table.type_set(typ, .unset)
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,7 +162,7 @@ pub fn (g mut Gen) typ(t table.Type) string {
|
||||||
styp = 'struct $styp'
|
styp = 'struct $styp'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if table.type_is_optional(t) {
|
if table.type_is(t, .optional) {
|
||||||
styp = 'Option_' + styp
|
styp = 'Option_' + styp
|
||||||
if !(styp in g.optionals) {
|
if !(styp in g.optionals) {
|
||||||
g.definitions.writeln('typedef Option $styp;')
|
g.definitions.writeln('typedef Option $styp;')
|
||||||
|
@ -506,7 +506,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
else if table.type_is_variadic(it.cond_type) {
|
else if table.type_is(it.cond_type, .variadic) {
|
||||||
g.writeln('// FOR IN')
|
g.writeln('// FOR IN')
|
||||||
i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var }
|
i := if it.key_var == '' { g.new_tmp_var() } else { it.key_var }
|
||||||
styp := g.typ(it.cond_type)
|
styp := g.typ(it.cond_type)
|
||||||
|
@ -597,7 +597,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
else {}
|
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_var_name := 'mr_$assign_stmt.pos.pos'
|
||||||
mr_styp := g.typ(return_type)
|
mr_styp := g.typ(return_type)
|
||||||
g.write('$mr_styp $mr_var_name = ')
|
g.write('$mr_styp $mr_var_name = ')
|
||||||
|
@ -644,7 +644,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
else {}
|
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
|
g.is_assign_rhs = true
|
||||||
if ident.kind == .blank_ident {
|
if ident.kind == .blank_ident {
|
||||||
if is_call {
|
if is_call {
|
||||||
|
@ -846,10 +846,11 @@ fn (g mut Gen) free_scope_vars(pos int) {
|
||||||
// }
|
// }
|
||||||
var := *it
|
var := *it
|
||||||
sym := g.table.get_type_symbol(var.typ)
|
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')
|
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.
|
// Don't free simple string literals.
|
||||||
t := typeof(var.expr)
|
t := typeof(var.expr)
|
||||||
match var.expr {
|
match var.expr {
|
||||||
|
@ -1220,7 +1221,7 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) {
|
||||||
}
|
}
|
||||||
else {}
|
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 { '' }
|
tmp_opt := if gen_or { g.new_tmp_var() } else { '' }
|
||||||
if gen_or {
|
if gen_or {
|
||||||
rstyp := g.typ(return_type)
|
rstyp := g.typ(return_type)
|
||||||
|
@ -1239,7 +1240,7 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g.is_assign_lhs = true
|
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
|
g.right_is_opt = true
|
||||||
}
|
}
|
||||||
mut str_add := false
|
mut str_add := false
|
||||||
|
@ -1672,7 +1673,7 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
||||||
if !is_range {
|
if !is_range {
|
||||||
sym := g.table.get_type_symbol(node.left_type)
|
sym := g.table.get_type_symbol(node.left_type)
|
||||||
left_is_ptr := table.type_is_ptr(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.expr(node.left)
|
||||||
g.write('.args')
|
g.write('.args')
|
||||||
g.write('[')
|
g.write('[')
|
||||||
|
@ -1778,7 +1779,7 @@ fn (g mut Gen) return_statement(node ast.Return) {
|
||||||
g.writeln(' 0;')
|
g.writeln(' 0;')
|
||||||
return
|
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
|
// multiple returns
|
||||||
if node.exprs.len > 1 {
|
if node.exprs.len > 1 {
|
||||||
g.write(' ')
|
g.write(' ')
|
||||||
|
@ -1806,7 +1807,7 @@ fn (g mut Gen) return_statement(node ast.Return) {
|
||||||
else if node.exprs.len == 1 {
|
else if node.exprs.len == 1 {
|
||||||
g.write(' ')
|
g.write(' ')
|
||||||
// `return opt_ok(expr)` for functions that expect an optional
|
// `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_none := false
|
||||||
mut is_error := false
|
mut is_error := false
|
||||||
expr0 := node.exprs[0]
|
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) {
|
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
|
mut arg_no := 0
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if is_variadic && arg_no == expected_types.len - 1 {
|
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)
|
g.expr(node.left)
|
||||||
is_variadic := node.expected_arg_types.len > 0 &&
|
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 {
|
if node.args.len > 0 || is_variadic {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
|
@ -2436,7 +2437,7 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
g.str_types << styp
|
g.str_types << styp
|
||||||
g.gen_str_for_type(sym, 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
|
// Create a temporary variable so that the value can be freed
|
||||||
tmp := g.new_tmp_var()
|
tmp := g.new_tmp_var()
|
||||||
// tmps << tmp
|
// tmps << tmp
|
||||||
|
|
|
@ -202,7 +202,7 @@ fn (p mut Parser) fn_args() ([]table.Arg,bool) {
|
||||||
}
|
}
|
||||||
mut arg_type := p.parse_type()
|
mut arg_type := p.parse_type()
|
||||||
if is_variadic {
|
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 p.tok.kind == .comma {
|
||||||
if is_variadic {
|
if is_variadic {
|
||||||
|
@ -236,7 +236,7 @@ fn (p mut Parser) fn_args() ([]table.Arg,bool) {
|
||||||
}
|
}
|
||||||
mut typ := p.parse_type()
|
mut typ := p.parse_type()
|
||||||
if is_variadic {
|
if is_variadic {
|
||||||
typ = table.type_to_variadic(typ)
|
typ = table.type_set(typ, .variadic)
|
||||||
}
|
}
|
||||||
for arg_name in arg_names {
|
for arg_name in arg_names {
|
||||||
args << table.Arg{
|
args << table.Arg{
|
||||||
|
|
|
@ -115,7 +115,7 @@ pub fn (p mut Parser) parse_type() table.Type {
|
||||||
}
|
}
|
||||||
mut typ := p.parse_any_type(is_c, nr_muls > 0)
|
mut typ := p.parse_any_type(is_c, nr_muls > 0)
|
||||||
if is_optional {
|
if is_optional {
|
||||||
typ = table.type_to_optional(typ)
|
typ = table.type_set(typ, .optional)
|
||||||
}
|
}
|
||||||
if nr_muls > 0 {
|
if nr_muls > 0 {
|
||||||
typ = table.type_set_nr_muls(typ, nr_muls)
|
typ = table.type_set_nr_muls(typ, nr_muls)
|
||||||
|
|
|
@ -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
|
module table
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -17,10 +29,9 @@ mut:
|
||||||
kind Kind
|
kind Kind
|
||||||
name string
|
name string
|
||||||
methods []Fn
|
methods []Fn
|
||||||
// is_sum bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TypeExtra {
|
pub enum TypeFlag {
|
||||||
unset
|
unset
|
||||||
optional
|
optional
|
||||||
variadic
|
variadic
|
||||||
|
@ -35,90 +46,71 @@ pub fn (types []Type) contains(typ Type) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// return underlying TypeSymbol idx
|
// return TypeSymbol idx for `t`
|
||||||
[inline]
|
[inline]
|
||||||
pub fn type_idx(t Type) int {
|
pub fn type_idx(t Type) int {
|
||||||
return u16(t) & 0xffff
|
return u16(t) & 0xffff
|
||||||
}
|
}
|
||||||
|
|
||||||
// return nr_muls
|
// return nr_muls for `t`
|
||||||
[inline]
|
[inline]
|
||||||
pub fn type_nr_muls(t Type) int {
|
pub fn type_nr_muls(t Type) int {
|
||||||
return (int(t)>>16) & 0xff
|
return (int(t)>>16) & 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if pointer (nr_muls>0)
|
// return true if `t` is a pointer (nr_muls>0)
|
||||||
[inline]
|
[inline]
|
||||||
pub fn type_is_ptr(t Type) bool {
|
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]
|
[inline]
|
||||||
pub fn type_set_nr_muls(t Type, nr_muls int) Type {
|
pub fn type_set_nr_muls(t Type, nr_muls int) Type {
|
||||||
if nr_muls < 0 || nr_muls > 255 {
|
if nr_muls < 0 || nr_muls > 255 {
|
||||||
panic('typ_set_nr_muls: nr_muls must be between 0 & 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]
|
[inline]
|
||||||
pub fn type_to_ptr(t Type) Type {
|
pub fn type_to_ptr(t Type) Type {
|
||||||
nr_muls := type_nr_muls(t)
|
nr_muls := (int(t)>>16) & 0xff
|
||||||
if nr_muls == 255 {
|
if nr_muls == 255 {
|
||||||
panic('type_to_pre: nr_muls is already at max of 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]
|
[inline]
|
||||||
pub fn type_deref(t Type) Type {
|
pub fn type_deref(t Type) Type {
|
||||||
nr_muls := type_nr_muls(t)
|
nr_muls := (int(t)>>16) & 0xff
|
||||||
if nr_muls == 0 {
|
if nr_muls == 0 {
|
||||||
panic('deref: type `$t` is not a pointer')
|
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]
|
[inline]
|
||||||
pub fn type_clear_extra(t Type) Type {
|
pub fn type_flag(t Type) TypeFlag {
|
||||||
return type_set_extra(t, .unset)
|
|
||||||
}
|
|
||||||
|
|
||||||
// return extra info
|
|
||||||
[inline]
|
|
||||||
pub fn type_extra(t Type) TypeExtra {
|
|
||||||
return (int(t)>>24) & 0xff
|
return (int(t)>>24) & 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
// set extra info
|
// set the flag on `t` to `flag` and return it
|
||||||
[inline]
|
[inline]
|
||||||
pub fn type_set_extra(t Type, extra TypeExtra) Type {
|
pub fn type_set(t Type, flag TypeFlag) Type {
|
||||||
return (int(extra)<<24) | (type_nr_muls(t)<<16) | u16(type_idx(t))
|
return (int(flag)<<24) | (((int(t)>>16) & 0xff)<<16) | (u16(t) & 0xffff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return true if the flag set on `t` is `flag`
|
||||||
[inline]
|
[inline]
|
||||||
pub fn type_is_optional(t Type) bool {
|
pub fn type_is(t Type, flag TypeFlag) bool {
|
||||||
return type_extra(t) == .optional
|
return (int(t)>>24) & 0xff == flag
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
// return new type with TypeSymbol idx set to `idx`
|
||||||
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)
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn new_type(idx int) Type {
|
pub fn new_type(idx int) Type {
|
||||||
if idx < 1 || idx > 65536 {
|
if idx < 1 || idx > 65536 {
|
||||||
|
@ -127,28 +119,18 @@ pub fn new_type(idx int) Type {
|
||||||
return idx
|
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]
|
[inline]
|
||||||
pub fn new_type_ptr(idx int, nr_muls int) Type {
|
pub fn new_type_ptr(idx int, nr_muls int) Type {
|
||||||
if idx < 1 || idx > 65536 {
|
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 {
|
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)
|
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 {
|
pub fn is_number(typ Type) bool {
|
||||||
return type_idx(typ) in number_type_idxs
|
return type_idx(typ) in number_type_idxs
|
||||||
}
|
}
|
||||||
|
@ -630,7 +612,7 @@ pub fn (table &Table) type_to_str(t Type) string {
|
||||||
res = vals[vals.len - 2] + '.' + vals[vals.len - 1]
|
res = vals[vals.len - 2] + '.' + vals[vals.len - 1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if type_is_optional(t) {
|
if type_is(t, .optional) {
|
||||||
res = '?' + res
|
res = '?' + res
|
||||||
}
|
}
|
||||||
nr_muls := type_nr_muls(t)
|
nr_muls := type_nr_muls(t)
|
||||||
|
|
|
@ -385,9 +385,9 @@ pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) value_type(typ Type) Type {
|
pub fn (t &Table) value_type(typ Type) Type {
|
||||||
typ_sym := t.get_type_symbol(typ)
|
typ_sym := t.get_type_symbol(typ)
|
||||||
if type_is_variadic(typ) {
|
if type_is(typ, .variadic) {
|
||||||
// ...string => string
|
// ...string => string
|
||||||
return type_clear_extra(typ)
|
return type_set(typ, .unset)
|
||||||
}
|
}
|
||||||
else if typ_sym.kind == .array {
|
else if typ_sym.kind == .array {
|
||||||
// Check index type
|
// Check index type
|
||||||
|
|
Loading…
Reference in New Issue