checker, gen: add support for a [minify] struct attribute (#14247)
parent
aed2d0caf2
commit
332e821518
|
@ -202,6 +202,7 @@ pub:
|
|||
pos token.Pos
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct StringLiteral {
|
||||
pub:
|
||||
val string
|
||||
|
@ -246,6 +247,7 @@ pub enum GenericKindField {
|
|||
}
|
||||
|
||||
// `foo.bar`
|
||||
[minify]
|
||||
pub struct SelectorExpr {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -287,11 +289,13 @@ pub:
|
|||
is_skipped bool // module main can be skipped in single file programs
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct StructField {
|
||||
pub:
|
||||
pos token.Pos
|
||||
type_pos token.Pos
|
||||
comments []Comment
|
||||
i int
|
||||
has_default_expr bool
|
||||
attrs []Attr
|
||||
is_pub bool
|
||||
|
@ -333,6 +337,7 @@ pub mut:
|
|||
}
|
||||
|
||||
// const declaration
|
||||
[minify]
|
||||
pub struct ConstDecl {
|
||||
pub:
|
||||
is_pub bool
|
||||
|
@ -344,6 +349,7 @@ pub mut:
|
|||
is_block bool // const() block
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct StructDecl {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -380,6 +386,7 @@ pub:
|
|||
comments []Comment
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct InterfaceDecl {
|
||||
pub:
|
||||
name string
|
||||
|
@ -431,6 +438,7 @@ pub mut:
|
|||
// ...a
|
||||
// field1: 'hello'
|
||||
// }`
|
||||
[minify]
|
||||
pub struct StructInit {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -484,6 +492,7 @@ pub mut:
|
|||
}
|
||||
|
||||
// function or method declaration
|
||||
[minify]
|
||||
pub struct FnDecl {
|
||||
pub:
|
||||
name string // 'math.bits.normalize'
|
||||
|
@ -542,6 +551,7 @@ pub mut:
|
|||
}
|
||||
|
||||
// break, continue
|
||||
[minify]
|
||||
pub struct BranchStmt {
|
||||
pub:
|
||||
kind token.Kind
|
||||
|
@ -550,6 +560,7 @@ pub:
|
|||
}
|
||||
|
||||
// function or method call expr
|
||||
[minify]
|
||||
pub struct CallExpr {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -589,6 +600,7 @@ pub struct AutofreeArgVar {
|
|||
}
|
||||
*/
|
||||
// function call argument: `f(callarg)`
|
||||
[minify]
|
||||
pub struct CallArg {
|
||||
pub:
|
||||
is_mut bool
|
||||
|
@ -612,6 +624,7 @@ pub mut:
|
|||
types []Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Var {
|
||||
pub:
|
||||
name string
|
||||
|
@ -643,6 +656,7 @@ pub mut:
|
|||
|
||||
// used for smartcasting only
|
||||
// struct fields change type in scopes
|
||||
[minify]
|
||||
pub struct ScopeStructField {
|
||||
pub:
|
||||
struct_type Type // type of struct
|
||||
|
@ -657,6 +671,7 @@ pub:
|
|||
// 12 <- the current casted type (typ)
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct GlobalField {
|
||||
pub:
|
||||
name string
|
||||
|
@ -682,6 +697,7 @@ pub mut:
|
|||
end_comments []Comment
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct EmbeddedFile {
|
||||
pub:
|
||||
rpath string // used in the source code, as an ID/key to the embed
|
||||
|
@ -749,6 +765,7 @@ pub mut:
|
|||
|
||||
// TODO: (joe) remove completely, use ident.obj
|
||||
// instead which points to the scope object
|
||||
[minify]
|
||||
pub struct IdentVar {
|
||||
pub mut:
|
||||
typ Type
|
||||
|
@ -771,6 +788,7 @@ pub enum IdentKind {
|
|||
}
|
||||
|
||||
// A single identifier
|
||||
[minify]
|
||||
pub struct Ident {
|
||||
pub:
|
||||
language Language
|
||||
|
@ -816,6 +834,7 @@ pub fn (i &Ident) var_info() IdentVar {
|
|||
|
||||
// left op right
|
||||
// See: token.Kind.is_infix
|
||||
[minify]
|
||||
pub struct InfixExpr {
|
||||
pub:
|
||||
op token.Kind
|
||||
|
@ -846,6 +865,7 @@ pub mut:
|
|||
}
|
||||
|
||||
// See: token.Kind.is_prefix
|
||||
[minify]
|
||||
pub struct PrefixExpr {
|
||||
pub:
|
||||
op token.Kind
|
||||
|
@ -857,6 +877,7 @@ pub mut:
|
|||
is_option bool // IfGuard
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct IndexExpr {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -874,6 +895,7 @@ pub mut:
|
|||
is_gated bool // #[] gated array
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct IfExpr {
|
||||
pub:
|
||||
is_comptime bool
|
||||
|
@ -921,6 +943,7 @@ pub mut:
|
|||
scope &Scope
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct MatchExpr {
|
||||
pub:
|
||||
tok_kind token.Kind
|
||||
|
@ -959,6 +982,7 @@ pub mut:
|
|||
expected_type Type // for debugging only
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct SelectBranch {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -1000,6 +1024,7 @@ pub mut:
|
|||
scope &Scope
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct ForInStmt {
|
||||
pub:
|
||||
key_var string
|
||||
|
@ -1060,6 +1085,7 @@ pub:
|
|||
}
|
||||
*/
|
||||
// variable assign statement
|
||||
[minify]
|
||||
pub struct AssignStmt {
|
||||
pub:
|
||||
op token.Kind // include: =,:=,+=,-=,*=,/= and so on; for a list of all the assign operators, see vlib/token/token.v
|
||||
|
@ -1111,6 +1137,7 @@ pub mut:
|
|||
}
|
||||
|
||||
// enum declaration
|
||||
[minify]
|
||||
pub struct EnumDecl {
|
||||
pub:
|
||||
name string
|
||||
|
@ -1161,6 +1188,7 @@ pub:
|
|||
// TODO: handle this differently
|
||||
// v1 excludes non current os ifdefs so
|
||||
// the defer's never get added in the first place
|
||||
[minify]
|
||||
pub struct DeferStmt {
|
||||
pub:
|
||||
stmts []Stmt
|
||||
|
@ -1179,6 +1207,7 @@ pub mut:
|
|||
expr Expr
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct GoExpr {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -1199,6 +1228,7 @@ pub:
|
|||
pos token.Pos
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct ArrayInit {
|
||||
pub:
|
||||
pos token.Pos // `[]` in []Type{} position
|
||||
|
@ -1242,6 +1272,7 @@ pub mut:
|
|||
elem_type Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct MapInit {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -1257,6 +1288,7 @@ pub mut:
|
|||
}
|
||||
|
||||
// s[10..20]
|
||||
[minify]
|
||||
pub struct RangeExpr {
|
||||
pub:
|
||||
has_high bool
|
||||
|
@ -1268,6 +1300,7 @@ pub mut:
|
|||
high Expr
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct CastExpr {
|
||||
pub mut:
|
||||
arg Expr // `n` in `string(buf, n)`
|
||||
|
@ -1279,6 +1312,7 @@ pub mut:
|
|||
pos token.Pos
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct AsmStmt {
|
||||
pub:
|
||||
arch pref.Arch
|
||||
|
@ -1296,6 +1330,7 @@ pub mut:
|
|||
local_labels []string // local to the assembly block
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct AsmTemplate {
|
||||
pub mut:
|
||||
name string
|
||||
|
@ -1460,6 +1495,7 @@ pub const (
|
|||
}
|
||||
)
|
||||
|
||||
[minify]
|
||||
pub struct AssertStmt {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -1511,6 +1547,7 @@ pub:
|
|||
*/
|
||||
|
||||
// deprecated
|
||||
[minify]
|
||||
pub struct Assoc {
|
||||
pub:
|
||||
var_name string
|
||||
|
@ -1540,6 +1577,7 @@ pub mut:
|
|||
typ Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct OffsetOf {
|
||||
pub:
|
||||
struct_type Type
|
||||
|
@ -1555,6 +1593,7 @@ pub mut:
|
|||
expr Expr
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct TypeOf {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -1563,6 +1602,7 @@ pub mut:
|
|||
expr_type Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct DumpExpr {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
@ -1598,6 +1638,7 @@ pub mut:
|
|||
val string
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct ComptimeSelector {
|
||||
pub:
|
||||
has_parens bool // if $() is used, for vfmt
|
||||
|
@ -1609,6 +1650,7 @@ pub mut:
|
|||
typ Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct ComptimeCall {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
|
|
@ -14,6 +14,7 @@ pub enum AttrKind {
|
|||
}
|
||||
|
||||
// e.g. `[unsafe]`
|
||||
[minify]
|
||||
pub struct Attr {
|
||||
pub:
|
||||
name string // [name]
|
||||
|
|
|
@ -9,7 +9,7 @@ import v.cflag
|
|||
import v.token
|
||||
import v.util
|
||||
|
||||
[heap]
|
||||
[heap; minify]
|
||||
pub struct Table {
|
||||
mut:
|
||||
parsing_type string // name of the type to enable recursive type parsing
|
||||
|
@ -86,6 +86,7 @@ pub fn (t &Table) panic(message string) {
|
|||
t.panic_handler(t, message)
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Fn {
|
||||
pub:
|
||||
is_variadic bool
|
||||
|
@ -126,6 +127,7 @@ fn (f &Fn) method_equals(o &Fn) bool {
|
|||
&& f.name == o.name
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Param {
|
||||
pub:
|
||||
pos token.Pos
|
||||
|
|
|
@ -41,14 +41,22 @@ fn test_type_size() ? {
|
|||
|
||||
mut t := b.table
|
||||
|
||||
assert sizeof(T01) == t.type_size(t.type_idxs['main.T01'] ?)
|
||||
assert sizeof(T02) == t.type_size(t.type_idxs['main.T02'] ?)
|
||||
assert sizeof(T03) == t.type_size(t.type_idxs['main.T03'] ?)
|
||||
assert sizeof(T04) == t.type_size(t.type_idxs['main.T04'] ?)
|
||||
assert sizeof(T05) == t.type_size(t.type_idxs['main.T05'] ?)
|
||||
assert sizeof(T06) == t.type_size(t.type_idxs['main.T06'] ?)
|
||||
assert sizeof(T07) == t.type_size(t.type_idxs['main.T07'] ?)
|
||||
assert sizeof(T08) == t.type_size(t.type_idxs['main.T08'] ?)
|
||||
size01, _ := t.type_size(t.type_idxs['main.T01'] ?)
|
||||
assert sizeof(T01) == size01
|
||||
size02, _ := t.type_size(t.type_idxs['main.T02'] ?)
|
||||
assert sizeof(T02) == size02
|
||||
size03, _ := t.type_size(t.type_idxs['main.T03'] ?)
|
||||
assert sizeof(T03) == size03
|
||||
size04, _ := t.type_size(t.type_idxs['main.T04'] ?)
|
||||
assert sizeof(T04) == size04
|
||||
size05, _ := t.type_size(t.type_idxs['main.T05'] ?)
|
||||
assert sizeof(T05) == size05
|
||||
size06, _ := t.type_size(t.type_idxs['main.T06'] ?)
|
||||
assert sizeof(T06) == size06
|
||||
size07, _ := t.type_size(t.type_idxs['main.T07'] ?)
|
||||
assert sizeof(T07) == size07
|
||||
size08, _ := t.type_size(t.type_idxs['main.T08'] ?)
|
||||
assert sizeof(T08) == size08
|
||||
|
||||
println('done')
|
||||
}
|
||||
|
|
|
@ -80,6 +80,7 @@ pub fn pref_arch_to_table_language(pref_arch pref.Arch) Language {
|
|||
// Each TypeSymbol is entered into `Table.types`.
|
||||
// See also: Table.sym.
|
||||
|
||||
[minify]
|
||||
pub struct TypeSymbol {
|
||||
pub:
|
||||
parent_idx int
|
||||
|
@ -93,6 +94,8 @@ pub mut:
|
|||
is_pub bool
|
||||
language Language
|
||||
idx int
|
||||
size int = -1
|
||||
align int = -1
|
||||
}
|
||||
|
||||
// max of 8
|
||||
|
@ -825,88 +828,100 @@ pub fn (t &TypeSymbol) is_builtin() bool {
|
|||
return t.mod == 'builtin'
|
||||
}
|
||||
|
||||
// type_size returns the size in bytes of `typ`, similarly to C's `sizeof()`.
|
||||
pub fn (t &Table) type_size(typ Type) int {
|
||||
// type_size returns the size and alignment (in bytes) of `typ`, similarly to C's `sizeof()` and `alignof()`.
|
||||
pub fn (t &Table) type_size(typ Type) (int, int) {
|
||||
if typ.has_flag(.optional) {
|
||||
return t.type_size(ast.error_type_idx)
|
||||
}
|
||||
if typ.nr_muls() > 0 {
|
||||
return t.pointer_size
|
||||
return t.pointer_size, t.pointer_size
|
||||
}
|
||||
sym := t.sym(typ)
|
||||
mut sym := t.sym(typ)
|
||||
if sym.size != -1 {
|
||||
return sym.size, sym.align
|
||||
}
|
||||
mut size := 0
|
||||
mut align := 0
|
||||
match sym.kind {
|
||||
.placeholder, .void, .none_ {
|
||||
return 0
|
||||
}
|
||||
.placeholder, .void, .none_, .generic_inst {}
|
||||
.voidptr, .byteptr, .charptr, .function, .usize, .isize, .any, .thread, .chan {
|
||||
return t.pointer_size
|
||||
size = t.pointer_size
|
||||
}
|
||||
.i8, .u8, .char, .bool {
|
||||
return 1
|
||||
size = 1
|
||||
align = 1
|
||||
}
|
||||
.i16, .u16 {
|
||||
return 2
|
||||
size = 2
|
||||
align = 2
|
||||
}
|
||||
.int, .u32, .rune, .f32, .enum_ {
|
||||
return 4
|
||||
size = 4
|
||||
align = 4
|
||||
}
|
||||
.i64, .u64, .int_literal, .f64, .float_literal {
|
||||
return 8
|
||||
size = 8
|
||||
align = 8
|
||||
}
|
||||
.alias {
|
||||
return t.type_size((sym.info as Alias).parent_type)
|
||||
size, align = t.type_size((sym.info as Alias).parent_type)
|
||||
}
|
||||
.struct_, .string, .multi_return {
|
||||
mut max_alignment := 0
|
||||
mut total_size := 0
|
||||
types := if sym.info is Struct {
|
||||
types := if mut sym.info is Struct {
|
||||
sym.info.fields.map(it.typ)
|
||||
} else {
|
||||
(sym.info as MultiReturn).types
|
||||
}
|
||||
for ftyp in types {
|
||||
field_size := t.type_size(ftyp)
|
||||
alignment := if field_size > t.pointer_size { t.pointer_size } else { field_size }
|
||||
field_size, alignment := t.type_size(ftyp)
|
||||
if alignment > max_alignment {
|
||||
max_alignment = alignment
|
||||
}
|
||||
total_size = round_up(total_size, alignment) + field_size
|
||||
}
|
||||
return round_up(total_size, max_alignment)
|
||||
size = round_up(total_size, max_alignment)
|
||||
align = max_alignment
|
||||
}
|
||||
.sum_type, .interface_, .aggregate {
|
||||
match sym.info {
|
||||
match mut sym.info {
|
||||
SumType, Aggregate {
|
||||
return (sym.info.fields.len + 2) * t.pointer_size
|
||||
size = (sym.info.fields.len + 2) * t.pointer_size
|
||||
align = t.pointer_size
|
||||
}
|
||||
Interface {
|
||||
mut res := (sym.info.fields.len + 2) * t.pointer_size
|
||||
size = (sym.info.fields.len + 2) * t.pointer_size
|
||||
align = t.pointer_size
|
||||
for etyp in sym.info.embeds {
|
||||
res += t.type_size(etyp) - 2 * t.pointer_size
|
||||
esize, _ := t.type_size(etyp)
|
||||
size += esize - 2 * t.pointer_size
|
||||
}
|
||||
return res
|
||||
}
|
||||
else {
|
||||
// unreachable
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
.array_fixed {
|
||||
info := sym.info as ArrayFixed
|
||||
return info.size * t.type_size(info.elem_type)
|
||||
elem_size, elem_align := t.type_size(info.elem_type)
|
||||
size = info.size * elem_size
|
||||
align = elem_align
|
||||
}
|
||||
// TODO hardcoded:
|
||||
.map {
|
||||
return if t.pointer_size == 8 { 120 } else { 80 }
|
||||
size = if t.pointer_size == 8 { 120 } else { 80 }
|
||||
align = t.pointer_size
|
||||
}
|
||||
.array {
|
||||
return if t.pointer_size == 8 { 32 } else { 24 }
|
||||
}
|
||||
.generic_inst {
|
||||
return 0
|
||||
size = if t.pointer_size == 8 { 32 } else { 24 }
|
||||
align = t.pointer_size
|
||||
}
|
||||
}
|
||||
sym.size = size
|
||||
sym.align = align
|
||||
return size, align
|
||||
}
|
||||
|
||||
// round_up rounds the number `n` up to the next multiple `multiple`.
|
||||
|
@ -972,6 +987,7 @@ pub fn (kinds []Kind) str() string {
|
|||
return kinds_str
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Struct {
|
||||
pub:
|
||||
attrs []Attr
|
||||
|
@ -981,6 +997,7 @@ pub mut:
|
|||
is_typedef bool // C. [typedef]
|
||||
is_union bool
|
||||
is_heap bool
|
||||
is_minify bool
|
||||
is_generic bool
|
||||
generic_types []Type
|
||||
concrete_types []Type
|
||||
|
@ -994,6 +1011,7 @@ pub mut:
|
|||
concrete_types []Type // concrete types, e.g. <int, string>
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Interface {
|
||||
pub mut:
|
||||
types []Type // all types that implement this interface
|
||||
|
@ -1014,8 +1032,10 @@ pub:
|
|||
vals []string
|
||||
is_flag bool
|
||||
is_multi_allowed bool
|
||||
uses_exprs bool
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Alias {
|
||||
pub:
|
||||
parent_type Type
|
||||
|
@ -1038,6 +1058,7 @@ pub mut:
|
|||
elem_type Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct ArrayFixed {
|
||||
pub:
|
||||
size int
|
||||
|
@ -1063,6 +1084,7 @@ pub mut:
|
|||
value_type Type
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct SumType {
|
||||
pub mut:
|
||||
fields []StructField
|
||||
|
@ -1309,6 +1331,7 @@ fn (t Table) shorten_user_defined_typenames(originalname string, import_aliases
|
|||
return res
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct FnSignatureOpts {
|
||||
skip_receiver bool
|
||||
type_only bool
|
||||
|
|
|
@ -54,7 +54,7 @@ fn all_valid_comptime_idents() []string {
|
|||
return res
|
||||
}
|
||||
|
||||
[heap]
|
||||
[heap; minify]
|
||||
pub struct Checker {
|
||||
pref &pref.Preferences // Preferences shared from V struct
|
||||
pub mut:
|
||||
|
@ -644,8 +644,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
} else if is_left_type_signed != is_right_type_signed
|
||||
&& left_type != ast.int_literal_type_idx
|
||||
&& right_type != ast.int_literal_type_idx {
|
||||
ls := c.table.type_size(left_type)
|
||||
rs := c.table.type_size(right_type)
|
||||
ls, _ := c.table.type_size(left_type)
|
||||
rs, _ := c.table.type_size(right_type)
|
||||
// prevent e.g. `u32 == i16` but not `u16 == i32` as max_u16 fits in i32
|
||||
// TODO u32 == i32, change < to <=
|
||||
if (is_left_type_signed && ls < rs) || (is_right_type_signed && rs < ls) {
|
||||
|
@ -3720,6 +3720,16 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
|
|||
if node.right.op == .amp {
|
||||
c.error('unexpected `&`, expecting expression', node.right.pos)
|
||||
}
|
||||
} else if mut node.right is ast.SelectorExpr {
|
||||
right_sym := c.table.sym(right_type)
|
||||
expr_sym := c.table.sym(node.right.expr_type)
|
||||
if expr_sym.kind == .struct_ && (expr_sym.info as ast.Struct).is_minify
|
||||
&& (node.right.typ == ast.bool_type_idx || (right_sym.kind == .enum_
|
||||
&& !(right_sym.info as ast.Enum).is_flag
|
||||
&& !(right_sym.info as ast.Enum).uses_exprs)) {
|
||||
c.error('cannot take address of field in struct `${c.table.type_to_str(node.right.expr_type)}`, which is tagged as `[minify]`',
|
||||
node.pos.extend(node.right.pos))
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: testing ref/deref strategy
|
||||
|
|
|
@ -127,7 +127,8 @@ fn (mut c Checker) eval_comptime_const_expr(expr ast.Expr, nlevel int) ?ast.Comp
|
|||
// return expr.val.i64()
|
||||
// }
|
||||
ast.SizeOf {
|
||||
return c.table.type_size(expr.typ)
|
||||
s, _ := c.table.type_size(expr.typ)
|
||||
return s
|
||||
}
|
||||
ast.FloatLiteral {
|
||||
x := expr.val.f64()
|
||||
|
|
|
@ -25,6 +25,10 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if struct_sym.info.is_minify {
|
||||
node.fields.sort_with_compare(minify_sort_fn)
|
||||
struct_sym.info.fields.sort_with_compare(minify_sort_fn)
|
||||
}
|
||||
for attr in node.attrs {
|
||||
if attr.name == 'typedef' && node.language != .c {
|
||||
c.error('`typedef` attribute can only be used with C structs', node.pos)
|
||||
|
@ -124,6 +128,62 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
|||
}
|
||||
}
|
||||
|
||||
fn minify_sort_fn(a &ast.StructField, b &ast.StructField) int {
|
||||
if a.typ == b.typ {
|
||||
return 0
|
||||
}
|
||||
// push all bool fields to the end of the struct
|
||||
if a.typ == ast.bool_type_idx {
|
||||
if b.typ == ast.bool_type_idx {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
} else if b.typ == ast.bool_type_idx {
|
||||
return -1
|
||||
}
|
||||
|
||||
mut t := global_table
|
||||
a_sym := t.sym(a.typ)
|
||||
b_sym := t.sym(b.typ)
|
||||
|
||||
// push all non-flag enums to the end too, just before the bool fields
|
||||
// TODO: support enums with custom field values as well
|
||||
if a_sym.info is ast.Enum {
|
||||
if !a_sym.info.is_flag && !a_sym.info.uses_exprs {
|
||||
if b_sym.kind == .enum_ {
|
||||
a_nr_vals := (a_sym.info as ast.Enum).vals.len
|
||||
b_nr_vals := (b_sym.info as ast.Enum).vals.len
|
||||
return if a_nr_vals > b_nr_vals {
|
||||
-1
|
||||
} else if a_nr_vals < b_nr_vals {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
} else if b_sym.info is ast.Enum {
|
||||
if !b_sym.info.is_flag && !b_sym.info.uses_exprs {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
a_size, a_align := t.type_size(a.typ)
|
||||
b_size, b_align := t.type_size(b.typ)
|
||||
return if a_align > b_align {
|
||||
-1
|
||||
} else if a_align < b_align {
|
||||
1
|
||||
} else if a_size > b_size {
|
||||
-1
|
||||
} else if a_size < b_size {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
||||
if node.typ == ast.void_type {
|
||||
// short syntax `foo(key:val, key2:val2)`
|
||||
|
@ -267,6 +327,11 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||
node.pos)
|
||||
}
|
||||
}
|
||||
mut info_fields_sorted := []ast.StructField{}
|
||||
if node.is_short {
|
||||
info_fields_sorted = info.fields.clone()
|
||||
info_fields_sorted.sort(a.i < b.i)
|
||||
}
|
||||
mut inited_fields := []string{}
|
||||
for i, mut field in node.fields {
|
||||
mut field_info := ast.StructField{}
|
||||
|
@ -277,7 +342,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||
// We should just stop here.
|
||||
break
|
||||
}
|
||||
field_info = info.fields[i]
|
||||
field_info = info_fields_sorted[i]
|
||||
field_name = field_info.name
|
||||
node.fields[i].name = field_name
|
||||
} else {
|
||||
|
|
|
@ -92,6 +92,7 @@ pub fn (sk SymbolKind) str() string {
|
|||
}
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Doc {
|
||||
pub mut:
|
||||
prefs &pref.Preferences = new_vdoc_preferences()
|
||||
|
@ -121,6 +122,7 @@ pub mut:
|
|||
platform Platform
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct DocNode {
|
||||
pub mut:
|
||||
name string
|
||||
|
|
|
@ -10,6 +10,7 @@ pub enum Reporter {
|
|||
gen
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Error {
|
||||
pub:
|
||||
message string
|
||||
|
|
|
@ -16,7 +16,7 @@ pub enum CommentsLevel {
|
|||
// - level: either .keep (don't indent), or .indent (increment indentation)
|
||||
// - iembed: a /* ... */ block comment used inside expressions; // comments the whole line
|
||||
// - prev_line: the line number of the previous token to save linebreaks
|
||||
[params]
|
||||
[minify; params]
|
||||
pub struct CommentsOptions {
|
||||
has_nl bool = true
|
||||
inline bool
|
||||
|
|
|
@ -15,6 +15,7 @@ const (
|
|||
max_len = [0, 35, 60, 85, 93, 100]
|
||||
)
|
||||
|
||||
[minify]
|
||||
pub struct Fmt {
|
||||
pub mut:
|
||||
file ast.File
|
||||
|
|
|
@ -4801,6 +4801,7 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
|||
}
|
||||
}
|
||||
|
||||
is_minify := sym.info.is_minify
|
||||
g.type_definitions.writeln(pre_pragma)
|
||||
|
||||
if sym.info.is_union {
|
||||
|
@ -4835,7 +4836,26 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
|||
type_name := g.typ(field.typ)
|
||||
field_name := c_name(field.name)
|
||||
volatile_prefix := if field.is_volatile { 'volatile ' } else { '' }
|
||||
g.type_definitions.writeln('\t$volatile_prefix$type_name $field_name;')
|
||||
mut size_suffix := ''
|
||||
if is_minify && !g.is_cc_msvc {
|
||||
if field.typ == ast.bool_type_idx {
|
||||
size_suffix = ' : 1'
|
||||
} else {
|
||||
field_sym := g.table.sym(field.typ)
|
||||
if field_sym.info is ast.Enum {
|
||||
if !field_sym.info.is_flag && !field_sym.info.uses_exprs {
|
||||
mut bits_needed := 0
|
||||
mut l := field_sym.info.vals.len
|
||||
for l > 0 {
|
||||
bits_needed++
|
||||
l >>= 1
|
||||
}
|
||||
size_suffix = ' : $bits_needed'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.type_definitions.writeln('\t$volatile_prefix$type_name $field_name$size_suffix;')
|
||||
}
|
||||
} else {
|
||||
g.type_definitions.writeln('\tEMPTY_STRUCT_DECLARATION;')
|
||||
|
|
|
@ -492,7 +492,8 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
|
|||
g.indent--
|
||||
ps := g.table.pointer_size
|
||||
is_big_cutoff := if g.pref.os == .windows || g.pref.arch == .arm32 { ps } else { ps * 2 }
|
||||
is_big := g.table.type_size(node.decl.return_type) > is_big_cutoff
|
||||
rt_size, _ := g.table.type_size(node.decl.return_type)
|
||||
is_big := rt_size > is_big_cutoff
|
||||
g.write('}, sizeof($ctx_struct)))')
|
||||
|
||||
mut sb := strings.new_builder(512)
|
||||
|
|
|
@ -22,7 +22,7 @@ mut:
|
|||
// XXX WHY gen_exit fn (expr ast.Expr)
|
||||
}
|
||||
|
||||
[heap]
|
||||
[heap; minify]
|
||||
pub struct Gen {
|
||||
out_name string
|
||||
pref &pref.Preferences // Preferences shared from V struct
|
||||
|
|
|
@ -8,6 +8,7 @@ pub type FNLinkLiveSymbols = fn (linkcb voidptr)
|
|||
|
||||
pub type FNLiveReloadCB = fn (info &LiveReloadInfo)
|
||||
|
||||
[minify]
|
||||
pub struct LiveReloadInfo {
|
||||
pub:
|
||||
vexe string // full path to the v compiler
|
||||
|
|
|
@ -14,6 +14,7 @@ import v.errors
|
|||
import os
|
||||
import hash.fnv1a
|
||||
|
||||
[minify]
|
||||
pub struct Parser {
|
||||
pref &pref.Preferences
|
||||
mut:
|
||||
|
@ -3480,6 +3481,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
|||
mut vals := []string{}
|
||||
// mut default_exprs := []ast.Expr{}
|
||||
mut fields := []ast.EnumField{}
|
||||
mut uses_exprs := false
|
||||
for p.tok.kind != .eof && p.tok.kind != .rcbr {
|
||||
pos := p.tok.pos()
|
||||
val := p.check_name()
|
||||
|
@ -3491,6 +3493,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
|||
p.next()
|
||||
expr = p.expr(0)
|
||||
has_expr = true
|
||||
uses_exprs = true
|
||||
}
|
||||
fields << ast.EnumField{
|
||||
name: val
|
||||
|
@ -3538,6 +3541,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
|
|||
vals: vals
|
||||
is_flag: is_flag
|
||||
is_multi_allowed: is_multi_allowed
|
||||
uses_exprs: uses_exprs
|
||||
}
|
||||
is_pub: is_pub
|
||||
})
|
||||
|
|
|
@ -103,6 +103,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
mut end_comments := []ast.Comment{}
|
||||
if !no_body {
|
||||
p.check(.lcbr)
|
||||
mut i := 0
|
||||
for p.tok.kind != .rcbr {
|
||||
mut comments := []ast.Comment{}
|
||||
for p.tok.kind == .comment {
|
||||
|
@ -267,6 +268,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
pos: field_pos
|
||||
type_pos: type_pos
|
||||
comments: comments
|
||||
i: i
|
||||
default_expr: default_expr
|
||||
has_default_expr: has_default_expr
|
||||
attrs: p.attrs
|
||||
|
@ -283,6 +285,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
pos: field_pos
|
||||
type_pos: type_pos
|
||||
comments: comments
|
||||
i: i
|
||||
default_expr: default_expr
|
||||
has_default_expr: has_default_expr
|
||||
attrs: p.attrs
|
||||
|
@ -292,12 +295,14 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
is_volatile: is_field_volatile
|
||||
}
|
||||
p.attrs = []
|
||||
i++
|
||||
}
|
||||
p.top_level_statement_end()
|
||||
last_line = p.tok.line_nr
|
||||
p.check(.rcbr)
|
||||
}
|
||||
t := ast.TypeSymbol{
|
||||
is_minify := attrs.contains('minify')
|
||||
mut t := ast.TypeSymbol{
|
||||
kind: .struct_
|
||||
language: language
|
||||
name: name
|
||||
|
@ -309,6 +314,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
is_typedef: attrs.contains('typedef')
|
||||
is_union: is_union
|
||||
is_heap: attrs.contains('heap')
|
||||
is_minify: is_minify
|
||||
is_generic: generic_types.len > 0
|
||||
generic_types: generic_types
|
||||
attrs: attrs
|
||||
|
|
|
@ -88,7 +88,7 @@ const (
|
|||
'cflags', 'path', 'arch']
|
||||
)
|
||||
|
||||
[heap]
|
||||
[heap; minify]
|
||||
pub struct Preferences {
|
||||
pub mut:
|
||||
os OS // the OS to compile for
|
||||
|
|
|
@ -23,6 +23,7 @@ const (
|
|||
backslash = `\\`
|
||||
)
|
||||
|
||||
[minify]
|
||||
pub struct Scanner {
|
||||
pub mut:
|
||||
file_path string // '/path/to/file.v'
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module token
|
||||
|
||||
[minify]
|
||||
pub struct Token {
|
||||
pub:
|
||||
kind Kind // the token number/enum; for quick comparisons
|
||||
|
|
|
@ -22,6 +22,7 @@ pub enum ErrorType {
|
|||
trailing_space
|
||||
}
|
||||
|
||||
[minify]
|
||||
pub struct Error {
|
||||
pub mut:
|
||||
kind ErrorKind [required]
|
||||
|
|
Loading…
Reference in New Issue