all: fix casting of `string(MyString('abc'))` and `byte(MyByte(123))`; improve TypeSymbol handling (#12617)
parent
519ca90cfa
commit
47aa2b1f93
|
@ -92,7 +92,7 @@ pub fn (mut b Builder) cut_to(pos int) string {
|
||||||
|
|
||||||
pub fn (mut b Builder) write_runes(runes []rune) {
|
pub fn (mut b Builder) write_runes(runes []rune) {
|
||||||
for r in runes {
|
for r in runes {
|
||||||
res := string(r)
|
res := r.str()
|
||||||
#res.str = String.fromCharCode(r.val)
|
#res.str = String.fromCharCode(r.val)
|
||||||
b << res.bytes()
|
b << res.bytes()
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import v.util
|
||||||
[heap]
|
[heap]
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
pub mut:
|
pub mut:
|
||||||
type_symbols []TypeSymbol
|
type_symbols []&TypeSymbol
|
||||||
type_idxs map[string]int
|
type_idxs map[string]int
|
||||||
fns map[string]Fn
|
fns map[string]Fn
|
||||||
iface_types map[string][]Type
|
iface_types map[string][]Type
|
||||||
|
@ -42,8 +42,11 @@ pub mut:
|
||||||
// used by vls to avoid leaks
|
// used by vls to avoid leaks
|
||||||
// TODO remove manual memory management
|
// TODO remove manual memory management
|
||||||
[unsafe]
|
[unsafe]
|
||||||
pub fn (t &Table) free() {
|
pub fn (mut t Table) free() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
for s in t.type_symbols {
|
||||||
|
s.free()
|
||||||
|
}
|
||||||
t.type_symbols.free()
|
t.type_symbols.free()
|
||||||
t.type_idxs.free()
|
t.type_idxs.free()
|
||||||
t.fns.free()
|
t.fns.free()
|
||||||
|
@ -169,7 +172,6 @@ fn (p []Param) equals(o []Param) bool {
|
||||||
|
|
||||||
pub fn new_table() &Table {
|
pub fn new_table() &Table {
|
||||||
mut t := &Table{
|
mut t := &Table{
|
||||||
type_symbols: []TypeSymbol{cap: 64000}
|
|
||||||
global_scope: &Scope{
|
global_scope: &Scope{
|
||||||
parent: 0
|
parent: 0
|
||||||
}
|
}
|
||||||
|
@ -348,7 +350,7 @@ pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
|
||||||
if ts.parent_idx == 0 {
|
if ts.parent_idx == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ts = unsafe { &t.type_symbols[ts.parent_idx] }
|
ts = t.type_symbols[ts.parent_idx]
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
@ -490,7 +492,7 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
|
||||||
if ts.parent_idx == 0 {
|
if ts.parent_idx == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
ts = unsafe { &t.type_symbols[ts.parent_idx] }
|
ts = t.type_symbols[ts.parent_idx]
|
||||||
}
|
}
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
@ -625,7 +627,7 @@ pub fn (t &Table) find_type_idx(name string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) find_type(name string) ?TypeSymbol {
|
pub fn (t &Table) find_type(name string) ?&TypeSymbol {
|
||||||
idx := t.type_idxs[name]
|
idx := t.type_idxs[name]
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
return t.type_symbols[idx]
|
return t.type_symbols[idx]
|
||||||
|
@ -634,6 +636,7 @@ pub fn (t &Table) find_type(name string) ?TypeSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const invalid_type_symbol = &TypeSymbol{
|
pub const invalid_type_symbol = &TypeSymbol{
|
||||||
|
idx: -1
|
||||||
parent_idx: -1
|
parent_idx: -1
|
||||||
language: .v
|
language: .v
|
||||||
mod: 'builtin'
|
mod: 'builtin'
|
||||||
|
@ -643,10 +646,14 @@ pub const invalid_type_symbol = &TypeSymbol{
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
pub fn (t &Table) get_type_symbol_by_idx(idx int) &TypeSymbol {
|
||||||
|
return t.type_symbols[idx]
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
||||||
idx := typ.idx()
|
idx := typ.idx()
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
return unsafe { &t.type_symbols[idx] }
|
return t.type_symbols[idx]
|
||||||
}
|
}
|
||||||
// this should never happen
|
// this should never happen
|
||||||
t.panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`.
|
t.panic('get_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`.
|
||||||
|
@ -659,11 +666,11 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
||||||
pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol {
|
pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol {
|
||||||
mut idx := typ.idx()
|
mut idx := typ.idx()
|
||||||
if idx > 0 {
|
if idx > 0 {
|
||||||
current_type := t.type_symbols[idx]
|
current_symbol := t.type_symbols[idx]
|
||||||
if current_type.kind == .alias {
|
if current_symbol.kind == .alias {
|
||||||
idx = (current_type.info as Alias).parent_type.idx()
|
idx = (current_symbol.info as Alias).parent_type.idx()
|
||||||
}
|
}
|
||||||
return unsafe { &t.type_symbols[idx] }
|
return t.type_symbols[idx]
|
||||||
}
|
}
|
||||||
// this should never happen
|
// this should never happen
|
||||||
t.panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`.')
|
t.panic('get_final_type_symbol: invalid type (typ=$typ idx=$idx). Compiler bug. This should never happen. Please report the bug using `v bug file.v`.')
|
||||||
|
@ -672,8 +679,8 @@ pub fn (t &Table) get_final_type_symbol(typ Type) &TypeSymbol {
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) get_type_name(typ Type) string {
|
pub fn (t &Table) get_type_name(typ Type) string {
|
||||||
typ_sym := t.get_type_symbol(typ)
|
sym := t.get_type_symbol(typ)
|
||||||
return typ_sym.name
|
return sym.name
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -688,38 +695,36 @@ pub fn (t &Table) unalias_num_type(typ Type) Type {
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut t Table) check_for_already_registered_symbol(typ TypeSymbol, existing_idx int) int {
|
fn (mut t Table) rewrite_already_registered_symbol(typ TypeSymbol, existing_idx int) int {
|
||||||
ex_type := t.type_symbols[existing_idx]
|
existing_symbol := t.type_symbols[existing_idx]
|
||||||
match ex_type.kind {
|
if existing_symbol.kind == .placeholder {
|
||||||
.placeholder {
|
// override placeholder
|
||||||
// override placeholder
|
t.type_symbols[existing_idx] = &TypeSymbol{
|
||||||
t.type_symbols[existing_idx] = TypeSymbol{
|
...typ
|
||||||
...typ
|
methods: existing_symbol.methods
|
||||||
methods: ex_type.methods
|
|
||||||
}
|
|
||||||
return existing_idx
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// builtin
|
|
||||||
// this will override the already registered builtin types
|
|
||||||
// with the actual v struct declaration in the source
|
|
||||||
if (existing_idx >= string_type_idx && existing_idx <= map_type_idx)
|
|
||||||
|| existing_idx == error_type_idx {
|
|
||||||
if existing_idx == string_type_idx {
|
|
||||||
// existing_type := t.type_symbols[existing_idx]
|
|
||||||
t.type_symbols[existing_idx] = TypeSymbol{
|
|
||||||
...typ
|
|
||||||
kind: ex_type.kind
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
t.type_symbols[existing_idx] = typ
|
|
||||||
}
|
|
||||||
return existing_idx
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
|
return existing_idx
|
||||||
}
|
}
|
||||||
return -2
|
// Override the already registered builtin types with the actual
|
||||||
|
// v struct declarations in the vlib/builtin module sources:
|
||||||
|
if (existing_idx >= string_type_idx && existing_idx <= map_type_idx)
|
||||||
|
|| existing_idx == error_type_idx {
|
||||||
|
if existing_idx == string_type_idx {
|
||||||
|
// existing_type := t.type_symbols[existing_idx]
|
||||||
|
unsafe {
|
||||||
|
*existing_symbol = &TypeSymbol{
|
||||||
|
...typ
|
||||||
|
kind: existing_symbol.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.type_symbols[existing_idx] = &TypeSymbol{
|
||||||
|
...typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -727,7 +732,7 @@ pub fn (mut t Table) register_type_symbol(sym TypeSymbol) int {
|
||||||
mut idx := -2
|
mut idx := -2
|
||||||
mut existing_idx := t.type_idxs[sym.name]
|
mut existing_idx := t.type_idxs[sym.name]
|
||||||
if existing_idx > 0 {
|
if existing_idx > 0 {
|
||||||
idx = t.check_for_already_registered_symbol(sym, existing_idx)
|
idx = t.rewrite_already_registered_symbol(sym, existing_idx)
|
||||||
if idx != -2 {
|
if idx != -2 {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
|
@ -735,14 +740,16 @@ pub fn (mut t Table) register_type_symbol(sym TypeSymbol) int {
|
||||||
if sym.mod == 'main' {
|
if sym.mod == 'main' {
|
||||||
existing_idx = t.type_idxs[sym.name.trim_prefix('main.')]
|
existing_idx = t.type_idxs[sym.name.trim_prefix('main.')]
|
||||||
if existing_idx > 0 {
|
if existing_idx > 0 {
|
||||||
idx = t.check_for_already_registered_symbol(sym, existing_idx)
|
idx = t.rewrite_already_registered_symbol(sym, existing_idx)
|
||||||
if idx != -2 {
|
if idx != -2 {
|
||||||
return idx
|
return idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
idx = t.type_symbols.len
|
idx = t.type_symbols.len
|
||||||
t.type_symbols << sym
|
t.type_symbols << &TypeSymbol{
|
||||||
|
...sym
|
||||||
|
}
|
||||||
t.type_symbols[idx].idx = idx
|
t.type_symbols[idx].idx = idx
|
||||||
t.type_idxs[sym.name] = idx
|
t.type_idxs[sym.name] = idx
|
||||||
return idx
|
return idx
|
||||||
|
@ -1088,31 +1095,31 @@ pub fn (mut t Table) add_placeholder_type(name string, language Language) 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_final_type_symbol(typ)
|
sym := t.get_final_type_symbol(typ)
|
||||||
if typ.has_flag(.variadic) {
|
if typ.has_flag(.variadic) {
|
||||||
// ...string => string
|
// ...string => string
|
||||||
// return typ.clear_flag(.variadic)
|
// return typ.clear_flag(.variadic)
|
||||||
array_info := typ_sym.info as Array
|
array_info := sym.info as Array
|
||||||
return array_info.elem_type
|
return array_info.elem_type
|
||||||
}
|
}
|
||||||
if typ_sym.kind == .array {
|
if sym.kind == .array {
|
||||||
// Check index type
|
// Check index type
|
||||||
info := typ_sym.info as Array
|
info := sym.info as Array
|
||||||
return info.elem_type
|
return info.elem_type
|
||||||
}
|
}
|
||||||
if typ_sym.kind == .array_fixed {
|
if sym.kind == .array_fixed {
|
||||||
info := typ_sym.info as ArrayFixed
|
info := sym.info as ArrayFixed
|
||||||
return info.elem_type
|
return info.elem_type
|
||||||
}
|
}
|
||||||
if typ_sym.kind == .map {
|
if sym.kind == .map {
|
||||||
info := typ_sym.info as Map
|
info := sym.info as Map
|
||||||
return info.value_type
|
return info.value_type
|
||||||
}
|
}
|
||||||
if typ_sym.kind == .string && typ.is_ptr() {
|
if sym.kind == .string && typ.is_ptr() {
|
||||||
// (&string)[i] => string
|
// (&string)[i] => string
|
||||||
return string_type
|
return string_type
|
||||||
}
|
}
|
||||||
if typ_sym.kind in [.byteptr, .string] {
|
if sym.kind in [.byteptr, .string] {
|
||||||
return byte_type
|
return byte_type
|
||||||
}
|
}
|
||||||
if typ.is_ptr() {
|
if typ.is_ptr() {
|
||||||
|
@ -1277,18 +1284,18 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool {
|
||||||
// `none` "implements" the Error interface
|
// `none` "implements" the Error interface
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
typ_sym := t.get_type_symbol(typ)
|
sym := t.get_type_symbol(typ)
|
||||||
if typ_sym.language != .v {
|
if sym.language != .v {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// generic struct don't generate cast interface fn
|
// generic struct don't generate cast interface fn
|
||||||
if typ_sym.info is Struct {
|
if sym.info is Struct {
|
||||||
if typ_sym.info.is_generic {
|
if sym.info.is_generic {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut inter_sym := t.get_type_symbol(inter_typ)
|
mut inter_sym := t.get_type_symbol(inter_typ)
|
||||||
if typ_sym.kind == .interface_ && inter_sym.kind == .interface_ {
|
if sym.kind == .interface_ && inter_sym.kind == .interface_ {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if mut inter_sym.info is Interface {
|
if mut inter_sym.info is Interface {
|
||||||
|
@ -1306,7 +1313,7 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool {
|
||||||
}
|
}
|
||||||
// verify methods
|
// verify methods
|
||||||
for imethod in inter_sym.info.methods {
|
for imethod in inter_sym.info.methods {
|
||||||
if method := typ_sym.find_method(imethod.name) {
|
if method := sym.find_method(imethod.name) {
|
||||||
msg := t.is_same_method(imethod, method)
|
msg := t.is_same_method(imethod, method)
|
||||||
if msg.len > 0 {
|
if msg.len > 0 {
|
||||||
return false
|
return false
|
||||||
|
@ -1320,13 +1327,13 @@ pub fn (t Table) does_type_implement_interface(typ Type, inter_typ Type) bool {
|
||||||
if ifield.typ == voidptr_type {
|
if ifield.typ == voidptr_type {
|
||||||
// Allow `voidptr` fields in interfaces for now. (for example
|
// Allow `voidptr` fields in interfaces for now. (for example
|
||||||
// to enable .db check in vweb)
|
// to enable .db check in vweb)
|
||||||
if t.struct_has_field(typ_sym, ifield.name) {
|
if t.struct_has_field(sym, ifield.name) {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if field := t.find_field_with_embeds(typ_sym, ifield.name) {
|
if field := t.find_field_with_embeds(sym, ifield.name) {
|
||||||
if ifield.typ != field.typ {
|
if ifield.typ != field.typ {
|
||||||
return false
|
return false
|
||||||
} else if ifield.is_mut && !(field.is_mut || field.is_global) {
|
} else if ifield.is_mut && !(field.is_mut || field.is_global) {
|
||||||
|
|
|
@ -664,7 +664,7 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||||
if node.language == .v && !c.is_builtin_mod {
|
if node.language == .v && !c.is_builtin_mod {
|
||||||
c.check_valid_pascal_case(node.name, 'struct name', node.pos)
|
c.check_valid_pascal_case(node.name, 'struct name', node.pos)
|
||||||
}
|
}
|
||||||
mut struct_sym := c.table.find_type(node.name) or { ast.TypeSymbol{} }
|
mut struct_sym := c.table.find_type(node.name) or { ast.invalid_type_symbol }
|
||||||
mut has_generic_types := false
|
mut has_generic_types := false
|
||||||
if mut struct_sym.info is ast.Struct {
|
if mut struct_sym.info is ast.Struct {
|
||||||
for embed in node.embeds {
|
for embed in node.embeds {
|
||||||
|
@ -5655,77 +5655,93 @@ pub fn (mut c Checker) expr(node ast.Expr) ast.Type {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||||
|
// Given: `Outside( Inside(xyz) )`,
|
||||||
|
// node.expr_type: `Inside`
|
||||||
|
// node.typ: `Outside`
|
||||||
node.expr_type = c.expr(node.expr) // type to be casted
|
node.expr_type = c.expr(node.expr) // type to be casted
|
||||||
from_type_sym := c.table.get_type_symbol(node.expr_type)
|
mut from_type := node.expr_type
|
||||||
to_type_sym := c.table.get_type_symbol(node.typ) // type to be used as cast
|
to_type := node.typ
|
||||||
|
//
|
||||||
|
from_type_sym := c.table.get_type_symbol(from_type)
|
||||||
|
from_type_sym_final := c.table.get_final_type_symbol(from_type)
|
||||||
|
to_type_sym := c.table.get_type_symbol(to_type) // type to be used as cast
|
||||||
|
to_type_sym_final := c.table.get_final_type_symbol(to_type)
|
||||||
|
//
|
||||||
if (to_type_sym.is_number() && from_type_sym.name == 'JS.Number')
|
if (to_type_sym.is_number() && from_type_sym.name == 'JS.Number')
|
||||||
|| (to_type_sym.is_number() && from_type_sym.name == 'JS.BigInt')
|
|| (to_type_sym.is_number() && from_type_sym.name == 'JS.BigInt')
|
||||||
|| (to_type_sym.is_string() && from_type_sym.name == 'JS.String')
|
|| (to_type_sym.is_string() && from_type_sym.name == 'JS.String')
|
||||||
|| (node.typ.is_bool() && from_type_sym.name == 'JS.Boolean')
|
|| (to_type.is_bool() && from_type_sym.name == 'JS.Boolean')
|
||||||
|| (node.expr_type.is_bool() && to_type_sym.name == 'JS.Boolean')
|
|| (from_type.is_bool() && to_type_sym.name == 'JS.Boolean')
|
||||||
|| (from_type_sym.is_number() && to_type_sym.name == 'JS.Number')
|
|| (from_type_sym.is_number() && to_type_sym.name == 'JS.Number')
|
||||||
|| (from_type_sym.is_number() && to_type_sym.name == 'JS.BigInt')
|
|| (from_type_sym.is_number() && to_type_sym.name == 'JS.BigInt')
|
||||||
|| (from_type_sym.is_string() && to_type_sym.name == 'JS.String') {
|
|| (from_type_sym.is_string() && to_type_sym.name == 'JS.String') {
|
||||||
return node.typ
|
return to_type
|
||||||
}
|
}
|
||||||
|
|
||||||
if to_type_sym.language != .c {
|
if to_type_sym.language != .c {
|
||||||
c.ensure_type_exists(node.typ, node.pos) or {}
|
c.ensure_type_exists(to_type, node.pos) or {}
|
||||||
}
|
}
|
||||||
if from_type_sym.kind == .byte && node.expr_type.is_ptr() && to_type_sym.kind == .string
|
if from_type_sym.kind == .byte && from_type.is_ptr() && to_type_sym.kind == .string
|
||||||
&& !node.typ.is_ptr() {
|
&& !to_type.is_ptr() {
|
||||||
c.error('to convert a C string buffer pointer to a V string, use x.vstring() instead of string(x)',
|
c.error('to convert a C string buffer pointer to a V string, use x.vstring() instead of string(x)',
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
if node.expr_type == ast.void_type {
|
if from_type == ast.void_type {
|
||||||
c.error('expression does not return a value so it cannot be cast', node.expr.position())
|
c.error('expression does not return a value so it cannot be cast', node.expr.position())
|
||||||
}
|
}
|
||||||
if node.expr_type == ast.byte_type && to_type_sym.kind == .string {
|
//
|
||||||
c.error('can not cast type `byte` to string, use `${node.expr.str()}.str()` instead.',
|
if to_type == ast.string_type {
|
||||||
node.pos)
|
if from_type in [ast.byte_type, ast.bool_type] {
|
||||||
}
|
c.error('cannot cast type `$from_type_sym.name` to string, use `${node.expr.str()}.str()` instead.',
|
||||||
if to_type_sym.kind == .sum_type {
|
node.pos)
|
||||||
if node.expr_type in [ast.int_literal_type, ast.float_literal_type] {
|
|
||||||
node.expr_type = c.promote_num(node.expr_type, if node.expr_type == ast.int_literal_type {
|
|
||||||
ast.int_type
|
|
||||||
} else {
|
|
||||||
ast.f64_type
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if !c.table.sumtype_has_variant(node.typ, node.expr_type) && !node.typ.has_flag(.optional) {
|
if from_type.is_real_pointer() {
|
||||||
|
c.error('cannot cast pointer type `$from_type_sym.name` to string, use `&byte($node.expr.str()).vstring()` instead.',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
if from_type.is_number() {
|
||||||
|
c.error('cannot cast number to string, use `${node.expr.str()}.str()` instead.',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
if from_type_sym.kind == .alias && from_type_sym_final.name != 'string' {
|
||||||
|
c.error('cannot cast type `$from_type_sym.name` to string, use `x.str()` instead',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if to_type_sym.kind == .sum_type {
|
||||||
|
if from_type in [ast.int_literal_type, ast.float_literal_type] {
|
||||||
|
xx := if from_type == ast.int_literal_type { ast.int_type } else { ast.f64_type }
|
||||||
|
node.expr_type = c.promote_num(node.expr_type, xx)
|
||||||
|
from_type = node.expr_type
|
||||||
|
}
|
||||||
|
if !c.table.sumtype_has_variant(to_type, from_type) && !to_type.has_flag(.optional) {
|
||||||
c.error('cannot cast `$from_type_sym.name` to `$to_type_sym.name`', node.pos)
|
c.error('cannot cast `$from_type_sym.name` to `$to_type_sym.name`', node.pos)
|
||||||
}
|
}
|
||||||
} else if mut to_type_sym.info is ast.Alias {
|
} else if mut to_type_sym.info is ast.Alias {
|
||||||
if !c.check_types(node.expr_type, to_type_sym.info.parent_type) {
|
if !c.check_types(from_type, to_type_sym.info.parent_type) {
|
||||||
parent_type_sym := c.table.get_type_symbol(to_type_sym.info.parent_type)
|
c.error('cannot convert type `$from_type_sym.name` to `$to_type_sym.name` (alias to `$to_type_sym_final.name`)',
|
||||||
c.error('cannot convert type `$from_type_sym.name` to `$to_type_sym.name` (alias to `$parent_type_sym.name`)',
|
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
} else if node.typ == ast.string_type
|
} else if to_type != ast.string_type && from_type == ast.string_type
|
||||||
&& (from_type_sym.kind in [.int_literal, .int, .byte, .byteptr, .bool]
|
&& (!(to_type_sym.kind == .alias && to_type_sym_final.name == 'string')) {
|
||||||
|| (from_type_sym.kind == .array && from_type_sym.name == 'array_byte')) {
|
mut error_msg := 'cannot cast a string to a type `$to_type_sym_final.name`, that is not an alias of string'
|
||||||
type_name := c.table.type_to_str(node.expr_type)
|
if mut node.expr is ast.StringLiteral {
|
||||||
c.error('cannot cast type `$type_name` to string, use `x.str()` instead', node.pos)
|
if node.expr.val.len == 1 {
|
||||||
} else if node.expr_type == ast.string_type {
|
error_msg += ", for denoting characters use `$node.expr.val` instead of '$node.expr.val'"
|
||||||
if to_type_sym.kind != .alias {
|
|
||||||
mut error_msg := 'cannot cast a string'
|
|
||||||
if mut node.expr is ast.StringLiteral {
|
|
||||||
if node.expr.val.len == 1 {
|
|
||||||
error_msg += ", for denoting characters use `$node.expr.val` instead of '$node.expr.val'"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c.error(error_msg, node.pos)
|
|
||||||
}
|
}
|
||||||
} else if to_type_sym.kind == .byte && node.expr_type != ast.voidptr_type
|
c.error(error_msg, node.pos)
|
||||||
&& from_type_sym.kind != .enum_ && !node.expr_type.is_int() && !node.expr_type.is_float()
|
} else if to_type_sym.kind == .byte && from_type != ast.voidptr_type
|
||||||
&& node.expr_type != ast.bool_type && !node.expr_type.is_ptr() {
|
&& from_type_sym.kind != .enum_ && !from_type.is_int() && !from_type.is_float()
|
||||||
type_name := c.table.type_to_str(node.expr_type)
|
&& from_type != ast.bool_type && !from_type.is_ptr() && from_type_sym.kind == .alias
|
||||||
|
&& from_type_sym_final.name != 'byte' {
|
||||||
|
type_name := c.table.type_to_str(from_type)
|
||||||
c.error('cannot cast type `$type_name` to `byte`', node.pos)
|
c.error('cannot cast type `$type_name` to `byte`', node.pos)
|
||||||
} else if to_type_sym.kind == .struct_ && !node.typ.is_ptr()
|
} else if to_type_sym.kind == .struct_ && !to_type.is_ptr()
|
||||||
&& !(to_type_sym.info as ast.Struct).is_typedef {
|
&& !(to_type_sym.info as ast.Struct).is_typedef {
|
||||||
// For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard
|
// For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard
|
||||||
if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() {
|
if from_type_sym.kind == .struct_ && !from_type.is_ptr() {
|
||||||
c.warn('casting to struct is deprecated, use e.g. `Struct{...expr}` instead',
|
c.warn('casting to struct is deprecated, use e.g. `Struct{...expr}` instead',
|
||||||
node.pos)
|
node.pos)
|
||||||
from_type_info := from_type_sym.info as ast.Struct
|
from_type_info := from_type_sym.info as ast.Struct
|
||||||
|
@ -5735,40 +5751,37 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
type_name := c.table.type_to_str(node.expr_type)
|
type_name := c.table.type_to_str(from_type)
|
||||||
// dump(node.typ)
|
|
||||||
// dump(node.expr_type)
|
|
||||||
// dump(type_name)
|
|
||||||
// dump(to_type_sym.debug())
|
|
||||||
c.error('cannot cast `$type_name` to struct', node.pos)
|
c.error('cannot cast `$type_name` to struct', node.pos)
|
||||||
}
|
}
|
||||||
} else if to_type_sym.kind == .interface_ {
|
} else if to_type_sym.kind == .interface_ {
|
||||||
if c.type_implements(node.expr_type, node.typ, node.pos) {
|
if c.type_implements(from_type, to_type, node.pos) {
|
||||||
if !node.expr_type.is_ptr() && !node.expr_type.is_pointer()
|
if !from_type.is_ptr() && !from_type.is_pointer() && from_type_sym.kind != .interface_
|
||||||
&& from_type_sym.kind != .interface_ && !c.inside_unsafe {
|
&& !c.inside_unsafe {
|
||||||
c.mark_as_referenced(mut &node.expr, true)
|
c.mark_as_referenced(mut &node.expr, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if node.typ == ast.bool_type && node.expr_type != ast.bool_type && !c.inside_unsafe {
|
} else if to_type == ast.bool_type && from_type != ast.bool_type && !c.inside_unsafe {
|
||||||
c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos)
|
c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos)
|
||||||
} else if node.expr_type == ast.none_type && !node.typ.has_flag(.optional) {
|
} else if from_type == ast.none_type && !to_type.has_flag(.optional) {
|
||||||
type_name := c.table.type_to_str(node.typ)
|
type_name := c.table.type_to_str(to_type)
|
||||||
c.error('cannot cast `none` to `$type_name`', node.pos)
|
c.error('cannot cast `none` to `$type_name`', node.pos)
|
||||||
} else if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() {
|
} else if from_type_sym.kind == .struct_ && !from_type.is_ptr() {
|
||||||
if (node.typ.is_ptr() || to_type_sym.kind !in [.sum_type, .interface_]) && !c.is_builtin_mod {
|
if (to_type.is_ptr() || to_type_sym.kind !in [.sum_type, .interface_]) && !c.is_builtin_mod {
|
||||||
type_name := c.table.type_to_str(node.typ)
|
from_type_name := c.table.type_to_str(from_type)
|
||||||
c.error('cannot cast struct to `$type_name`', node.pos)
|
type_name := c.table.type_to_str(to_type)
|
||||||
|
c.error('cannot cast struct `$from_type_name` to `$type_name`', node.pos)
|
||||||
}
|
}
|
||||||
} else if node.expr_type.has_flag(.optional) || node.expr_type.has_flag(.variadic) {
|
} else if from_type.has_flag(.optional) || from_type.has_flag(.variadic) {
|
||||||
// variadic case can happen when arrays are converted into variadic
|
// variadic case can happen when arrays are converted into variadic
|
||||||
msg := if node.expr_type.has_flag(.optional) { 'an optional' } else { 'a variadic' }
|
msg := if from_type.has_flag(.optional) { 'an optional' } else { 'a variadic' }
|
||||||
c.error('cannot type cast $msg', node.pos)
|
c.error('cannot type cast $msg', node.pos)
|
||||||
} else if !c.inside_unsafe && node.typ.is_ptr() && node.expr_type.is_ptr()
|
} else if !c.inside_unsafe && to_type.is_ptr() && from_type.is_ptr()
|
||||||
&& node.typ.deref() != ast.char_type && node.expr_type.deref() != ast.char_type {
|
&& to_type.deref() != ast.char_type && from_type.deref() != ast.char_type {
|
||||||
ft := c.table.type_to_str(node.expr_type)
|
ft := c.table.type_to_str(from_type)
|
||||||
tt := c.table.type_to_str(node.typ)
|
tt := c.table.type_to_str(to_type)
|
||||||
c.warn('casting `$ft` to `$tt` is only allowed in `unsafe` code', node.pos)
|
c.warn('casting `$ft` to `$tt` is only allowed in `unsafe` code', node.pos)
|
||||||
} else if from_type_sym.kind == .array_fixed && !node.expr_type.is_ptr() {
|
} else if from_type_sym.kind == .array_fixed && !from_type.is_ptr() {
|
||||||
c.warn('cannot cast a fixed array (use e.g. `&arr[0]` instead)', node.pos)
|
c.warn('cannot cast a fixed array (use e.g. `&arr[0]` instead)', node.pos)
|
||||||
}
|
}
|
||||||
if node.has_arg {
|
if node.has_arg {
|
||||||
|
@ -5778,7 +5791,7 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||||
// checks on int literal to enum cast if the value represents a value on the enum
|
// checks on int literal to enum cast if the value represents a value on the enum
|
||||||
if to_type_sym.kind == .enum_ {
|
if to_type_sym.kind == .enum_ {
|
||||||
if node.expr is ast.IntegerLiteral {
|
if node.expr is ast.IntegerLiteral {
|
||||||
enum_typ_name := c.table.get_type_name(node.typ)
|
enum_typ_name := c.table.get_type_name(to_type)
|
||||||
node_val := (node.expr as ast.IntegerLiteral).val.int()
|
node_val := (node.expr as ast.IntegerLiteral).val.int()
|
||||||
|
|
||||||
if enum_decl := c.table.enum_decls[to_type_sym.name] {
|
if enum_decl := c.table.enum_decls[to_type_sym.name] {
|
||||||
|
@ -5807,9 +5820,9 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node.typname = c.table.get_type_symbol(node.typ).name
|
node.typname = c.table.get_type_symbol(to_type).name
|
||||||
|
|
||||||
return node.typ
|
return to_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
vlib/v/checker/tests/bool_string_cast_err.vv:2:13: error: cannot cast type `bool` to string, use `x.str()` instead
|
vlib/v/checker/tests/bool_string_cast_err.vv:2:13: error: cannot cast type `bool` to string, use `true.str()` instead.
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | println(string(true))
|
2 | println(string(true))
|
||||||
| ~~~~~~~~~~~~
|
| ~~~~~~~~~~~~
|
||||||
3 | println(string(false))
|
3 | println(string(false))
|
||||||
4 | }
|
4 | }
|
||||||
vlib/v/checker/tests/bool_string_cast_err.vv:3:13: error: cannot cast type `bool` to string, use `x.str()` instead
|
vlib/v/checker/tests/bool_string_cast_err.vv:3:13: error: cannot cast type `bool` to string, use `false.str()` instead.
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | println(string(true))
|
2 | println(string(true))
|
||||||
3 | println(string(false))
|
3 | println(string(false))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/cast_string_err.vv:2:7: error: cannot cast type `int literal` to string, use `x.str()` instead
|
vlib/v/checker/tests/cast_string_err.vv:2:7: error: cannot cast number to string, use `1.str()` instead.
|
||||||
1 | fn main() {
|
1 | fn main() {
|
||||||
2 | a := string(1)
|
2 | a := string(1)
|
||||||
| ~~~~~~~~~
|
| ~~~~~~~~~
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
vlib/v/checker/tests/cast_string_with_byte_err.vv:2:12: error: can not cast type `byte` to string, use `by.str()` instead.
|
vlib/v/checker/tests/cast_string_with_byte_err.vv:2:12: error: cannot cast type `byte` to string, use `by.str()` instead.
|
||||||
1 | for by in 'abc' {
|
1 | for by in 'abc' {
|
||||||
2 | println(string(by))
|
2 | println(string(by))
|
||||||
| ~~~~~~~~~~
|
| ~~~~~~~~~~
|
||||||
|
|
|
@ -1,60 +1,60 @@
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:5:10: error: cannot cast struct to `string`
|
vlib/v/checker/tests/struct_type_cast_err.vv:5:10: error: cannot cast struct `Foo` to `string`
|
||||||
3 | fn main() {
|
3 | fn main() {
|
||||||
4 | foo := Foo{}
|
4 | foo := Foo{}
|
||||||
5 | _ := string(foo)
|
5 | _ := string(foo)
|
||||||
| ~~~~~~~~~~~
|
| ~~~~~~~~~~~
|
||||||
6 | _ := int(foo)
|
6 | _ := int(foo)
|
||||||
7 | _ := u64(foo)
|
7 | _ := u64(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:6:10: error: cannot cast struct to `int`
|
vlib/v/checker/tests/struct_type_cast_err.vv:6:10: error: cannot cast struct `Foo` to `int`
|
||||||
4 | foo := Foo{}
|
4 | foo := Foo{}
|
||||||
5 | _ := string(foo)
|
5 | _ := string(foo)
|
||||||
6 | _ := int(foo)
|
6 | _ := int(foo)
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
7 | _ := u64(foo)
|
7 | _ := u64(foo)
|
||||||
8 | _ := u32(foo)
|
8 | _ := u32(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:7:10: error: cannot cast struct to `u64`
|
vlib/v/checker/tests/struct_type_cast_err.vv:7:10: error: cannot cast struct `Foo` to `u64`
|
||||||
5 | _ := string(foo)
|
5 | _ := string(foo)
|
||||||
6 | _ := int(foo)
|
6 | _ := int(foo)
|
||||||
7 | _ := u64(foo)
|
7 | _ := u64(foo)
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
8 | _ := u32(foo)
|
8 | _ := u32(foo)
|
||||||
9 | _ := rune(foo)
|
9 | _ := rune(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:8:10: error: cannot cast struct to `u32`
|
vlib/v/checker/tests/struct_type_cast_err.vv:8:10: error: cannot cast struct `Foo` to `u32`
|
||||||
6 | _ := int(foo)
|
6 | _ := int(foo)
|
||||||
7 | _ := u64(foo)
|
7 | _ := u64(foo)
|
||||||
8 | _ := u32(foo)
|
8 | _ := u32(foo)
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
9 | _ := rune(foo)
|
9 | _ := rune(foo)
|
||||||
10 | _ := byte(foo)
|
10 | _ := byte(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:9:10: error: cannot cast struct to `rune`
|
vlib/v/checker/tests/struct_type_cast_err.vv:9:10: error: cannot cast struct `Foo` to `rune`
|
||||||
7 | _ := u64(foo)
|
7 | _ := u64(foo)
|
||||||
8 | _ := u32(foo)
|
8 | _ := u32(foo)
|
||||||
9 | _ := rune(foo)
|
9 | _ := rune(foo)
|
||||||
| ~~~~~~~~~
|
| ~~~~~~~~~
|
||||||
10 | _ := byte(foo)
|
10 | _ := byte(foo)
|
||||||
11 | _ := i8(foo)
|
11 | _ := i8(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:10:10: error: cannot cast type `Foo` to `byte`
|
vlib/v/checker/tests/struct_type_cast_err.vv:10:10: error: cannot cast struct `Foo` to `byte`
|
||||||
8 | _ := u32(foo)
|
8 | _ := u32(foo)
|
||||||
9 | _ := rune(foo)
|
9 | _ := rune(foo)
|
||||||
10 | _ := byte(foo)
|
10 | _ := byte(foo)
|
||||||
| ~~~~~~~~~
|
| ~~~~~~~~~
|
||||||
11 | _ := i8(foo)
|
11 | _ := i8(foo)
|
||||||
12 | _ := i64(foo)
|
12 | _ := i64(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:11:10: error: cannot cast struct to `i8`
|
vlib/v/checker/tests/struct_type_cast_err.vv:11:10: error: cannot cast struct `Foo` to `i8`
|
||||||
9 | _ := rune(foo)
|
9 | _ := rune(foo)
|
||||||
10 | _ := byte(foo)
|
10 | _ := byte(foo)
|
||||||
11 | _ := i8(foo)
|
11 | _ := i8(foo)
|
||||||
| ~~~~~~~
|
| ~~~~~~~
|
||||||
12 | _ := i64(foo)
|
12 | _ := i64(foo)
|
||||||
13 | _ := int(foo)
|
13 | _ := int(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:12:10: error: cannot cast struct to `i64`
|
vlib/v/checker/tests/struct_type_cast_err.vv:12:10: error: cannot cast struct `Foo` to `i64`
|
||||||
10 | _ := byte(foo)
|
10 | _ := byte(foo)
|
||||||
11 | _ := i8(foo)
|
11 | _ := i8(foo)
|
||||||
12 | _ := i64(foo)
|
12 | _ := i64(foo)
|
||||||
| ~~~~~~~~
|
| ~~~~~~~~
|
||||||
13 | _ := int(foo)
|
13 | _ := int(foo)
|
||||||
14 | _ = &I1(foo)
|
14 | _ = &I1(foo)
|
||||||
vlib/v/checker/tests/struct_type_cast_err.vv:13:10: error: cannot cast struct to `int`
|
vlib/v/checker/tests/struct_type_cast_err.vv:13:10: error: cannot cast struct `Foo` to `int`
|
||||||
11 | _ := i8(foo)
|
11 | _ := i8(foo)
|
||||||
12 | _ := i64(foo)
|
12 | _ := i64(foo)
|
||||||
13 | _ := int(foo)
|
13 | _ := int(foo)
|
||||||
|
|
|
@ -378,18 +378,18 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string {
|
||||||
g.timers.start('cgen common')
|
g.timers.start('cgen common')
|
||||||
// to make sure type idx's are the same in cached mods
|
// to make sure type idx's are the same in cached mods
|
||||||
if g.pref.build_mode == .build_module {
|
if g.pref.build_mode == .build_module {
|
||||||
for idx, typ in g.table.type_symbols {
|
for idx, sym in g.table.type_symbols {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.definitions.writeln('int _v_type_idx_${typ.cname}();')
|
g.definitions.writeln('int _v_type_idx_${sym.cname}();')
|
||||||
}
|
}
|
||||||
} else if g.pref.use_cache {
|
} else if g.pref.use_cache {
|
||||||
for idx, typ in g.table.type_symbols {
|
for idx, sym in g.table.type_symbols {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.definitions.writeln('int _v_type_idx_${typ.cname}() { return $idx; };')
|
g.definitions.writeln('int _v_type_idx_${sym.cname}() { return $idx; };')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
@ -745,43 +745,43 @@ pub fn (mut g Gen) finish() {
|
||||||
pub fn (mut g Gen) write_typeof_functions() {
|
pub fn (mut g Gen) write_typeof_functions() {
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
g.writeln('// >> typeof() support for sum types / interfaces')
|
g.writeln('// >> typeof() support for sum types / interfaces')
|
||||||
for ityp, typ in g.table.type_symbols {
|
for ityp, sym in g.table.type_symbols {
|
||||||
if typ.kind == .sum_type {
|
if sym.kind == .sum_type {
|
||||||
sum_info := typ.info as ast.SumType
|
sum_info := sym.info as ast.SumType
|
||||||
if sum_info.is_generic {
|
if sum_info.is_generic {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.writeln('static char * v_typeof_sumtype_${typ.cname}(int sidx) { /* $typ.name */ ')
|
g.writeln('static char * v_typeof_sumtype_${sym.cname}(int sidx) { /* $sym.name */ ')
|
||||||
if g.pref.build_mode == .build_module {
|
if g.pref.build_mode == .build_module {
|
||||||
g.writeln('\t\tif( sidx == _v_type_idx_${typ.cname}() ) return "${util.strip_main_name(typ.name)}";')
|
g.writeln('\t\tif( sidx == _v_type_idx_${sym.cname}() ) return "${util.strip_main_name(sym.name)}";')
|
||||||
for v in sum_info.variants {
|
for v in sum_info.variants {
|
||||||
subtype := g.table.get_type_symbol(v)
|
subtype := g.table.get_type_symbol(v)
|
||||||
g.writeln('\tif( sidx == _v_type_idx_${subtype.cname}() ) return "${util.strip_main_name(subtype.name)}";')
|
g.writeln('\tif( sidx == _v_type_idx_${subtype.cname}() ) return "${util.strip_main_name(subtype.name)}";')
|
||||||
}
|
}
|
||||||
g.writeln('\treturn "unknown ${util.strip_main_name(typ.name)}";')
|
g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";')
|
||||||
} else {
|
} else {
|
||||||
tidx := g.table.find_type_idx(typ.name)
|
tidx := g.table.find_type_idx(sym.name)
|
||||||
g.writeln('\tswitch(sidx) {')
|
g.writeln('\tswitch(sidx) {')
|
||||||
g.writeln('\t\tcase $tidx: return "${util.strip_main_name(typ.name)}";')
|
g.writeln('\t\tcase $tidx: return "${util.strip_main_name(sym.name)}";')
|
||||||
for v in sum_info.variants {
|
for v in sum_info.variants {
|
||||||
subtype := g.table.get_type_symbol(v)
|
subtype := g.table.get_type_symbol(v)
|
||||||
g.writeln('\t\tcase $v: return "${util.strip_main_name(subtype.name)}";')
|
g.writeln('\t\tcase $v: return "${util.strip_main_name(subtype.name)}";')
|
||||||
}
|
}
|
||||||
g.writeln('\t\tdefault: return "unknown ${util.strip_main_name(typ.name)}";')
|
g.writeln('\t\tdefault: return "unknown ${util.strip_main_name(sym.name)}";')
|
||||||
g.writeln('\t}')
|
g.writeln('\t}')
|
||||||
}
|
}
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
g.writeln('int v_typeof_sumtype_idx_${typ.cname}(int sidx) { /* $typ.name */ ')
|
g.writeln('int v_typeof_sumtype_idx_${sym.cname}(int sidx) { /* $sym.name */ ')
|
||||||
if g.pref.build_mode == .build_module {
|
if g.pref.build_mode == .build_module {
|
||||||
g.writeln('\t\tif( sidx == _v_type_idx_${typ.cname}() ) return ${int(ityp)};')
|
g.writeln('\t\tif( sidx == _v_type_idx_${sym.cname}() ) return ${int(ityp)};')
|
||||||
for v in sum_info.variants {
|
for v in sum_info.variants {
|
||||||
subtype := g.table.get_type_symbol(v)
|
subtype := g.table.get_type_symbol(v)
|
||||||
g.writeln('\tif( sidx == _v_type_idx_${subtype.cname}() ) return ${int(v)};')
|
g.writeln('\tif( sidx == _v_type_idx_${subtype.cname}() ) return ${int(v)};')
|
||||||
}
|
}
|
||||||
g.writeln('\treturn ${int(ityp)};')
|
g.writeln('\treturn ${int(ityp)};')
|
||||||
} else {
|
} else {
|
||||||
tidx := g.table.find_type_idx(typ.name)
|
tidx := g.table.find_type_idx(sym.name)
|
||||||
g.writeln('\tswitch(sidx) {')
|
g.writeln('\tswitch(sidx) {')
|
||||||
g.writeln('\t\tcase $tidx: return ${int(ityp)};')
|
g.writeln('\t\tcase $tidx: return ${int(ityp)};')
|
||||||
for v in sum_info.variants {
|
for v in sum_info.variants {
|
||||||
|
@ -791,27 +791,27 @@ pub fn (mut g Gen) write_typeof_functions() {
|
||||||
g.writeln('\t}')
|
g.writeln('\t}')
|
||||||
}
|
}
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
} else if typ.kind == .interface_ {
|
} else if sym.kind == .interface_ {
|
||||||
if typ.info !is ast.Interface {
|
if sym.info !is ast.Interface {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
inter_info := typ.info as ast.Interface
|
inter_info := sym.info as ast.Interface
|
||||||
if inter_info.is_generic {
|
if inter_info.is_generic {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.definitions.writeln('static char * v_typeof_interface_${typ.cname}(int sidx);')
|
g.definitions.writeln('static char * v_typeof_interface_${sym.cname}(int sidx);')
|
||||||
g.writeln('static char * v_typeof_interface_${typ.cname}(int sidx) { /* $typ.name */ ')
|
g.writeln('static char * v_typeof_interface_${sym.cname}(int sidx) { /* $sym.name */ ')
|
||||||
for t in inter_info.types {
|
for t in inter_info.types {
|
||||||
subtype := g.table.get_type_symbol(t)
|
subtype := g.table.get_type_symbol(t)
|
||||||
g.writeln('\tif (sidx == _${typ.cname}_${subtype.cname}_index) return "${util.strip_main_name(subtype.name)}";')
|
g.writeln('\tif (sidx == _${sym.cname}_${subtype.cname}_index) return "${util.strip_main_name(subtype.name)}";')
|
||||||
}
|
}
|
||||||
g.writeln('\treturn "unknown ${util.strip_main_name(typ.name)}";')
|
g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
g.writeln('')
|
g.writeln('')
|
||||||
g.writeln('static int v_typeof_interface_idx_${typ.cname}(int sidx) { /* $typ.name */ ')
|
g.writeln('static int v_typeof_interface_idx_${sym.cname}(int sidx) { /* $sym.name */ ')
|
||||||
for t in inter_info.types {
|
for t in inter_info.types {
|
||||||
subtype := g.table.get_type_symbol(t)
|
subtype := g.table.get_type_symbol(t)
|
||||||
g.writeln('\tif (sidx == _${typ.cname}_${subtype.cname}_index) return ${int(t)};')
|
g.writeln('\tif (sidx == _${sym.cname}_${subtype.cname}_index) return ${int(t)};')
|
||||||
}
|
}
|
||||||
g.writeln('\treturn ${int(ityp)};')
|
g.writeln('\treturn ${int(ityp)};')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
@ -1097,24 +1097,24 @@ fn (g &Gen) type_sidx(t ast.Type) string {
|
||||||
|
|
||||||
//
|
//
|
||||||
pub fn (mut g Gen) write_typedef_types() {
|
pub fn (mut g Gen) write_typedef_types() {
|
||||||
for typ in g.table.type_symbols {
|
for sym in g.table.type_symbols {
|
||||||
if typ.name in c.builtins {
|
if sym.name in c.builtins {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
match typ.kind {
|
match sym.kind {
|
||||||
.array {
|
.array {
|
||||||
info := typ.info as ast.Array
|
info := sym.info as ast.Array
|
||||||
elem_sym := g.table.get_type_symbol(info.elem_type)
|
elem_sym := g.table.get_type_symbol(info.elem_type)
|
||||||
if elem_sym.kind != .placeholder && !info.elem_type.has_flag(.generic) {
|
if elem_sym.kind != .placeholder && !info.elem_type.has_flag(.generic) {
|
||||||
g.type_definitions.writeln('typedef array $typ.cname;')
|
g.type_definitions.writeln('typedef array $sym.cname;')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.array_fixed {
|
.array_fixed {
|
||||||
info := typ.info as ast.ArrayFixed
|
info := sym.info as ast.ArrayFixed
|
||||||
elem_sym := g.table.get_type_symbol(info.elem_type)
|
elem_sym := g.table.get_type_symbol(info.elem_type)
|
||||||
if elem_sym.is_builtin() {
|
if elem_sym.is_builtin() {
|
||||||
// .array_fixed {
|
// .array_fixed {
|
||||||
styp := typ.cname
|
styp := sym.cname
|
||||||
// array_fixed_char_300 => char x[300]
|
// array_fixed_char_300 => char x[300]
|
||||||
mut fixed := styp[12..]
|
mut fixed := styp[12..]
|
||||||
len := styp.after('_')
|
len := styp.after('_')
|
||||||
|
@ -1135,59 +1135,59 @@ pub fn (mut g Gen) write_typedef_types() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.chan {
|
.chan {
|
||||||
if typ.name != 'chan' {
|
if sym.name != 'chan' {
|
||||||
g.type_definitions.writeln('typedef chan $typ.cname;')
|
g.type_definitions.writeln('typedef chan $sym.cname;')
|
||||||
chan_inf := typ.chan_info()
|
chan_inf := sym.chan_info()
|
||||||
chan_elem_type := chan_inf.elem_type
|
chan_elem_type := chan_inf.elem_type
|
||||||
if !chan_elem_type.has_flag(.generic) {
|
if !chan_elem_type.has_flag(.generic) {
|
||||||
el_stype := g.typ(chan_elem_type)
|
el_stype := g.typ(chan_elem_type)
|
||||||
g.channel_definitions.writeln('
|
g.channel_definitions.writeln('
|
||||||
static inline $el_stype __${typ.cname}_popval($typ.cname ch) {
|
static inline $el_stype __${sym.cname}_popval($sym.cname ch) {
|
||||||
$el_stype val;
|
$el_stype val;
|
||||||
sync__Channel_try_pop_priv(ch, &val, false);
|
sync__Channel_try_pop_priv(ch, &val, false);
|
||||||
return val;
|
return val;
|
||||||
}')
|
}')
|
||||||
g.channel_definitions.writeln('
|
g.channel_definitions.writeln('
|
||||||
static inline void __${typ.cname}_pushval($typ.cname ch, $el_stype val) {
|
static inline void __${sym.cname}_pushval($sym.cname ch, $el_stype val) {
|
||||||
sync__Channel_try_push_priv(ch, &val, false);
|
sync__Channel_try_push_priv(ch, &val, false);
|
||||||
}')
|
}')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
g.type_definitions.writeln('typedef map $typ.cname;')
|
g.type_definitions.writeln('typedef map $sym.cname;')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for typ in g.table.type_symbols {
|
for sym in g.table.type_symbols {
|
||||||
if typ.kind == .alias && typ.name !in c.builtins {
|
if sym.kind == .alias && sym.name !in c.builtins {
|
||||||
g.write_alias_typesymbol_declaration(typ)
|
g.write_alias_typesymbol_declaration(sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for typ in g.table.type_symbols {
|
for sym in g.table.type_symbols {
|
||||||
if typ.kind == .function && typ.name !in c.builtins {
|
if sym.kind == .function && sym.name !in c.builtins {
|
||||||
g.write_fn_typesymbol_declaration(typ)
|
g.write_fn_typesymbol_declaration(sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Generating interfaces after all the common types have been defined
|
// Generating interfaces after all the common types have been defined
|
||||||
// to prevent generating interface struct before definition of field types
|
// to prevent generating interface struct before definition of field types
|
||||||
for typ in g.table.type_symbols {
|
for sym in g.table.type_symbols {
|
||||||
if typ.kind == .interface_ && typ.name !in c.builtins {
|
if sym.kind == .interface_ && sym.name !in c.builtins {
|
||||||
g.write_interface_typedef(typ)
|
g.write_interface_typedef(sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for typ in g.table.type_symbols {
|
for sym in g.table.type_symbols {
|
||||||
if typ.kind == .interface_ && typ.name !in c.builtins {
|
if sym.kind == .interface_ && sym.name !in c.builtins {
|
||||||
g.write_interface_typesymbol_declaration(typ)
|
g.write_interface_typesymbol_declaration(sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) {
|
pub fn (mut g Gen) write_alias_typesymbol_declaration(sym ast.TypeSymbol) {
|
||||||
parent := unsafe { &g.table.type_symbols[sym.parent_idx] }
|
parent := g.table.type_symbols[sym.parent_idx]
|
||||||
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
is_c_parent := parent.name.len > 2 && parent.name[0] == `C` && parent.name[1] == `.`
|
||||||
mut is_typedef := false
|
mut is_typedef := false
|
||||||
if parent.info is ast.Struct {
|
if parent.info is ast.Struct {
|
||||||
|
@ -3679,9 +3679,9 @@ fn (mut g Gen) map_fn_ptrs(key_typ ast.TypeSymbol) (string, string, string, stri
|
||||||
}
|
}
|
||||||
.voidptr {
|
.voidptr {
|
||||||
ts := if g.pref.m64 {
|
ts := if g.pref.m64 {
|
||||||
unsafe { &g.table.type_symbols[ast.u64_type_idx] }
|
unsafe { g.table.get_type_symbol_by_idx(ast.u64_type_idx) }
|
||||||
} else {
|
} else {
|
||||||
unsafe { &g.table.type_symbols[ast.u32_type_idx] }
|
unsafe { g.table.get_type_symbol_by_idx(ast.u32_type_idx) }
|
||||||
}
|
}
|
||||||
return g.map_fn_ptrs(ts)
|
return g.map_fn_ptrs(ts)
|
||||||
}
|
}
|
||||||
|
@ -5102,27 +5102,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||||
}
|
}
|
||||||
g.is_amp = false
|
g.is_amp = false
|
||||||
sym := g.table.get_type_symbol(node.typ)
|
sym := g.table.get_type_symbol(node.typ)
|
||||||
if sym.kind == .string && !node.typ.is_ptr() {
|
if sym.kind in [.sum_type, .interface_] {
|
||||||
// `string(x)` needs `tos()`, but not `&string(x)
|
|
||||||
// `tos(str, len)`, `tos2(str)`
|
|
||||||
if node.has_arg {
|
|
||||||
g.write('tos((byteptr)')
|
|
||||||
} else {
|
|
||||||
g.write('tos2((byteptr)')
|
|
||||||
}
|
|
||||||
g.expr(node.expr)
|
|
||||||
expr_sym := g.table.get_type_symbol(node.expr_type)
|
|
||||||
if expr_sym.kind == .array {
|
|
||||||
// if we are casting an array, we need to add `.data`
|
|
||||||
g.write('.data')
|
|
||||||
}
|
|
||||||
if node.has_arg {
|
|
||||||
// len argument
|
|
||||||
g.write(', ')
|
|
||||||
g.expr(node.arg)
|
|
||||||
}
|
|
||||||
g.write(')')
|
|
||||||
} else if sym.kind in [.sum_type, .interface_] {
|
|
||||||
g.expr_with_cast(node.expr, node.expr_type, node.typ)
|
g.expr_with_cast(node.expr, node.expr_type, node.typ)
|
||||||
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as ast.Struct).is_typedef {
|
} else if sym.kind == .struct_ && !node.typ.is_ptr() && !(sym.info as ast.Struct).is_typedef {
|
||||||
// deprecated, replaced by Struct{...exr}
|
// deprecated, replaced by Struct{...exr}
|
||||||
|
@ -6328,11 +6308,11 @@ fn (mut g Gen) write_builtin_types() {
|
||||||
if g.pref.no_builtin {
|
if g.pref.no_builtin {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mut builtin_types := []ast.TypeSymbol{} // builtin types
|
mut builtin_types := []&ast.TypeSymbol{} // builtin types
|
||||||
// builtin types need to be on top
|
// builtin types need to be on top
|
||||||
// everything except builtin will get sorted
|
// everything except builtin will get sorted
|
||||||
for builtin_name in c.builtins {
|
for builtin_name in c.builtins {
|
||||||
sym := g.table.type_symbols[g.table.type_idxs[builtin_name]]
|
sym := g.table.get_type_symbol_by_idx(g.table.type_idxs[builtin_name])
|
||||||
if sym.kind == .interface_ {
|
if sym.kind == .interface_ {
|
||||||
g.write_interface_typedef(sym)
|
g.write_interface_typedef(sym)
|
||||||
g.write_interface_typesymbol_declaration(sym)
|
g.write_interface_typesymbol_declaration(sym)
|
||||||
|
@ -6347,36 +6327,36 @@ fn (mut g Gen) write_builtin_types() {
|
||||||
// Sort the types, make sure types that are referenced by other types
|
// Sort the types, make sure types that are referenced by other types
|
||||||
// are added before them.
|
// are added before them.
|
||||||
fn (mut g Gen) write_sorted_types() {
|
fn (mut g Gen) write_sorted_types() {
|
||||||
mut types := []ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted
|
mut symbols := []&ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted
|
||||||
for typ in g.table.type_symbols {
|
for sym in g.table.type_symbols {
|
||||||
if typ.name !in c.builtins {
|
if sym.name !in c.builtins {
|
||||||
types << typ
|
symbols << sym
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sort structs
|
// sort structs
|
||||||
types_sorted := g.sort_structs(types)
|
sorted_symbols := g.sort_structs(symbols)
|
||||||
// Generate C code
|
// Generate C code
|
||||||
g.type_definitions.writeln('// builtin types:')
|
g.type_definitions.writeln('// builtin types:')
|
||||||
g.type_definitions.writeln('//------------------ #endbuiltin')
|
g.type_definitions.writeln('//------------------ #endbuiltin')
|
||||||
g.write_types(types_sorted)
|
g.write_types(sorted_symbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
for typ in types {
|
for sym in symbols {
|
||||||
if typ.name.starts_with('C.') {
|
if sym.name.starts_with('C.') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if typ.kind == .none_ {
|
if sym.kind == .none_ {
|
||||||
g.type_definitions.writeln('struct none {')
|
g.type_definitions.writeln('struct none {')
|
||||||
g.type_definitions.writeln('\tEMPTY_STRUCT_DECLARATION;')
|
g.type_definitions.writeln('\tEMPTY_STRUCT_DECLARATION;')
|
||||||
g.type_definitions.writeln('};')
|
g.type_definitions.writeln('};')
|
||||||
g.typedefs2.writeln('typedef struct none none;')
|
g.typedefs2.writeln('typedef struct none none;')
|
||||||
}
|
}
|
||||||
// sym := g.table.get_type_symbol(typ)
|
// sym := g.table.get_type_symbol(typ)
|
||||||
mut name := typ.cname
|
mut name := sym.cname
|
||||||
match mut typ.info {
|
match mut sym.info {
|
||||||
ast.Struct {
|
ast.Struct {
|
||||||
if typ.info.is_generic {
|
if sym.info.is_generic {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if name.contains('_T_') {
|
if name.contains('_T_') {
|
||||||
|
@ -6388,7 +6368,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||||
mut pre_pragma := ''
|
mut pre_pragma := ''
|
||||||
mut post_pragma := ''
|
mut post_pragma := ''
|
||||||
|
|
||||||
for attr in typ.info.attrs {
|
for attr in sym.info.attrs {
|
||||||
match attr.name {
|
match attr.name {
|
||||||
'_pack' {
|
'_pack' {
|
||||||
pre_pragma += '#pragma pack(push, $attr.arg)\n'
|
pre_pragma += '#pragma pack(push, $attr.arg)\n'
|
||||||
|
@ -6400,13 +6380,13 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||||
|
|
||||||
g.type_definitions.writeln(pre_pragma)
|
g.type_definitions.writeln(pre_pragma)
|
||||||
|
|
||||||
if typ.info.is_union {
|
if sym.info.is_union {
|
||||||
g.type_definitions.writeln('union $name {')
|
g.type_definitions.writeln('union $name {')
|
||||||
} else {
|
} else {
|
||||||
g.type_definitions.writeln('struct $name {')
|
g.type_definitions.writeln('struct $name {')
|
||||||
}
|
}
|
||||||
if typ.info.fields.len > 0 || typ.info.embeds.len > 0 {
|
if sym.info.fields.len > 0 || sym.info.embeds.len > 0 {
|
||||||
for field in typ.info.fields {
|
for field in sym.info.fields {
|
||||||
// Some of these structs may want to contain
|
// Some of these structs may want to contain
|
||||||
// optionals that may not be defined at this point
|
// optionals that may not be defined at this point
|
||||||
// if this is the case then we are going to
|
// if this is the case then we are going to
|
||||||
|
@ -6439,7 +6419,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
// g.type_definitions.writeln('} $name;\n')
|
// g.type_definitions.writeln('} $name;\n')
|
||||||
//
|
//
|
||||||
ti_attrs := if typ.info.attrs.contains('packed') {
|
ti_attrs := if sym.info.attrs.contains('packed') {
|
||||||
'__attribute__((__packed__))'
|
'__attribute__((__packed__))'
|
||||||
} else {
|
} else {
|
||||||
''
|
''
|
||||||
|
@ -6469,26 +6449,26 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.SumType {
|
ast.SumType {
|
||||||
if typ.info.is_generic {
|
if sym.info.is_generic {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.typedefs.writeln('typedef struct $name $name;')
|
g.typedefs.writeln('typedef struct $name $name;')
|
||||||
g.type_definitions.writeln('')
|
g.type_definitions.writeln('')
|
||||||
g.type_definitions.writeln('// Union sum type $name = ')
|
g.type_definitions.writeln('// Union sum type $name = ')
|
||||||
for variant in typ.info.variants {
|
for variant in sym.info.variants {
|
||||||
g.type_definitions.writeln('// | ${variant:4d} = ${g.typ(variant.idx()):-20s}')
|
g.type_definitions.writeln('// | ${variant:4d} = ${g.typ(variant.idx()):-20s}')
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('struct $name {')
|
g.type_definitions.writeln('struct $name {')
|
||||||
g.type_definitions.writeln('\tunion {')
|
g.type_definitions.writeln('\tunion {')
|
||||||
for variant in typ.info.variants {
|
for variant in sym.info.variants {
|
||||||
variant_sym := g.table.get_type_symbol(variant)
|
variant_sym := g.table.get_type_symbol(variant)
|
||||||
g.type_definitions.writeln('\t\t${g.typ(variant.ref())} _$variant_sym.cname;')
|
g.type_definitions.writeln('\t\t${g.typ(variant.ref())} _$variant_sym.cname;')
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('\t};')
|
g.type_definitions.writeln('\t};')
|
||||||
g.type_definitions.writeln('\tint _typ;')
|
g.type_definitions.writeln('\tint _typ;')
|
||||||
if typ.info.fields.len > 0 {
|
if sym.info.fields.len > 0 {
|
||||||
g.writeln('\t// pointers to common sumtype fields')
|
g.writeln('\t// pointers to common sumtype fields')
|
||||||
for field in typ.info.fields {
|
for field in sym.info.fields {
|
||||||
g.type_definitions.writeln('\t${g.typ(field.typ.ref())} $field.name;')
|
g.type_definitions.writeln('\t${g.typ(field.typ.ref())} $field.name;')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6496,18 +6476,18 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||||
g.type_definitions.writeln('')
|
g.type_definitions.writeln('')
|
||||||
}
|
}
|
||||||
ast.ArrayFixed {
|
ast.ArrayFixed {
|
||||||
elem_sym := g.table.get_type_symbol(typ.info.elem_type)
|
elem_sym := g.table.get_type_symbol(sym.info.elem_type)
|
||||||
if !elem_sym.is_builtin() && !typ.info.elem_type.has_flag(.generic) {
|
if !elem_sym.is_builtin() && !sym.info.elem_type.has_flag(.generic) {
|
||||||
// .array_fixed {
|
// .array_fixed {
|
||||||
styp := typ.cname
|
styp := sym.cname
|
||||||
// array_fixed_char_300 => char x[300]
|
// array_fixed_char_300 => char x[300]
|
||||||
// [16]&&&EventListener{} => Array_fixed_main__EventListener_16_ptr3
|
// [16]&&&EventListener{} => Array_fixed_main__EventListener_16_ptr3
|
||||||
// => typedef main__EventListener*** Array_fixed_main__EventListener_16_ptr3 [16]
|
// => typedef main__EventListener*** Array_fixed_main__EventListener_16_ptr3 [16]
|
||||||
mut fixed_elem_name := g.typ(typ.info.elem_type.set_nr_muls(0))
|
mut fixed_elem_name := g.typ(sym.info.elem_type.set_nr_muls(0))
|
||||||
if typ.info.elem_type.is_ptr() {
|
if sym.info.elem_type.is_ptr() {
|
||||||
fixed_elem_name += '*'.repeat(typ.info.elem_type.nr_muls())
|
fixed_elem_name += '*'.repeat(sym.info.elem_type.nr_muls())
|
||||||
}
|
}
|
||||||
len := typ.info.size
|
len := sym.info.size
|
||||||
if fixed_elem_name.starts_with('C__') {
|
if fixed_elem_name.starts_with('C__') {
|
||||||
fixed_elem_name = fixed_elem_name[3..]
|
fixed_elem_name = fixed_elem_name[3..]
|
||||||
}
|
}
|
||||||
|
@ -6529,7 +6509,7 @@ fn (mut g Gen) write_types(types []ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort structs by dependant fields
|
// sort structs by dependant fields
|
||||||
fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol {
|
fn (g &Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol {
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
defer {
|
defer {
|
||||||
util.timing_measure(@METHOD)
|
util.timing_measure(@METHOD)
|
||||||
|
@ -6537,26 +6517,26 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol {
|
||||||
mut dep_graph := depgraph.new_dep_graph()
|
mut dep_graph := depgraph.new_dep_graph()
|
||||||
// types name list
|
// types name list
|
||||||
mut type_names := []string{}
|
mut type_names := []string{}
|
||||||
for typ in typesa {
|
for sym in typesa {
|
||||||
type_names << typ.name
|
type_names << sym.name
|
||||||
}
|
}
|
||||||
// loop over types
|
// loop over types
|
||||||
for t in typesa {
|
for sym in typesa {
|
||||||
if t.kind == .interface_ {
|
if sym.kind == .interface_ {
|
||||||
dep_graph.add(t.name, [])
|
dep_graph.add(sym.name, [])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// create list of deps
|
// create list of deps
|
||||||
mut field_deps := []string{}
|
mut field_deps := []string{}
|
||||||
match mut t.info {
|
match mut sym.info {
|
||||||
ast.ArrayFixed {
|
ast.ArrayFixed {
|
||||||
dep := g.table.get_type_symbol(t.info.elem_type).name
|
dep := g.table.get_type_symbol(sym.info.elem_type).name
|
||||||
if dep in type_names {
|
if dep in type_names {
|
||||||
field_deps << dep
|
field_deps << dep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Struct {
|
ast.Struct {
|
||||||
for embed in t.info.embeds {
|
for embed in sym.info.embeds {
|
||||||
dep := g.table.get_type_symbol(embed).name
|
dep := g.table.get_type_symbol(embed).name
|
||||||
// skip if not in types list or already in deps
|
// skip if not in types list or already in deps
|
||||||
if dep !in type_names || dep in field_deps {
|
if dep !in type_names || dep in field_deps {
|
||||||
|
@ -6564,7 +6544,7 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol {
|
||||||
}
|
}
|
||||||
field_deps << dep
|
field_deps << dep
|
||||||
}
|
}
|
||||||
for field in t.info.fields {
|
for field in sym.info.fields {
|
||||||
dep := g.table.get_type_symbol(field.typ).name
|
dep := g.table.get_type_symbol(field.typ).name
|
||||||
// skip if not in types list or already in deps
|
// skip if not in types list or already in deps
|
||||||
if dep !in type_names || dep in field_deps || field.typ.is_ptr() {
|
if dep !in type_names || dep in field_deps || field.typ.is_ptr() {
|
||||||
|
@ -6577,7 +6557,7 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
// add type and dependant types to graph
|
// add type and dependant types to graph
|
||||||
dep_graph.add(t.name, field_deps)
|
dep_graph.add(sym.name, field_deps)
|
||||||
}
|
}
|
||||||
// sort graph
|
// sort graph
|
||||||
dep_graph_sorted := dep_graph.resolve()
|
dep_graph_sorted := dep_graph.resolve()
|
||||||
|
@ -6590,11 +6570,11 @@ fn (g &Gen) sort_structs(typesa []ast.TypeSymbol) []ast.TypeSymbol {
|
||||||
'\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro')
|
'\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro')
|
||||||
}
|
}
|
||||||
// sort types
|
// sort types
|
||||||
mut types_sorted := []ast.TypeSymbol{cap: dep_graph_sorted.nodes.len}
|
mut sorted_symbols := []&ast.TypeSymbol{cap: dep_graph_sorted.nodes.len}
|
||||||
for node in dep_graph_sorted.nodes {
|
for node in dep_graph_sorted.nodes {
|
||||||
types_sorted << g.table.type_symbols[g.table.type_idxs[node.name]]
|
sorted_symbols << g.table.get_type_symbol_by_idx(g.table.type_idxs[node.name])
|
||||||
}
|
}
|
||||||
return types_sorted
|
return sorted_symbols
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
|
@ -7184,19 +7164,19 @@ fn (g Gen) as_cast_name_table() string {
|
||||||
fn (mut g Gen) interface_table() string {
|
fn (mut g Gen) interface_table() string {
|
||||||
mut sb := strings.new_builder(100)
|
mut sb := strings.new_builder(100)
|
||||||
mut conversion_functions := strings.new_builder(100)
|
mut conversion_functions := strings.new_builder(100)
|
||||||
for ityp in g.table.type_symbols {
|
for isym in g.table.type_symbols {
|
||||||
if ityp.kind != .interface_ {
|
if isym.kind != .interface_ {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ityp.info !is ast.Interface {
|
if isym.info !is ast.Interface {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
inter_info := ityp.info as ast.Interface
|
inter_info := isym.info as ast.Interface
|
||||||
if inter_info.is_generic {
|
if inter_info.is_generic {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// interface_name is for example Speaker
|
// interface_name is for example Speaker
|
||||||
interface_name := ityp.cname
|
interface_name := isym.cname
|
||||||
// generate a struct that references interface methods
|
// generate a struct that references interface methods
|
||||||
methods_struct_name := 'struct _${interface_name}_interface_methods'
|
methods_struct_name := 'struct _${interface_name}_interface_methods'
|
||||||
mut methods_struct_def := strings.new_builder(100)
|
mut methods_struct_def := strings.new_builder(100)
|
||||||
|
@ -7243,7 +7223,7 @@ fn (mut g Gen) interface_table() string {
|
||||||
cctype := g.cc_type(st, true)
|
cctype := g.cc_type(st, true)
|
||||||
$if debug_interface_table ? {
|
$if debug_interface_table ? {
|
||||||
eprintln(
|
eprintln(
|
||||||
'>> interface name: $ityp.name | concrete type: $st.debug() | st symname: ' +
|
'>> interface name: $isym.name | concrete type: $st.debug() | st symname: ' +
|
||||||
st_sym.name)
|
st_sym.name)
|
||||||
}
|
}
|
||||||
// Speaker_Cat_index = 0
|
// Speaker_Cat_index = 0
|
||||||
|
@ -7253,7 +7233,7 @@ fn (mut g Gen) interface_table() string {
|
||||||
}
|
}
|
||||||
already_generated_mwrappers[interface_index_name] = current_iinidx
|
already_generated_mwrappers[interface_index_name] = current_iinidx
|
||||||
current_iinidx++
|
current_iinidx++
|
||||||
if ityp.name != 'vweb.DbInterface' { // TODO remove this
|
if isym.name != 'vweb.DbInterface' { // TODO remove this
|
||||||
// eprintln('>>> current_iinidx: ${current_iinidx-iinidx_minimum_base} | interface_index_name: $interface_index_name')
|
// eprintln('>>> current_iinidx: ${current_iinidx-iinidx_minimum_base} | interface_index_name: $interface_index_name')
|
||||||
sb.writeln('static $interface_name I_${cctype}_to_Interface_${interface_name}($cctype* x);')
|
sb.writeln('static $interface_name I_${cctype}_to_Interface_${interface_name}($cctype* x);')
|
||||||
mut cast_struct := strings.new_builder(100)
|
mut cast_struct := strings.new_builder(100)
|
||||||
|
|
|
@ -119,7 +119,7 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Pref
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) typ(a int) &ast.TypeSymbol {
|
pub fn (mut g Gen) typ(a int) &ast.TypeSymbol {
|
||||||
return &g.table.type_symbols[a]
|
return g.table.type_symbols[a]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g Gen) generate_header() {
|
pub fn (mut g Gen) generate_header() {
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
type MyByte = byte
|
||||||
|
|
||||||
|
type MyInt = int
|
||||||
|
|
||||||
|
type MyString = string
|
||||||
|
|
||||||
|
fn ok() {
|
||||||
|
assert true
|
||||||
|
}
|
||||||
|
|
||||||
|
// bytes
|
||||||
|
fn test_byte_aliasing() {
|
||||||
|
dump(byte(123))
|
||||||
|
dump(MyByte(byte(123)))
|
||||||
|
dump(byte(MyByte(byte(123))))
|
||||||
|
ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_pbyte_aliasing() {
|
||||||
|
unsafe {
|
||||||
|
dump(voidptr(&byte(123)))
|
||||||
|
dump(voidptr(&MyByte(&byte(123))))
|
||||||
|
dump(voidptr(&byte(&MyByte(&byte(123)))))
|
||||||
|
}
|
||||||
|
ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ints
|
||||||
|
fn test_int_aliasing() {
|
||||||
|
dump(int(123))
|
||||||
|
dump(int(MyInt(123)))
|
||||||
|
dump(MyInt(int(MyInt(123))))
|
||||||
|
ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_pint_aliasing() {
|
||||||
|
unsafe {
|
||||||
|
dump(voidptr(&int(123456)))
|
||||||
|
dump(voidptr(&MyInt(&int(123456))))
|
||||||
|
dump(voidptr(&int(&MyInt(&int(123456)))))
|
||||||
|
}
|
||||||
|
ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
// strings
|
||||||
|
fn test_string_aliasing() {
|
||||||
|
$if msvc {
|
||||||
|
eprintln('> TODO: msvc errors out for casting a `string` to a `string`')
|
||||||
|
}
|
||||||
|
$if !msvc {
|
||||||
|
dump(string('abc'))
|
||||||
|
dump(string(MyString('abc')))
|
||||||
|
dump(MyString(string(MyString('abc'))))
|
||||||
|
}
|
||||||
|
ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_pstring_aliasing() {
|
||||||
|
s := 'abc'
|
||||||
|
unsafe {
|
||||||
|
dump(voidptr(&string(&s)))
|
||||||
|
dump(voidptr(&string(&MyString(&s))))
|
||||||
|
dump(voidptr(&MyString(&string(&MyString(&s)))))
|
||||||
|
}
|
||||||
|
ok()
|
||||||
|
}
|
|
@ -13,6 +13,10 @@ pub mut:
|
||||||
last_line int // the line number where the ast object ends (used by vfmt)
|
last_line int // the line number where the ast object ends (used by vfmt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[unsafe]
|
||||||
|
pub fn (mut p Position) free() {
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (pos Position) extend(end Position) Position {
|
pub fn (pos Position) extend(end Position) Position {
|
||||||
return Position{
|
return Position{
|
||||||
...pos
|
...pos
|
||||||
|
|
Loading…
Reference in New Issue