2022-01-04 10:21:08 +01:00
|
|
|
|
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
//
|
|
|
|
|
// Type layout information (32 bits)
|
2020-04-04 14:32:42 +02:00
|
|
|
|
// flag (8 bits) | nr_muls (8 bits) | idx (16 bits)
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// pack: (int(flag)<<24) | (nr_muls<<16) | u16(idx)
|
|
|
|
|
// unpack:
|
2020-04-14 00:37:47 +02:00
|
|
|
|
// flag: (int(type)>>24) & 0xff
|
|
|
|
|
// nr_muls: (int(type)>>16) & 0xff
|
|
|
|
|
// idx: u16(type) & 0xffff
|
2021-04-02 00:57:09 +02:00
|
|
|
|
module ast
|
2020-03-13 01:43:30 +01:00
|
|
|
|
|
2020-04-17 17:16:14 +02:00
|
|
|
|
import strings
|
2021-03-17 01:43:17 +01:00
|
|
|
|
import v.pref
|
2020-03-13 01:43:30 +01:00
|
|
|
|
|
2020-09-25 12:02:32 +02:00
|
|
|
|
pub type Type = int
|
2020-03-13 01:43:30 +01:00
|
|
|
|
|
2021-09-10 19:56:55 +02:00
|
|
|
|
pub type TypeInfo = Aggregate
|
|
|
|
|
| Alias
|
|
|
|
|
| Array
|
|
|
|
|
| ArrayFixed
|
|
|
|
|
| Chan
|
|
|
|
|
| Enum
|
|
|
|
|
| FnType
|
|
|
|
|
| GenericInst
|
|
|
|
|
| Interface
|
|
|
|
|
| Map
|
|
|
|
|
| MultiReturn
|
|
|
|
|
| Struct
|
|
|
|
|
| SumType
|
|
|
|
|
| Thread
|
2020-03-13 01:43:30 +01:00
|
|
|
|
|
2020-05-19 17:12:47 +02:00
|
|
|
|
pub enum Language {
|
|
|
|
|
v
|
|
|
|
|
c
|
|
|
|
|
js
|
2021-03-17 01:43:17 +01:00
|
|
|
|
amd64 // aka x86_64
|
|
|
|
|
i386
|
2021-04-26 18:01:42 +02:00
|
|
|
|
arm64 // 64-bit arm
|
|
|
|
|
arm32 // 32-bit arm
|
2021-03-17 01:43:17 +01:00
|
|
|
|
rv64 // 64-bit risc-v
|
|
|
|
|
rv32 // 32-bit risc-v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn pref_arch_to_table_language(pref_arch pref.Arch) Language {
|
|
|
|
|
return match pref_arch {
|
|
|
|
|
.amd64 {
|
|
|
|
|
Language.amd64
|
|
|
|
|
}
|
2021-04-26 18:01:42 +02:00
|
|
|
|
.arm64 {
|
|
|
|
|
Language.arm64
|
2021-03-17 01:43:17 +01:00
|
|
|
|
}
|
2021-04-26 18:01:42 +02:00
|
|
|
|
.arm32 {
|
|
|
|
|
Language.arm32
|
2021-03-17 01:43:17 +01:00
|
|
|
|
}
|
|
|
|
|
.rv64 {
|
|
|
|
|
Language.rv64
|
|
|
|
|
}
|
|
|
|
|
.rv32 {
|
|
|
|
|
Language.rv32
|
|
|
|
|
}
|
|
|
|
|
.i386 {
|
|
|
|
|
Language.i386
|
|
|
|
|
}
|
2021-10-19 11:11:54 +02:00
|
|
|
|
.js_node, .js_browser, .js_freestanding {
|
|
|
|
|
Language.js
|
|
|
|
|
}
|
2021-06-12 21:15:08 +02:00
|
|
|
|
._auto, ._max {
|
2021-03-17 01:43:17 +01:00
|
|
|
|
Language.v
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-19 17:12:47 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-09-18 01:09:00 +02:00
|
|
|
|
// Represents a type that only needs an identifier, e.g. int, array_int.
|
|
|
|
|
// A pointer type `&T` would have a TypeSymbol `T`.
|
2020-11-17 21:26:40 +01:00
|
|
|
|
// Note: For a Type, use:
|
|
|
|
|
// * Table.type_to_str(typ) not TypeSymbol.name.
|
|
|
|
|
// * Table.type_kind(typ) not TypeSymbol.kind.
|
2020-09-18 01:09:00 +02:00
|
|
|
|
// Each TypeSymbol is entered into `Table.types`.
|
2021-12-19 17:25:18 +01:00
|
|
|
|
// See also: Table.sym.
|
2021-05-07 14:58:48 +02:00
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub struct TypeSymbol {
|
|
|
|
|
pub:
|
2020-12-06 04:55:08 +01:00
|
|
|
|
parent_idx int
|
2020-05-09 15:16:48 +02:00
|
|
|
|
pub mut:
|
2021-01-12 04:38:43 +01:00
|
|
|
|
info TypeInfo
|
|
|
|
|
kind Kind
|
|
|
|
|
name string // the internal & source name of the type, i.e. `[5]int`.
|
|
|
|
|
cname string // the name with no dots for use in the generated C code
|
|
|
|
|
methods []Fn
|
|
|
|
|
mod string
|
|
|
|
|
is_public bool
|
|
|
|
|
language Language
|
2021-07-17 13:44:38 +02:00
|
|
|
|
idx int
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-04 14:38:54 +02:00
|
|
|
|
// max of 8
|
2020-04-04 07:37:11 +02:00
|
|
|
|
pub enum TypeFlag {
|
2020-03-13 01:43:30 +01:00
|
|
|
|
optional
|
|
|
|
|
variadic
|
2020-06-01 15:43:54 +02:00
|
|
|
|
generic
|
2020-07-04 12:44:25 +02:00
|
|
|
|
shared_f
|
2020-07-07 01:57:31 +02:00
|
|
|
|
atomic_f
|
2020-07-04 12:44:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-11 15:09:12 +02:00
|
|
|
|
/*
|
2020-07-27 12:15:29 +02:00
|
|
|
|
To save precious TypeFlag bits the 4 possible ShareTypes are coded in the two
|
2020-07-04 12:44:25 +02:00
|
|
|
|
bits `shared` and `atomic_or_rw` (see sharetype_from_flags() below).
|
|
|
|
|
*/
|
|
|
|
|
pub enum ShareType {
|
|
|
|
|
mut_t
|
|
|
|
|
shared_t
|
|
|
|
|
atomic_t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (t ShareType) str() string {
|
|
|
|
|
match t {
|
|
|
|
|
.mut_t { return 'mut' }
|
|
|
|
|
.shared_t { return 'shared' }
|
|
|
|
|
.atomic_t { return 'atomic' }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// <atomic.h> defines special typenames
|
|
|
|
|
pub fn (t Type) atomic_typename() string {
|
|
|
|
|
idx := t.idx()
|
|
|
|
|
match idx {
|
2021-04-02 00:57:09 +02:00
|
|
|
|
ast.u32_type_idx { return 'atomic_uint' }
|
|
|
|
|
ast.int_type_idx { return 'atomic_int' }
|
|
|
|
|
ast.u64_type_idx { return 'atomic_ullong' }
|
|
|
|
|
ast.i64_type_idx { return 'atomic_llong' }
|
2020-07-04 12:44:25 +02:00
|
|
|
|
else { return 'unknown_atomic' }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-15 12:32:28 +02:00
|
|
|
|
pub fn sharetype_from_flags(is_shared bool, is_atomic bool) ShareType {
|
2021-11-29 01:48:49 +01:00
|
|
|
|
return ShareType(int(u32(is_atomic) << 1) | int(is_shared))
|
2020-07-04 12:44:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (t Type) share() ShareType {
|
2020-07-07 01:57:31 +02:00
|
|
|
|
return sharetype_from_flags(t.has_flag(.shared_f), t.has_flag(.atomic_f))
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// return TypeSymbol idx for `t`
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (t Type) idx() int {
|
2020-03-13 01:43:30 +01:00
|
|
|
|
return u16(t) & 0xffff
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-15 10:13:35 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t Type) is_void() bool {
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return t == ast.void_type
|
2020-11-15 10:13:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t Type) is_full() bool {
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return t != 0 && t != ast.void_type
|
2020-11-15 10:13:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// return nr_muls for `t`
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (t Type) nr_muls() int {
|
2020-04-14 00:37:47 +02:00
|
|
|
|
return (int(t) >> 16) & 0xff
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// return true if `t` is a pointer (nr_muls>0)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (t Type) is_ptr() bool {
|
2021-04-05 18:31:28 +02:00
|
|
|
|
// any normal pointer, i.e. &Type, &&Type etc;
|
2022-03-06 18:01:22 +01:00
|
|
|
|
// Note: voidptr, charptr and byteptr are NOT included!
|
2020-04-14 00:37:47 +02:00
|
|
|
|
return (int(t) >> 16) & 0xff > 0
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2020-04-14 00:37:47 +02:00
|
|
|
|
|
2021-07-18 14:04:16 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t Type) is_any_kind_of_pointer() bool {
|
|
|
|
|
return (int(t) >> 16) & 0xff > 0 || (u16(t) & 0xffff) in ast.pointer_type_idxs
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// set nr_muls on `t` and return it
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-04-25 09:54:32 +02:00
|
|
|
|
pub fn (t Type) set_nr_muls(nr_muls int) Type {
|
2020-03-13 01:43:30 +01:00
|
|
|
|
if nr_muls < 0 || nr_muls > 255 {
|
2020-04-27 15:16:31 +02:00
|
|
|
|
panic('set_nr_muls: nr_muls must be between 0 & 255')
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-11-29 01:48:49 +01:00
|
|
|
|
return int(t) & 0xff00ffff | int(u32(nr_muls) << 16)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 19:49:39 +02:00
|
|
|
|
// increments nr_muls on `t` and return it
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2021-10-06 19:49:39 +02:00
|
|
|
|
pub fn (t Type) ref() Type {
|
2020-04-14 00:37:47 +02:00
|
|
|
|
nr_muls := (int(t) >> 16) & 0xff
|
2020-03-13 01:43:30 +01:00
|
|
|
|
if nr_muls == 255 {
|
2021-10-06 19:49:39 +02:00
|
|
|
|
panic('ref: nr_muls is already at max of 255')
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-11-29 01:48:49 +01:00
|
|
|
|
return int(t) & 0xff00ffff | int(u32(nr_muls + 1) << 16)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// decrement nr_muls on `t` and return it
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (t Type) deref() Type {
|
2020-04-14 00:37:47 +02:00
|
|
|
|
nr_muls := (int(t) >> 16) & 0xff
|
2020-03-13 01:43:30 +01:00
|
|
|
|
if nr_muls == 0 {
|
|
|
|
|
panic('deref: type `$t` is not a pointer')
|
|
|
|
|
}
|
2021-11-29 01:48:49 +01:00
|
|
|
|
return int(t) & 0xff00ffff | int(u32(nr_muls - 1) << 16)
|
2020-03-15 08:18:42 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-04 14:38:54 +02:00
|
|
|
|
// set `flag` on `t` and return `t`
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-06-04 14:38:54 +02:00
|
|
|
|
pub fn (t Type) set_flag(flag TypeFlag) Type {
|
2020-07-27 12:15:29 +02:00
|
|
|
|
return int(t) | (1 << (int(flag) + 24))
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-04 14:38:54 +02:00
|
|
|
|
// clear `flag` on `t` and return `t`
|
2020-06-04 16:28:34 +02:00
|
|
|
|
[inline]
|
2020-06-04 14:38:54 +02:00
|
|
|
|
pub fn (t Type) clear_flag(flag TypeFlag) Type {
|
2020-07-27 12:15:29 +02:00
|
|
|
|
return int(t) & ~(1 << (int(flag) + 24))
|
2020-06-04 14:38:54 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// clear all flags
|
2020-06-05 10:41:15 +02:00
|
|
|
|
[inline]
|
2020-06-04 14:38:54 +02:00
|
|
|
|
pub fn (t Type) clear_flags() Type {
|
2020-06-08 15:36:59 +02:00
|
|
|
|
return int(t) & 0xffffff
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-05 10:41:15 +02:00
|
|
|
|
// return true if `flag` is set on `t`
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-06-04 14:38:54 +02:00
|
|
|
|
pub fn (t Type) has_flag(flag TypeFlag) bool {
|
2020-07-27 12:15:29 +02:00
|
|
|
|
return int(t) & (1 << (int(flag) + 24)) > 0
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-17 13:44:38 +02:00
|
|
|
|
// debug returns a verbose representation of the information in ts, useful for tracing/debugging
|
2020-11-28 18:48:35 +01:00
|
|
|
|
pub fn (ts TypeSymbol) debug() []string {
|
|
|
|
|
mut res := []string{}
|
2021-07-17 13:44:38 +02:00
|
|
|
|
ts.dbg_common(mut res)
|
|
|
|
|
res << 'info: $ts.info'
|
|
|
|
|
res << 'methods ($ts.methods.len): ' + ts.methods.map(it.str()).join(', ')
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// same as .debug(), but without the verbose .info and .methods fields
|
|
|
|
|
pub fn (ts TypeSymbol) dbg() []string {
|
|
|
|
|
mut res := []string{}
|
|
|
|
|
ts.dbg_common(mut res)
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn (ts TypeSymbol) dbg_common(mut res []string) {
|
|
|
|
|
res << 'idx: 0x$ts.idx.hex()'
|
|
|
|
|
res << 'parent_idx: 0x$ts.parent_idx.hex()'
|
2020-11-28 18:48:35 +01:00
|
|
|
|
res << 'mod: $ts.mod'
|
|
|
|
|
res << 'name: $ts.name'
|
2020-12-06 04:55:08 +01:00
|
|
|
|
res << 'cname: $ts.cname'
|
2020-11-28 18:48:35 +01:00
|
|
|
|
res << 'kind: $ts.kind'
|
|
|
|
|
res << 'is_public: $ts.is_public'
|
|
|
|
|
res << 'language: $ts.language'
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-17 13:44:38 +02:00
|
|
|
|
pub fn (t Type) str() string {
|
|
|
|
|
return 'ast.Type(0x$t.hex() = ${u32(t)})'
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-09 19:21:01 +02:00
|
|
|
|
pub fn (t &Table) type_str(typ Type) string {
|
2021-12-19 17:25:18 +01:00
|
|
|
|
sym := t.sym(typ)
|
2021-09-09 19:21:01 +02:00
|
|
|
|
return sym.name
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-17 13:44:38 +02:00
|
|
|
|
// debug returns a verbose representation of the information in the type `t`, useful for tracing/debugging
|
2020-11-14 10:39:58 +01:00
|
|
|
|
pub fn (t Type) debug() []string {
|
|
|
|
|
mut res := []string{}
|
2021-07-17 13:44:38 +02:00
|
|
|
|
res << 'idx: 0x${t.idx().hex():-8}'
|
|
|
|
|
res << 'type: 0x${t.hex():-8}'
|
2020-11-14 10:39:58 +01:00
|
|
|
|
res << 'nr_muls: $t.nr_muls()'
|
|
|
|
|
if t.has_flag(.optional) {
|
|
|
|
|
res << 'optional'
|
|
|
|
|
}
|
|
|
|
|
if t.has_flag(.variadic) {
|
|
|
|
|
res << 'variadic'
|
|
|
|
|
}
|
|
|
|
|
if t.has_flag(.generic) {
|
|
|
|
|
res << 'generic'
|
|
|
|
|
}
|
|
|
|
|
if t.has_flag(.shared_f) {
|
|
|
|
|
res << 'shared_f'
|
|
|
|
|
}
|
|
|
|
|
if t.has_flag(.atomic_f) {
|
|
|
|
|
res << 'atomic_f'
|
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-06 04:51:36 +02:00
|
|
|
|
// copy flags & nr_muls from `t_from` to `t` and return `t`
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t Type) derive(t_from Type) Type {
|
2020-06-08 15:36:59 +02:00
|
|
|
|
return (0xffff0000 & t_from) | u16(t)
|
2020-06-06 04:51:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-07 10:51:05 +02:00
|
|
|
|
// copy flags from `t_from` to `t` and return `t`
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t Type) derive_add_muls(t_from Type) Type {
|
|
|
|
|
return Type((0xff000000 & t_from) | u16(t)).set_nr_muls(t.nr_muls() + t_from.nr_muls())
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// return new type with TypeSymbol idx set to `idx`
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn new_type(idx int) Type {
|
2020-06-04 14:38:54 +02:00
|
|
|
|
if idx < 1 || idx > 65535 {
|
2020-06-29 20:09:09 +02:00
|
|
|
|
panic('new_type: idx must be between 1 & 65535')
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
return idx
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 07:37:11 +02:00
|
|
|
|
// return new type with TypeSymbol idx set to `idx` & nr_muls set to `nr_muls`
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
2020-10-15 12:32:28 +02:00
|
|
|
|
pub fn new_type_ptr(idx int, nr_muls int) Type {
|
2020-06-04 14:38:54 +02:00
|
|
|
|
if idx < 1 || idx > 65535 {
|
|
|
|
|
panic('new_type_ptr: idx must be between 1 & 65535')
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
if nr_muls < 0 || nr_muls > 255 {
|
2020-04-04 07:37:11 +02:00
|
|
|
|
panic('new_type_ptr: nr_muls must be between 0 & 255')
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-11-29 01:48:49 +01:00
|
|
|
|
return (u32(nr_muls) << 16) | u16(idx)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 00:24:33 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_pointer() bool {
|
2021-04-05 18:31:28 +02:00
|
|
|
|
// builtin pointer types (voidptr, byteptr, charptr)
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return typ.idx() in ast.pointer_type_idxs
|
2020-05-05 00:24:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-09 19:21:01 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_real_pointer() bool {
|
|
|
|
|
return typ.is_ptr() || typ.is_pointer()
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 06:14:17 +02:00
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (typ Type) is_float() bool {
|
2021-04-05 17:45:03 +02:00
|
|
|
|
return typ.clear_flags() in ast.float_type_idxs
|
2020-04-25 06:14:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (typ Type) is_int() bool {
|
2021-04-05 17:45:03 +02:00
|
|
|
|
return typ.clear_flags() in ast.integer_type_idxs
|
2020-04-25 06:14:17 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-05 18:31:28 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_int_valptr() bool {
|
|
|
|
|
return typ.idx() in ast.integer_type_idxs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_float_valptr() bool {
|
|
|
|
|
return typ.idx() in ast.float_type_idxs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_pure_int() bool {
|
|
|
|
|
return int(typ) in ast.integer_type_idxs
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_pure_float() bool {
|
|
|
|
|
return int(typ) in ast.float_type_idxs
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-02 00:43:59 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_signed() bool {
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return typ.idx() in ast.signed_integer_type_idxs
|
2020-05-02 00:43:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_unsigned() bool {
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return typ.idx() in ast.unsigned_integer_type_idxs
|
2020-05-02 00:43:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-24 14:26:43 +02:00
|
|
|
|
[inline]
|
2021-01-11 22:58:15 +01:00
|
|
|
|
pub fn (typ Type) is_int_literal() bool {
|
2021-04-05 09:02:47 +02:00
|
|
|
|
return int(typ) == ast.int_literal_type_idx
|
2020-05-24 14:26:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-25 06:14:17 +02:00
|
|
|
|
[inline]
|
2020-04-25 09:08:53 +02:00
|
|
|
|
pub fn (typ Type) is_number() bool {
|
2021-04-05 17:45:03 +02:00
|
|
|
|
return typ.clear_flags() in ast.number_type_idxs
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-16 10:41:51 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_string() bool {
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return typ.idx() in ast.string_type_idxs
|
2020-06-16 10:41:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-18 08:00:20 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (typ Type) is_bool() bool {
|
|
|
|
|
return typ.idx() == ast.bool_type_idx
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub const (
|
2021-01-11 22:58:15 +01:00
|
|
|
|
void_type_idx = 1
|
|
|
|
|
voidptr_type_idx = 2
|
|
|
|
|
byteptr_type_idx = 3
|
|
|
|
|
charptr_type_idx = 4
|
|
|
|
|
i8_type_idx = 5
|
|
|
|
|
i16_type_idx = 6
|
|
|
|
|
int_type_idx = 7
|
|
|
|
|
i64_type_idx = 8
|
2021-09-08 04:53:39 +02:00
|
|
|
|
isize_type_idx = 9
|
|
|
|
|
byte_type_idx = 10
|
|
|
|
|
u16_type_idx = 11
|
|
|
|
|
u32_type_idx = 12
|
|
|
|
|
u64_type_idx = 13
|
|
|
|
|
usize_type_idx = 14
|
|
|
|
|
f32_type_idx = 15
|
|
|
|
|
f64_type_idx = 16
|
|
|
|
|
char_type_idx = 17
|
|
|
|
|
bool_type_idx = 18
|
|
|
|
|
none_type_idx = 19
|
|
|
|
|
string_type_idx = 20
|
|
|
|
|
rune_type_idx = 21
|
|
|
|
|
array_type_idx = 22
|
|
|
|
|
map_type_idx = 23
|
|
|
|
|
chan_type_idx = 24
|
2021-09-21 01:12:38 +02:00
|
|
|
|
any_type_idx = 25
|
|
|
|
|
float_literal_type_idx = 26
|
|
|
|
|
int_literal_type_idx = 27
|
|
|
|
|
thread_type_idx = 28
|
|
|
|
|
error_type_idx = 29
|
|
|
|
|
u8_type_idx = 30
|
2020-03-13 01:43:30 +01:00
|
|
|
|
)
|
|
|
|
|
|
2022-03-06 18:01:22 +01:00
|
|
|
|
// Note: builtin_type_names must be in the same order as the idx consts above
|
2021-11-07 15:02:37 +01:00
|
|
|
|
pub const builtin_type_names = ['void', 'voidptr', 'byteptr', 'charptr', 'i8', 'i16', 'int', 'i64',
|
|
|
|
|
'isize', 'byte', 'u16', 'u32', 'u64', 'usize', 'f32', 'f64', 'char', 'bool', 'none', 'string',
|
|
|
|
|
'rune', 'array', 'map', 'chan', 'any', 'float_literal', 'int_literal', 'thread', 'Error', 'u8']
|
|
|
|
|
|
|
|
|
|
pub const builtin_type_names_matcher = build_builtin_type_names_matcher()
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub const (
|
2021-03-22 23:06:12 +01:00
|
|
|
|
integer_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx,
|
2021-09-08 04:53:39 +02:00
|
|
|
|
byte_type_idx, u8_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx,
|
|
|
|
|
usize_type_idx, int_literal_type_idx, rune_type_idx]
|
2021-11-29 01:48:49 +01:00
|
|
|
|
signed_integer_type_idxs = [char_type_idx, i8_type_idx, i16_type_idx, int_type_idx,
|
|
|
|
|
i64_type_idx, isize_type_idx]
|
|
|
|
|
unsigned_integer_type_idxs = [byte_type_idx, u8_type_idx, u16_type_idx, u32_type_idx,
|
|
|
|
|
u64_type_idx, usize_type_idx]
|
2021-01-11 22:58:15 +01:00
|
|
|
|
float_type_idxs = [f32_type_idx, f64_type_idx, float_literal_type_idx]
|
2021-03-22 23:06:12 +01:00
|
|
|
|
number_type_idxs = [i8_type_idx, i16_type_idx, int_type_idx, i64_type_idx,
|
2021-11-29 01:48:49 +01:00
|
|
|
|
byte_type_idx, char_type_idx, u16_type_idx, u32_type_idx, u64_type_idx, isize_type_idx,
|
|
|
|
|
usize_type_idx, f32_type_idx, f64_type_idx, int_literal_type_idx, float_literal_type_idx,
|
|
|
|
|
rune_type_idx]
|
2020-05-04 00:14:59 +02:00
|
|
|
|
pointer_type_idxs = [voidptr_type_idx, byteptr_type_idx, charptr_type_idx]
|
2021-07-03 19:14:09 +02:00
|
|
|
|
string_type_idxs = [string_type_idx]
|
2020-03-13 01:43:30 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
pub const (
|
2021-01-11 22:58:15 +01:00
|
|
|
|
void_type = new_type(void_type_idx)
|
|
|
|
|
ovoid_type = new_type(void_type_idx).set_flag(.optional) // the return type of `fn () ?`
|
|
|
|
|
voidptr_type = new_type(voidptr_type_idx)
|
|
|
|
|
byteptr_type = new_type(byteptr_type_idx)
|
|
|
|
|
charptr_type = new_type(charptr_type_idx)
|
|
|
|
|
i8_type = new_type(i8_type_idx)
|
|
|
|
|
int_type = new_type(int_type_idx)
|
|
|
|
|
i16_type = new_type(i16_type_idx)
|
|
|
|
|
i64_type = new_type(i64_type_idx)
|
2021-09-08 04:53:39 +02:00
|
|
|
|
isize_type = new_type(isize_type_idx)
|
2021-01-11 22:58:15 +01:00
|
|
|
|
byte_type = new_type(byte_type_idx)
|
2021-07-29 04:00:03 +02:00
|
|
|
|
u8_type = new_type(u8_type_idx)
|
2021-01-11 22:58:15 +01:00
|
|
|
|
u16_type = new_type(u16_type_idx)
|
|
|
|
|
u32_type = new_type(u32_type_idx)
|
|
|
|
|
u64_type = new_type(u64_type_idx)
|
2021-09-08 04:53:39 +02:00
|
|
|
|
usize_type = new_type(usize_type_idx)
|
2021-01-11 22:58:15 +01:00
|
|
|
|
f32_type = new_type(f32_type_idx)
|
|
|
|
|
f64_type = new_type(f64_type_idx)
|
|
|
|
|
char_type = new_type(char_type_idx)
|
|
|
|
|
bool_type = new_type(bool_type_idx)
|
|
|
|
|
none_type = new_type(none_type_idx)
|
|
|
|
|
string_type = new_type(string_type_idx)
|
|
|
|
|
rune_type = new_type(rune_type_idx)
|
|
|
|
|
array_type = new_type(array_type_idx)
|
|
|
|
|
map_type = new_type(map_type_idx)
|
|
|
|
|
chan_type = new_type(chan_type_idx)
|
|
|
|
|
any_type = new_type(any_type_idx)
|
|
|
|
|
float_literal_type = new_type(float_literal_type_idx)
|
|
|
|
|
int_literal_type = new_type(int_literal_type_idx)
|
2021-02-22 14:08:52 +01:00
|
|
|
|
thread_type = new_type(thread_type_idx)
|
2021-02-28 20:24:29 +01:00
|
|
|
|
error_type = new_type(error_type_idx)
|
2021-04-11 21:53:58 +02:00
|
|
|
|
charptr_types = [charptr_type, new_type(char_type_idx).set_nr_muls(1)]
|
|
|
|
|
byteptr_types = [byteptr_type, new_type(byte_type_idx).set_nr_muls(1)]
|
2021-06-28 08:48:58 +02:00
|
|
|
|
voidptr_types = [voidptr_type, new_type(voidptr_type_idx).set_nr_muls(1)]
|
|
|
|
|
cptr_types = merge_types(voidptr_types, byteptr_types, charptr_types)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
)
|
|
|
|
|
|
2021-06-28 08:48:58 +02:00
|
|
|
|
pub fn merge_types(params ...[]Type) []Type {
|
|
|
|
|
mut res := []Type{}
|
|
|
|
|
for types in params {
|
|
|
|
|
res << types
|
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-04 17:37:18 +01:00
|
|
|
|
pub fn mktyp(typ Type) Type {
|
|
|
|
|
match typ {
|
|
|
|
|
ast.float_literal_type { return ast.f64_type }
|
|
|
|
|
ast.int_literal_type { return ast.int_type }
|
|
|
|
|
else { return typ }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub struct MultiReturn {
|
2020-05-09 15:16:48 +02:00
|
|
|
|
pub mut:
|
2020-03-13 01:43:30 +01:00
|
|
|
|
types []Type
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-16 10:12:03 +01:00
|
|
|
|
pub struct FnType {
|
2021-05-13 11:26:13 +02:00
|
|
|
|
pub mut:
|
2020-03-16 10:12:03 +01:00
|
|
|
|
is_anon bool
|
|
|
|
|
has_decl bool
|
|
|
|
|
func Fn
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-17 21:26:40 +01:00
|
|
|
|
// returns TypeSymbol kind only if there are no type modifiers
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (t &Table) type_kind(typ Type) Kind {
|
2020-11-17 21:26:40 +01:00
|
|
|
|
if typ.nr_muls() > 0 || typ.has_flag(.optional) {
|
|
|
|
|
return Kind.placeholder
|
|
|
|
|
}
|
2021-12-19 17:25:18 +01:00
|
|
|
|
return t.sym(typ).kind
|
2020-11-17 21:26:40 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub enum Kind {
|
|
|
|
|
placeholder
|
|
|
|
|
void
|
|
|
|
|
voidptr
|
|
|
|
|
byteptr
|
|
|
|
|
charptr
|
|
|
|
|
i8
|
|
|
|
|
i16
|
|
|
|
|
int
|
|
|
|
|
i64
|
2021-09-08 04:53:39 +02:00
|
|
|
|
isize
|
2020-03-13 01:43:30 +01:00
|
|
|
|
byte
|
2021-07-29 04:00:03 +02:00
|
|
|
|
u8
|
2020-03-13 01:43:30 +01:00
|
|
|
|
u16
|
|
|
|
|
u32
|
|
|
|
|
u64
|
2021-09-08 04:53:39 +02:00
|
|
|
|
usize
|
2020-03-13 01:43:30 +01:00
|
|
|
|
f32
|
|
|
|
|
f64
|
|
|
|
|
char
|
2020-08-25 18:15:19 +02:00
|
|
|
|
rune
|
2020-03-13 01:43:30 +01:00
|
|
|
|
bool
|
|
|
|
|
none_
|
|
|
|
|
string
|
|
|
|
|
array
|
|
|
|
|
array_fixed
|
|
|
|
|
map
|
2020-08-14 21:18:42 +02:00
|
|
|
|
chan
|
2020-05-03 18:08:45 +02:00
|
|
|
|
any
|
2020-03-13 01:43:30 +01:00
|
|
|
|
struct_
|
2021-08-04 02:37:27 +02:00
|
|
|
|
generic_inst
|
2020-03-13 01:43:30 +01:00
|
|
|
|
multi_return
|
2020-11-25 12:09:40 +01:00
|
|
|
|
sum_type
|
2020-03-13 01:43:30 +01:00
|
|
|
|
alias
|
|
|
|
|
enum_
|
|
|
|
|
function
|
2020-04-22 20:20:49 +02:00
|
|
|
|
interface_
|
2021-01-11 22:58:15 +01:00
|
|
|
|
float_literal
|
|
|
|
|
int_literal
|
2020-10-01 01:07:36 +02:00
|
|
|
|
aggregate
|
2021-02-22 14:08:52 +01:00
|
|
|
|
thread
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 09:28:04 +02:00
|
|
|
|
pub fn (t TypeSymbol) str() string {
|
2021-03-16 23:18:43 +01:00
|
|
|
|
return t.name
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-12-30 12:16:56 +01:00
|
|
|
|
[noreturn]
|
|
|
|
|
fn (t &TypeSymbol) no_info_panic(fname string) {
|
|
|
|
|
panic('$fname: no info for type: $t.name')
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) enum_info() Enum {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Enum {
|
|
|
|
|
return t.info
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is Enum {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) mr_info() MultiReturn {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is MultiReturn {
|
|
|
|
|
return t.info
|
|
|
|
|
}
|
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is MultiReturn {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) array_info() Array {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Array {
|
|
|
|
|
return t.info
|
|
|
|
|
}
|
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is Array {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) array_fixed_info() ArrayFixed {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is ArrayFixed {
|
|
|
|
|
return t.info
|
|
|
|
|
}
|
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is ArrayFixed {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-08-14 21:18:42 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) chan_info() Chan {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Chan {
|
|
|
|
|
return t.info
|
2020-08-14 21:18:42 +02:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is Chan {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-08-14 21:18:42 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 13:45:26 +01:00
|
|
|
|
[inline]
|
2021-02-22 14:08:52 +01:00
|
|
|
|
pub fn (t &TypeSymbol) thread_info() Thread {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Thread {
|
|
|
|
|
return t.info
|
2021-01-15 13:45:26 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is Thread {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
t.no_info_panic(@METHOD)
|
2021-01-15 13:45:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) map_info() Map {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Map {
|
|
|
|
|
return t.info
|
|
|
|
|
}
|
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is Map {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-27 22:53:26 +02:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) struct_info() Struct {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is Struct {
|
|
|
|
|
return t.info
|
|
|
|
|
}
|
|
|
|
|
if t.info is Alias {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is Struct {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
2020-04-27 22:53:26 +02:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
t.no_info_panic(@METHOD)
|
2020-04-27 22:53:26 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-03-22 06:39:07 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) sumtype_info() SumType {
|
2021-12-30 12:16:56 +01:00
|
|
|
|
if t.info is SumType {
|
|
|
|
|
return t.info
|
|
|
|
|
}
|
|
|
|
|
if t.info is SumType {
|
|
|
|
|
fsym := global_table.final_sym(t.info.parent_type)
|
|
|
|
|
if fsym.info is SumType {
|
|
|
|
|
return fsym.info
|
|
|
|
|
}
|
2021-03-22 06:39:07 +01:00
|
|
|
|
}
|
2021-12-30 12:16:56 +01:00
|
|
|
|
t.no_info_panic(@METHOD)
|
2021-03-22 06:39:07 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-07 14:58:48 +02:00
|
|
|
|
pub fn (t &TypeSymbol) is_heap() bool {
|
|
|
|
|
if t.kind == .struct_ {
|
|
|
|
|
info := t.info as Struct
|
|
|
|
|
return info.is_heap
|
|
|
|
|
} else {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:20:49 +02:00
|
|
|
|
pub fn (mut t Table) register_builtin_type_symbols() {
|
2020-03-13 01:43:30 +01:00
|
|
|
|
// reserve index 0 so nothing can go there
|
|
|
|
|
// save index check, 0 will mean not found
|
2022-01-19 19:16:23 +01:00
|
|
|
|
t.register_sym(kind: .placeholder, name: 'reserved_0')
|
|
|
|
|
t.register_sym(kind: .void, name: 'void', cname: 'void', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .voidptr, name: 'voidptr', cname: 'voidptr', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .byteptr, name: 'byteptr', cname: 'byteptr', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .charptr, name: 'charptr', cname: 'charptr', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .i8, name: 'i8', cname: 'i8', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .i16, name: 'i16', cname: 'i16', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .int, name: 'int', cname: 'int', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .i64, name: 'i64', cname: 'i64', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .isize, name: 'isize', cname: 'isize', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .byte, name: 'byte', cname: 'byte', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .u16, name: 'u16', cname: 'u16', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .u32, name: 'u32', cname: 'u32', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .u64, name: 'u64', cname: 'u64', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .usize, name: 'usize', cname: 'usize', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .f32, name: 'f32', cname: 'f32', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .f64, name: 'f64', cname: 'f64', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .char, name: 'char', cname: 'char', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .bool, name: 'bool', cname: 'bool', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .none_, name: 'none', cname: 'none', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .string, name: 'string', cname: 'string', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .rune, name: 'rune', cname: 'rune', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .array, name: 'array', cname: 'array', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .map, name: 'map', cname: 'map', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .chan, name: 'chan', cname: 'chan', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .any, name: 'any', cname: 'any', mod: 'builtin')
|
|
|
|
|
t.register_sym(
|
2021-01-11 22:58:15 +01:00
|
|
|
|
kind: .float_literal
|
2021-01-03 23:11:09 +01:00
|
|
|
|
name: 'float literal'
|
2021-01-11 22:58:15 +01:00
|
|
|
|
cname: 'float_literal'
|
|
|
|
|
mod: 'builtin'
|
|
|
|
|
)
|
2022-01-19 19:16:23 +01:00
|
|
|
|
t.register_sym(
|
2021-01-11 22:58:15 +01:00
|
|
|
|
kind: .int_literal
|
|
|
|
|
name: 'int literal'
|
|
|
|
|
cname: 'int_literal'
|
2021-01-03 18:02:33 +01:00
|
|
|
|
mod: 'builtin'
|
|
|
|
|
)
|
2022-01-19 19:16:23 +01:00
|
|
|
|
t.register_sym(
|
2021-02-23 08:37:29 +01:00
|
|
|
|
kind: .thread
|
|
|
|
|
name: 'thread'
|
|
|
|
|
cname: '__v_thread'
|
|
|
|
|
mod: 'builtin'
|
|
|
|
|
info: Thread{
|
2021-04-02 00:57:09 +02:00
|
|
|
|
return_type: ast.void_type
|
2021-02-23 08:37:29 +01:00
|
|
|
|
}
|
|
|
|
|
)
|
2022-01-19 19:16:23 +01:00
|
|
|
|
t.register_sym(kind: .interface_, name: 'IError', cname: 'IError', mod: 'builtin')
|
|
|
|
|
t.register_sym(kind: .u8, name: 'zu8', cname: 'zu8', mod: 'builtin')
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 13:36:27 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_pointer() bool {
|
|
|
|
|
return t.kind in [.byteptr, .charptr, .voidptr]
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_int() bool {
|
2021-09-08 04:53:39 +02:00
|
|
|
|
res := t.kind in [.i8, .i16, .int, .i64, .isize, .byte, .u16, .u32, .u64, .usize, .int_literal,
|
2021-09-21 15:20:09 +02:00
|
|
|
|
.rune]
|
2021-06-12 13:35:33 +02:00
|
|
|
|
if !res && t.kind == .alias {
|
|
|
|
|
return (t.info as Alias).parent_type.is_number()
|
|
|
|
|
}
|
|
|
|
|
return res
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_float() bool {
|
2021-01-11 22:58:15 +01:00
|
|
|
|
return t.kind in [.f32, .f64, .float_literal]
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 02:27:19 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_string() bool {
|
2021-07-03 19:14:09 +02:00
|
|
|
|
return t.kind == .string
|
2021-01-15 02:27:19 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_number() bool {
|
|
|
|
|
return t.is_int() || t.is_float()
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-15 02:27:19 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_primitive() bool {
|
|
|
|
|
return t.is_number() || t.is_pointer() || t.is_string()
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-26 11:19:48 +01:00
|
|
|
|
[inline]
|
|
|
|
|
pub fn (t &TypeSymbol) is_builtin() bool {
|
|
|
|
|
return t.mod == 'builtin'
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-03 18:08:45 +02:00
|
|
|
|
// for debugging/errors only, perf is not an issue
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub fn (k Kind) str() string {
|
|
|
|
|
k_str := match k {
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.placeholder { 'placeholder' }
|
|
|
|
|
.void { 'void' }
|
|
|
|
|
.voidptr { 'voidptr' }
|
|
|
|
|
.charptr { 'charptr' }
|
|
|
|
|
.byteptr { 'byteptr' }
|
|
|
|
|
.struct_ { 'struct' }
|
|
|
|
|
.int { 'int' }
|
|
|
|
|
.i8 { 'i8' }
|
|
|
|
|
.i16 { 'i16' }
|
|
|
|
|
.i64 { 'i64' }
|
2021-09-08 04:53:39 +02:00
|
|
|
|
.isize { 'isize' }
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.byte { 'byte' }
|
2021-07-29 04:00:03 +02:00
|
|
|
|
.u8 { 'u8' }
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.u16 { 'u16' }
|
|
|
|
|
.u32 { 'u32' }
|
|
|
|
|
.u64 { 'u64' }
|
2021-09-08 04:53:39 +02:00
|
|
|
|
.usize { 'usize' }
|
2021-01-11 22:58:15 +01:00
|
|
|
|
.int_literal { 'int_literal' }
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.f32 { 'f32' }
|
|
|
|
|
.f64 { 'f64' }
|
2021-01-11 22:58:15 +01:00
|
|
|
|
.float_literal { 'float_literal' }
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.string { 'string' }
|
|
|
|
|
.char { 'char' }
|
|
|
|
|
.bool { 'bool' }
|
|
|
|
|
.none_ { 'none' }
|
|
|
|
|
.array { 'array' }
|
|
|
|
|
.array_fixed { 'array_fixed' }
|
|
|
|
|
.map { 'map' }
|
2020-08-14 21:18:42 +02:00
|
|
|
|
.chan { 'chan' }
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.multi_return { 'multi_return' }
|
2020-11-25 12:09:40 +01:00
|
|
|
|
.sum_type { 'sum_type' }
|
2020-04-22 20:20:49 +02:00
|
|
|
|
.alias { 'alias' }
|
|
|
|
|
.enum_ { 'enum' }
|
2020-05-03 18:08:45 +02:00
|
|
|
|
.any { 'any' }
|
2020-07-04 19:58:10 +02:00
|
|
|
|
.function { 'function' }
|
|
|
|
|
.interface_ { 'interface' }
|
2021-08-04 02:37:27 +02:00
|
|
|
|
.generic_inst { 'generic_inst' }
|
2020-08-25 18:15:19 +02:00
|
|
|
|
.rune { 'rune' }
|
2020-10-01 01:07:36 +02:00
|
|
|
|
.aggregate { 'aggregate' }
|
2021-02-22 14:08:52 +01:00
|
|
|
|
.thread { 'thread' }
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
return k_str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (kinds []Kind) str() string {
|
2020-04-22 20:20:49 +02:00
|
|
|
|
mut kinds_str := ''
|
2020-03-13 01:43:30 +01:00
|
|
|
|
for i, k in kinds {
|
|
|
|
|
kinds_str += k.str()
|
|
|
|
|
if i < kinds.len - 1 {
|
|
|
|
|
kinds_str += '_'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return kinds_str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Struct {
|
2021-01-08 04:49:13 +01:00
|
|
|
|
pub:
|
2021-01-12 04:38:43 +01:00
|
|
|
|
attrs []Attr
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub mut:
|
2021-04-10 04:00:53 +02:00
|
|
|
|
embeds []Type
|
|
|
|
|
fields []StructField
|
|
|
|
|
is_typedef bool // C. [typedef]
|
|
|
|
|
is_union bool
|
|
|
|
|
is_heap bool
|
2021-04-23 14:17:57 +02:00
|
|
|
|
is_generic bool
|
2021-04-10 04:00:53 +02:00
|
|
|
|
generic_types []Type
|
|
|
|
|
concrete_types []Type
|
|
|
|
|
parent_type Type
|
2020-06-29 20:09:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-30 01:22:15 +02:00
|
|
|
|
// instantiation of a generic struct
|
2021-08-04 02:37:27 +02:00
|
|
|
|
pub struct GenericInst {
|
2020-06-29 20:09:09 +02:00
|
|
|
|
pub mut:
|
2021-04-22 17:21:01 +02:00
|
|
|
|
parent_idx int // idx of the base generic struct
|
|
|
|
|
concrete_types []Type // concrete types, e.g. <int, string>
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:20:49 +02:00
|
|
|
|
pub struct Interface {
|
2020-05-09 15:16:48 +02:00
|
|
|
|
pub mut:
|
2021-05-11 08:30:01 +02:00
|
|
|
|
types []Type // all types that implement this interface
|
2021-04-02 00:57:09 +02:00
|
|
|
|
fields []StructField
|
2021-01-26 11:56:17 +01:00
|
|
|
|
methods []Fn
|
2022-02-15 10:17:39 +01:00
|
|
|
|
embeds []Type
|
2021-08-17 20:00:27 +02:00
|
|
|
|
// `I1 is I2` conversions
|
|
|
|
|
conversions map[int][]Type
|
2021-07-15 07:29:13 +02:00
|
|
|
|
// generic interface support
|
|
|
|
|
is_generic bool
|
|
|
|
|
generic_types []Type
|
|
|
|
|
concrete_types []Type
|
|
|
|
|
parent_type Type
|
2020-04-22 20:20:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub struct Enum {
|
2020-04-08 18:55:10 +02:00
|
|
|
|
pub:
|
2020-07-27 12:15:29 +02:00
|
|
|
|
vals []string
|
|
|
|
|
is_flag bool
|
2020-07-10 16:43:02 +02:00
|
|
|
|
is_multi_allowed bool
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Alias {
|
|
|
|
|
pub:
|
2020-06-24 22:12:33 +02:00
|
|
|
|
parent_type Type
|
2020-07-27 12:15:29 +02:00
|
|
|
|
language Language
|
2020-11-03 14:13:35 +01:00
|
|
|
|
is_import bool
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-01 01:07:36 +02:00
|
|
|
|
pub struct Aggregate {
|
|
|
|
|
mut:
|
2021-04-02 00:57:09 +02:00
|
|
|
|
fields []StructField // used for faster lookup inside the module
|
2020-10-01 01:07:36 +02:00
|
|
|
|
pub:
|
2021-01-12 04:38:43 +01:00
|
|
|
|
types []Type
|
2020-10-01 01:07:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub struct Array {
|
|
|
|
|
pub:
|
2021-01-12 04:38:43 +01:00
|
|
|
|
nr_dims int
|
2020-05-09 15:16:48 +02:00
|
|
|
|
pub mut:
|
2020-03-13 01:43:30 +01:00
|
|
|
|
elem_type Type
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct ArrayFixed {
|
|
|
|
|
pub:
|
2021-06-13 22:53:38 +02:00
|
|
|
|
size int
|
|
|
|
|
size_expr Expr // used by fmt for e.g. ´[my_const]byte´
|
2020-05-09 15:16:48 +02:00
|
|
|
|
pub mut:
|
2020-03-13 01:43:30 +01:00
|
|
|
|
elem_type Type
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-14 21:18:42 +02:00
|
|
|
|
pub struct Chan {
|
|
|
|
|
pub mut:
|
2020-08-25 18:15:19 +02:00
|
|
|
|
elem_type Type
|
2020-09-06 21:24:41 +02:00
|
|
|
|
is_mut bool
|
2020-08-14 21:18:42 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-22 14:08:52 +01:00
|
|
|
|
pub struct Thread {
|
2021-01-15 13:45:26 +01:00
|
|
|
|
pub mut:
|
|
|
|
|
return_type Type
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-13 01:43:30 +01:00
|
|
|
|
pub struct Map {
|
|
|
|
|
pub mut:
|
|
|
|
|
key_type Type
|
|
|
|
|
value_type Type
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-25 12:09:40 +01:00
|
|
|
|
pub struct SumType {
|
2021-03-09 18:16:18 +01:00
|
|
|
|
pub mut:
|
2021-04-02 00:57:09 +02:00
|
|
|
|
fields []StructField
|
2021-03-09 18:16:18 +01:00
|
|
|
|
found_fields bool
|
2021-12-25 16:26:40 +01:00
|
|
|
|
is_anon bool
|
2021-07-15 07:29:13 +02:00
|
|
|
|
// generic sumtype support
|
|
|
|
|
is_generic bool
|
2022-01-21 13:46:55 +01:00
|
|
|
|
variants []Type
|
2021-07-15 07:29:13 +02:00
|
|
|
|
generic_types []Type
|
|
|
|
|
concrete_types []Type
|
|
|
|
|
parent_type Type
|
2020-11-11 09:18:15 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-03 23:11:09 +01:00
|
|
|
|
// human readable type name
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (t &Table) type_to_str(typ Type) string {
|
|
|
|
|
return t.type_to_str_using_aliases(typ, map[string]string{})
|
2020-12-07 18:13:03 +01:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-03 23:11:09 +01:00
|
|
|
|
// type name in code (for builtin)
|
2021-01-25 10:26:20 +01:00
|
|
|
|
pub fn (mytable &Table) type_to_code(t Type) string {
|
2021-01-03 23:11:09 +01:00
|
|
|
|
match t {
|
2021-12-19 17:25:18 +01:00
|
|
|
|
ast.int_literal_type, ast.float_literal_type { return mytable.sym(t).kind.str() }
|
2021-01-25 10:26:20 +01:00
|
|
|
|
else { return mytable.type_to_str_using_aliases(t, map[string]string{}) }
|
2021-01-03 23:11:09 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-07 18:13:03 +01:00
|
|
|
|
// import_aliases is a map of imported symbol aliases 'module.Type' => 'Type'
|
2021-04-04 16:43:32 +02:00
|
|
|
|
pub fn (t &Table) type_to_str_using_aliases(typ Type, import_aliases map[string]string) string {
|
2021-12-19 17:25:18 +01:00
|
|
|
|
sym := t.sym(typ)
|
2020-12-06 04:55:08 +01:00
|
|
|
|
mut res := sym.name
|
2021-07-12 09:40:11 +02:00
|
|
|
|
// Note, that the duplication of code in some of the match branches here
|
|
|
|
|
// is VERY deliberate. DO NOT be tempted to use `else {}` instead, because
|
|
|
|
|
// that strongly reduces the usefullness of the exhaustive checking that
|
|
|
|
|
// match does.
|
|
|
|
|
// Using else{} here led to subtle bugs in vfmt discovered *months*
|
|
|
|
|
// after the original code was written.
|
|
|
|
|
// It is important that each case here is handled *explicitly* and
|
|
|
|
|
// *clearly*, and that when a new kind is added, it should also be handled
|
|
|
|
|
// explicitly.
|
2020-10-12 17:41:42 +02:00
|
|
|
|
match sym.kind {
|
2021-09-29 12:53:46 +02:00
|
|
|
|
.int_literal, .float_literal {}
|
2021-09-08 04:53:39 +02:00
|
|
|
|
.i8, .i16, .int, .i64, .isize, .byte, .u8, .u16, .u32, .u64, .usize, .f32, .f64, .char,
|
2021-09-29 12:53:46 +02:00
|
|
|
|
.rune, .string, .bool, .none_, .voidptr, .byteptr, .charptr {
|
2020-10-12 17:41:42 +02:00
|
|
|
|
// primitive types
|
2021-09-08 04:53:39 +02:00
|
|
|
|
res = sym.kind.str()
|
2020-05-18 15:37:06 +02:00
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
.array {
|
2021-04-04 16:43:32 +02:00
|
|
|
|
if typ == ast.array_type {
|
2020-10-13 17:11:28 +02:00
|
|
|
|
return 'array'
|
|
|
|
|
}
|
2021-04-04 16:43:32 +02:00
|
|
|
|
if typ.has_flag(.variadic) {
|
|
|
|
|
res = t.type_to_str_using_aliases(t.value_type(typ), import_aliases)
|
2020-12-29 16:14:08 +01:00
|
|
|
|
} else {
|
2021-06-11 11:00:18 +02:00
|
|
|
|
if sym.info is Array {
|
|
|
|
|
elem_str := t.type_to_str_using_aliases(sym.info.elem_type, import_aliases)
|
|
|
|
|
res = '[]$elem_str'
|
|
|
|
|
} else {
|
|
|
|
|
res = 'array'
|
|
|
|
|
}
|
2020-12-29 16:14:08 +01:00
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
.array_fixed {
|
|
|
|
|
info := sym.info as ArrayFixed
|
2021-04-04 16:43:32 +02:00
|
|
|
|
elem_str := t.type_to_str_using_aliases(info.elem_type, import_aliases)
|
2021-06-13 22:53:38 +02:00
|
|
|
|
if info.size_expr is EmptyExpr {
|
|
|
|
|
res = '[$info.size]$elem_str'
|
|
|
|
|
} else {
|
|
|
|
|
res = '[$info.size_expr]$elem_str'
|
2021-04-28 21:11:15 +02:00
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
}
|
|
|
|
|
.chan {
|
|
|
|
|
// TODO currently the `chan` struct in builtin is not considered a struct but a chan
|
|
|
|
|
if sym.mod != 'builtin' && sym.name != 'chan' {
|
|
|
|
|
info := sym.info as Chan
|
|
|
|
|
mut elem_type := info.elem_type
|
|
|
|
|
mut mut_str := ''
|
|
|
|
|
if info.is_mut {
|
|
|
|
|
mut_str = 'mut '
|
|
|
|
|
elem_type = elem_type.set_nr_muls(elem_type.nr_muls() - 1)
|
|
|
|
|
}
|
2021-04-04 16:43:32 +02:00
|
|
|
|
elem_str := t.type_to_str_using_aliases(elem_type, import_aliases)
|
2020-10-12 17:41:42 +02:00
|
|
|
|
res = 'chan $mut_str$elem_str'
|
2020-09-08 00:36:05 +02:00
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
}
|
|
|
|
|
.function {
|
2021-01-02 16:36:31 +01:00
|
|
|
|
info := sym.info as FnType
|
2021-04-04 16:43:32 +02:00
|
|
|
|
if !t.is_fmt {
|
|
|
|
|
res = t.fn_signature(info.func, type_only: true)
|
2020-12-09 14:18:38 +01:00
|
|
|
|
} else {
|
2021-01-02 16:36:31 +01:00
|
|
|
|
if res.starts_with('fn (') {
|
|
|
|
|
// fn foo ()
|
2021-05-23 04:54:39 +02:00
|
|
|
|
has_names := info.func.params.any(it.name.len > 0)
|
|
|
|
|
res = t.fn_signature_using_aliases(info.func, import_aliases,
|
|
|
|
|
type_only: !has_names
|
|
|
|
|
)
|
2021-01-02 16:36:31 +01:00
|
|
|
|
} else {
|
|
|
|
|
// FnFoo
|
2021-04-04 16:43:32 +02:00
|
|
|
|
res = t.shorten_user_defined_typenames(res, import_aliases)
|
2021-01-02 16:36:31 +01:00
|
|
|
|
}
|
2020-11-05 19:15:26 +01:00
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
}
|
|
|
|
|
.map {
|
2021-04-04 16:43:32 +02:00
|
|
|
|
if int(typ) == ast.map_type_idx {
|
2020-10-13 17:11:28 +02:00
|
|
|
|
return 'map'
|
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
info := sym.info as Map
|
2021-04-04 16:43:32 +02:00
|
|
|
|
key_str := t.type_to_str_using_aliases(info.key_type, import_aliases)
|
|
|
|
|
val_str := t.type_to_str_using_aliases(info.value_type, import_aliases)
|
2020-10-12 17:41:42 +02:00
|
|
|
|
res = 'map[$key_str]$val_str'
|
|
|
|
|
}
|
|
|
|
|
.multi_return {
|
|
|
|
|
res = '('
|
|
|
|
|
info := sym.info as MultiReturn
|
2021-04-04 16:43:32 +02:00
|
|
|
|
for i, typ2 in info.types {
|
2020-10-12 17:41:42 +02:00
|
|
|
|
if i > 0 {
|
|
|
|
|
res += ', '
|
|
|
|
|
}
|
2021-04-04 16:43:32 +02:00
|
|
|
|
res += t.type_to_str_using_aliases(typ2, import_aliases)
|
2020-09-08 00:36:05 +02:00
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
res += ')'
|
2020-04-05 03:37:38 +02:00
|
|
|
|
}
|
2021-07-15 07:29:13 +02:00
|
|
|
|
.struct_, .interface_, .sum_type {
|
2021-04-08 07:24:34 +02:00
|
|
|
|
if typ.has_flag(.generic) {
|
2021-07-15 07:29:13 +02:00
|
|
|
|
match sym.info {
|
|
|
|
|
Struct, Interface, SumType {
|
|
|
|
|
res += '<'
|
|
|
|
|
for i, gtyp in sym.info.generic_types {
|
2021-12-19 17:25:18 +01:00
|
|
|
|
res += t.sym(gtyp).name
|
2021-07-15 07:29:13 +02:00
|
|
|
|
if i != sym.info.generic_types.len - 1 {
|
|
|
|
|
res += ', '
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
res += '>'
|
2021-04-08 07:24:34 +02:00
|
|
|
|
}
|
2021-07-15 07:29:13 +02:00
|
|
|
|
else {}
|
2021-04-08 07:24:34 +02:00
|
|
|
|
}
|
2021-12-25 16:26:40 +01:00
|
|
|
|
} else if sym.info is SumType && (sym.info as SumType).is_anon {
|
|
|
|
|
variant_names := sym.info.variants.map(t.shorten_user_defined_typenames(t.sym(it).name,
|
|
|
|
|
import_aliases))
|
|
|
|
|
res = '${variant_names.join(' | ')}'
|
2021-04-08 07:24:34 +02:00
|
|
|
|
} else {
|
|
|
|
|
res = t.shorten_user_defined_typenames(res, import_aliases)
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-04 02:37:27 +02:00
|
|
|
|
.generic_inst {
|
|
|
|
|
info := sym.info as GenericInst
|
2021-12-08 21:33:58 +01:00
|
|
|
|
res = t.shorten_user_defined_typenames(sym.name.all_before('<'), import_aliases)
|
2021-05-19 20:25:02 +02:00
|
|
|
|
res += '<'
|
|
|
|
|
for i, ctyp in info.concrete_types {
|
2021-12-08 21:33:58 +01:00
|
|
|
|
res += t.type_to_str_using_aliases(ctyp, import_aliases)
|
2021-05-19 20:25:02 +02:00
|
|
|
|
if i != info.concrete_types.len - 1 {
|
|
|
|
|
res += ', '
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
res += '>'
|
|
|
|
|
}
|
2020-10-12 17:41:42 +02:00
|
|
|
|
.void {
|
2021-04-04 16:43:32 +02:00
|
|
|
|
if typ.has_flag(.optional) {
|
2020-10-12 17:41:42 +02:00
|
|
|
|
return '?'
|
|
|
|
|
}
|
|
|
|
|
return 'void'
|
2020-06-10 16:12:55 +02:00
|
|
|
|
}
|
2021-07-12 09:40:11 +02:00
|
|
|
|
.thread {
|
2021-07-12 09:55:30 +02:00
|
|
|
|
rtype := sym.thread_info().return_type
|
|
|
|
|
if rtype != 1 {
|
|
|
|
|
res = 'thread ' + t.type_to_str_using_aliases(rtype, import_aliases)
|
|
|
|
|
}
|
2021-07-12 09:40:11 +02:00
|
|
|
|
}
|
2021-09-21 01:12:38 +02:00
|
|
|
|
.alias, .any, .aggregate, .placeholder, .enum_ {
|
2021-04-04 16:43:32 +02:00
|
|
|
|
res = t.shorten_user_defined_typenames(res, import_aliases)
|
2020-08-28 00:54:16 +02:00
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
}
|
2021-04-04 16:43:32 +02:00
|
|
|
|
mut nr_muls := typ.nr_muls()
|
|
|
|
|
if typ.has_flag(.shared_f) {
|
2021-02-06 21:25:06 +01:00
|
|
|
|
nr_muls--
|
|
|
|
|
res = 'shared ' + res
|
|
|
|
|
}
|
2021-08-10 20:14:37 +02:00
|
|
|
|
if nr_muls > 0 && !typ.has_flag(.variadic) {
|
2020-10-12 17:41:42 +02:00
|
|
|
|
res = strings.repeat(`&`, nr_muls) + res
|
|
|
|
|
}
|
2021-04-04 16:43:32 +02:00
|
|
|
|
if typ.has_flag(.optional) {
|
2021-12-25 16:26:40 +01:00
|
|
|
|
res = '?$res'
|
2020-04-22 20:12:58 +02:00
|
|
|
|
}
|
2020-03-13 01:43:30 +01:00
|
|
|
|
return res
|
|
|
|
|
}
|
2020-04-27 22:53:26 +02:00
|
|
|
|
|
2020-12-09 14:18:38 +01:00
|
|
|
|
fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases map[string]string) string {
|
|
|
|
|
mut res := originalname
|
2021-01-20 06:04:59 +01:00
|
|
|
|
if t.cmod_prefix.len > 0 && res.starts_with(t.cmod_prefix) {
|
|
|
|
|
// cur_mod.Type => Type
|
2020-12-09 14:18:38 +01:00
|
|
|
|
res = res.replace_once(t.cmod_prefix, '')
|
2021-01-20 06:04:59 +01:00
|
|
|
|
} else if res in import_aliases {
|
2020-12-09 14:18:38 +01:00
|
|
|
|
res = import_aliases[res]
|
2021-01-20 06:04:59 +01:00
|
|
|
|
} else {
|
|
|
|
|
// types defined by the user
|
|
|
|
|
// mod.submod.submod2.Type => submod2.Type
|
2021-03-27 11:33:41 +01:00
|
|
|
|
mut parts := res.split('.')
|
|
|
|
|
if parts.len > 1 {
|
|
|
|
|
ind := parts.len - 2
|
2021-05-21 19:33:04 +02:00
|
|
|
|
if t.is_fmt {
|
|
|
|
|
// Rejoin the module parts for correct usage of aliases
|
|
|
|
|
parts[ind] = parts[..ind + 1].join('.')
|
|
|
|
|
}
|
2021-03-27 11:33:41 +01:00
|
|
|
|
if parts[ind] in import_aliases {
|
|
|
|
|
parts[ind] = import_aliases[parts[ind]]
|
|
|
|
|
}
|
2021-05-21 19:33:04 +02:00
|
|
|
|
|
2021-03-27 11:33:41 +01:00
|
|
|
|
res = parts[ind..].join('.')
|
|
|
|
|
} else {
|
|
|
|
|
res = parts[0]
|
|
|
|
|
}
|
2020-12-09 14:18:38 +01:00
|
|
|
|
}
|
|
|
|
|
return res
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-05 06:34:56 +01:00
|
|
|
|
pub struct FnSignatureOpts {
|
|
|
|
|
skip_receiver bool
|
|
|
|
|
type_only bool
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (t &Table) fn_signature(func &Fn, opts FnSignatureOpts) string {
|
2021-05-21 19:33:04 +02:00
|
|
|
|
return t.fn_signature_using_aliases(func, map[string]string{}, opts)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (t &Table) fn_signature_using_aliases(func &Fn, import_aliases map[string]string, opts FnSignatureOpts) string {
|
2020-05-06 11:29:37 +02:00
|
|
|
|
mut sb := strings.new_builder(20)
|
2020-11-05 06:34:56 +01:00
|
|
|
|
if !opts.skip_receiver {
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string('fn ')
|
2020-11-05 06:34:56 +01:00
|
|
|
|
// TODO write receiver
|
|
|
|
|
}
|
|
|
|
|
if !opts.type_only {
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string('$func.name')
|
2020-11-05 06:34:56 +01:00
|
|
|
|
}
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string('(')
|
2020-11-05 06:34:56 +01:00
|
|
|
|
start := int(opts.skip_receiver)
|
|
|
|
|
for i in start .. func.params.len {
|
|
|
|
|
if i != start {
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string(', ')
|
2020-11-05 06:34:56 +01:00
|
|
|
|
}
|
2020-09-27 03:32:56 +02:00
|
|
|
|
param := func.params[i]
|
2020-11-05 06:34:56 +01:00
|
|
|
|
mut typ := param.typ
|
|
|
|
|
if param.is_mut {
|
2021-11-01 00:26:15 +01:00
|
|
|
|
if param.typ.is_ptr() {
|
|
|
|
|
typ = typ.deref()
|
|
|
|
|
}
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string('mut ')
|
2020-05-06 11:29:37 +02:00
|
|
|
|
}
|
2020-11-05 06:34:56 +01:00
|
|
|
|
if !opts.type_only {
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string('$param.name ')
|
2020-05-06 11:29:37 +02:00
|
|
|
|
}
|
2021-05-21 19:33:04 +02:00
|
|
|
|
styp := t.type_to_str_using_aliases(typ, import_aliases)
|
2021-05-04 11:33:24 +02:00
|
|
|
|
if i == func.params.len - 1 && func.is_variadic {
|
|
|
|
|
sb.write_string('...$styp')
|
|
|
|
|
} else {
|
|
|
|
|
sb.write_string('$styp')
|
|
|
|
|
}
|
2020-05-06 11:29:37 +02:00
|
|
|
|
}
|
2021-02-22 12:18:11 +01:00
|
|
|
|
sb.write_string(')')
|
2021-04-02 00:57:09 +02:00
|
|
|
|
if func.return_type != ast.void_type {
|
2021-05-21 19:33:04 +02:00
|
|
|
|
sb.write_string(' ${t.type_to_str_using_aliases(func.return_type, import_aliases)}')
|
2020-05-06 11:29:37 +02:00
|
|
|
|
}
|
|
|
|
|
return sb.str()
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-23 19:12:49 +01:00
|
|
|
|
pub fn (t &TypeSymbol) embed_name() string {
|
|
|
|
|
// main.Abc<int> => Abc<int>
|
|
|
|
|
mut embed_name := t.name.split('.').last()
|
|
|
|
|
// remove generic part from name
|
|
|
|
|
// Abc<int> => Abc
|
2021-03-23 09:38:56 +01:00
|
|
|
|
if embed_name.contains('<') {
|
2020-12-23 19:12:49 +01:00
|
|
|
|
embed_name = embed_name.split('<')[0]
|
|
|
|
|
}
|
|
|
|
|
return embed_name
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 00:14:59 +02:00
|
|
|
|
pub fn (t &TypeSymbol) has_method(name string) bool {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut method in unsafe { t.methods } {
|
2021-11-07 12:30:40 +01:00
|
|
|
|
if method.name == name {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
2020-05-04 00:14:59 +02:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 18:03:17 +02:00
|
|
|
|
pub fn (t &TypeSymbol) has_method_with_generic_parent(name string) bool {
|
|
|
|
|
t.find_method_with_generic_parent(name) or { return false }
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 00:14:59 +02:00
|
|
|
|
pub fn (t &TypeSymbol) find_method(name string) ?Fn {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut method in unsafe { t.methods } {
|
2020-05-04 00:14:59 +02:00
|
|
|
|
if method.name == name {
|
|
|
|
|
return method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-15 07:29:13 +02:00
|
|
|
|
pub fn (t &TypeSymbol) find_method_with_generic_parent(name string) ?Fn {
|
|
|
|
|
if m := t.find_method(name) {
|
|
|
|
|
return m
|
|
|
|
|
}
|
|
|
|
|
mut table := global_table
|
|
|
|
|
match t.info {
|
|
|
|
|
Struct, Interface, SumType {
|
|
|
|
|
if t.info.parent_type.has_flag(.generic) {
|
2021-12-19 17:25:18 +01:00
|
|
|
|
parent_sym := table.sym(t.info.parent_type)
|
2021-07-15 07:29:13 +02:00
|
|
|
|
if x := parent_sym.find_method(name) {
|
|
|
|
|
match parent_sym.info {
|
|
|
|
|
Struct, Interface, SumType {
|
|
|
|
|
mut method := x
|
2021-12-19 17:25:18 +01:00
|
|
|
|
generic_names := parent_sym.info.generic_types.map(table.sym(it).name)
|
2022-02-24 09:48:52 +01:00
|
|
|
|
return_sym := table.sym(method.return_type)
|
2022-02-26 00:11:56 +01:00
|
|
|
|
if return_sym.kind in [.struct_, .interface_, .sum_type] {
|
2022-02-24 09:48:52 +01:00
|
|
|
|
method.return_type = table.unwrap_generic_type(method.return_type,
|
|
|
|
|
generic_names, t.info.concrete_types)
|
|
|
|
|
} else {
|
|
|
|
|
if rt := table.resolve_generic_to_concrete(method.return_type,
|
|
|
|
|
generic_names, t.info.concrete_types)
|
|
|
|
|
{
|
|
|
|
|
method.return_type = rt
|
|
|
|
|
}
|
2021-07-15 07:29:13 +02:00
|
|
|
|
}
|
|
|
|
|
method.params = method.params.clone()
|
|
|
|
|
for mut param in method.params {
|
|
|
|
|
if pt := table.resolve_generic_to_concrete(param.typ,
|
|
|
|
|
generic_names, t.info.concrete_types)
|
|
|
|
|
{
|
|
|
|
|
param.typ = pt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
method.generic_names.clear()
|
|
|
|
|
return method
|
|
|
|
|
}
|
|
|
|
|
else {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-20 20:28:11 +01:00
|
|
|
|
// is_js_compatible returns true if type can be converted to JS type and from JS type back to V type
|
|
|
|
|
pub fn (t &TypeSymbol) is_js_compatible() bool {
|
|
|
|
|
mut table := global_table
|
|
|
|
|
if t.kind == .void {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
if t.kind == .function {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
if t.language == .js || t.name.starts_with('JS.') {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
match t.info {
|
|
|
|
|
SumType {
|
|
|
|
|
for variant in t.info.variants {
|
2021-12-19 17:25:18 +01:00
|
|
|
|
sym := table.final_sym(variant)
|
2021-11-20 20:28:11 +01:00
|
|
|
|
if !sym.is_js_compatible() {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-08 11:48:01 +02:00
|
|
|
|
pub fn (t &TypeSymbol) str_method_info() (bool, bool, int) {
|
|
|
|
|
mut has_str_method := false
|
|
|
|
|
mut expects_ptr := false
|
|
|
|
|
mut nr_args := 0
|
2021-10-28 18:03:17 +02:00
|
|
|
|
if sym_str_method := t.find_method_with_generic_parent('str') {
|
2020-05-08 11:48:01 +02:00
|
|
|
|
has_str_method = true
|
2020-09-27 03:32:56 +02:00
|
|
|
|
nr_args = sym_str_method.params.len
|
2020-05-08 11:48:01 +02:00
|
|
|
|
if nr_args > 0 {
|
2020-09-27 03:32:56 +02:00
|
|
|
|
expects_ptr = sym_str_method.params[0].typ.is_ptr()
|
2020-05-08 11:48:01 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return has_str_method, expects_ptr, nr_args
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (t &TypeSymbol) find_field(name string) ?StructField {
|
2021-01-23 07:57:17 +01:00
|
|
|
|
match t.info {
|
|
|
|
|
Aggregate { return t.info.find_field(name) }
|
|
|
|
|
Struct { return t.info.find_field(name) }
|
|
|
|
|
Interface { return t.info.find_field(name) }
|
2021-03-09 18:16:18 +01:00
|
|
|
|
SumType { return t.info.find_field(name) }
|
2021-01-23 07:57:17 +01:00
|
|
|
|
else { return none }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 00:57:09 +02:00
|
|
|
|
fn (a &Aggregate) find_field(name string) ?StructField {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut field in unsafe { a.fields } {
|
2020-10-01 01:07:36 +02:00
|
|
|
|
if field.name == name {
|
|
|
|
|
return field
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (i &Interface) find_field(name string) ?StructField {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut field in unsafe { i.fields } {
|
2021-01-23 07:57:17 +01:00
|
|
|
|
if field.name == name {
|
|
|
|
|
return field
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-03 05:02:10 +01:00
|
|
|
|
pub fn (i &Interface) find_method(name string) ?Fn {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut method in unsafe { i.methods } {
|
2021-03-03 05:02:10 +01:00
|
|
|
|
if method.name == name {
|
|
|
|
|
return method
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn (i &Interface) has_method(name string) bool {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut method in unsafe { i.methods } {
|
2021-11-07 12:30:40 +01:00
|
|
|
|
if method.name == name {
|
|
|
|
|
return true
|
|
|
|
|
}
|
2021-03-03 05:02:10 +01:00
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (s Struct) find_field(name string) ?StructField {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut field in unsafe { s.fields } {
|
2020-04-27 22:53:26 +02:00
|
|
|
|
if field.name == name {
|
|
|
|
|
return field
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (s Struct) get_field(name string) StructField {
|
2020-04-27 22:53:26 +02:00
|
|
|
|
if field := s.find_field(name) {
|
|
|
|
|
return field
|
|
|
|
|
}
|
|
|
|
|
panic('unknown field `$name`')
|
|
|
|
|
}
|
2021-01-26 11:56:17 +01:00
|
|
|
|
|
2021-04-02 00:57:09 +02:00
|
|
|
|
pub fn (s &SumType) find_field(name string) ?StructField {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut field in unsafe { s.fields } {
|
2021-03-09 18:16:18 +01:00
|
|
|
|
if field.name == name {
|
|
|
|
|
return field
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return none
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-26 11:56:17 +01:00
|
|
|
|
pub fn (i Interface) defines_method(name string) bool {
|
2021-11-07 17:05:20 +01:00
|
|
|
|
for mut method in unsafe { i.methods } {
|
2021-01-26 11:56:17 +01:00
|
|
|
|
if method.name == name {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|