Skip to content

Commit 1917eba

Browse files
committed
improve boxed type parsing
1 parent ec5cd08 commit 1917eba

File tree

5 files changed

+125
-144
lines changed

5 files changed

+125
-144
lines changed

lib/rivet/src/ast/Type.ri

Lines changed: 107 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import std/{ traits, process, strings.Builder };
77
import ../token;
88
import ../utils;
99

10-
#[boxed; default_value(.Void)]
10+
#[boxed; default_value(+mut .Void)]
1111
pub enum Type < traits.Stringable {
1212
Basic {
1313
mut sym: ?+mut TypeSym;
1414
mut is_unresolved: bool;
1515
mut expr: +mut Expr;
16-
is_boxed: bool;
16+
pos: token.Pos;
17+
},
18+
Boxed {
19+
type: +mut Type;
1720
is_mut: bool;
1821
pos: token.Pos;
1922
},
@@ -124,23 +127,22 @@ pub enum Type < traits.Stringable {
124127
// unaliasing instead.
125128
return match self.+ {
126129
.Rawptr, .Boxedptr -> self,
127-
.Result(result) -> +mut .Result(result.inner.unalias() ?? result.inner),
128-
.Option(option) -> +mut .Option(option.inner.unalias() ?? option.inner),
130+
.Boxed(boxed) -> +mut .Boxed(boxed.type.unalias() ?? boxed.type, ...self.+),
131+
.Result(result) -> +mut .Result(result.inner.unalias() ?? result.inner, result.pos),
132+
.Option(option) -> +mut .Option(option.inner.unalias() ?? option.inner, option.pos),
129133
.Tuple(tuple_data) -> {
130134
unaliased_types := []mut +mut Type(cap: tuple_data.inners.len);
131135
for i, tuple_type in tuple_data.inners {
132136
unaliased_types[i] = tuple_type.unalias() ?? tuple_type;
133137
}
134-
// FIXME: fix concatenation bug with the previous and next expression as
135-
// a binary addition operation
136-
tmp := +mut Self.Tuple(unaliased_types, tuple_data.sym);
137-
tmp
138+
+mut Self.Tuple(unaliased_types, tuple_data.sym, ...self.+)
138139
},
139140
.Slice(slice_data) -> +mut .Slice(
140-
slice_data.inner.unalias() ?? slice_data.inner, slice_data.is_mut
141+
slice_data.inner.unalias() ?? slice_data.inner, slice_data.is_mut, ...self.+
141142
),
142143
.DynArray(dyn_array_data) -> +mut .DynArray(
143-
dyn_array_data.inner.unalias() ?? dyn_array_data.inner, dyn_array_data.is_mut
144+
dyn_array_data.inner.unalias() ?? dyn_array_data.inner, dyn_array_data.is_mut,
145+
...self.+
144146
),
145147
.Array(array_data) -> +mut .Array(
146148
array_data.inner.unalias() ?? array_data.inner, ...self.+
@@ -152,13 +154,10 @@ pub enum Type < traits.Stringable {
152154
for arg in func_data.args {
153155
arg.type = arg.type.unalias() ?? arg.type;
154156
}
155-
// FIXME: fix concatenation bug with the previous and next expression as
156-
// a binary addition operation
157-
tmp := +mut Self.Func(
157+
+mut Self.Func(
158158
ret_type: func_data.ret_type.unalias() ?? func_data.ret_type,
159159
...self.+
160-
);
161-
tmp
160+
)
162161
},
163162
.Basic(basic) if !basic.is_unresolved -> if basic.sym?.info is .Alias(alias_info) {
164163
alias_info.parent.unalias() ?? alias_info.parent
@@ -182,6 +181,7 @@ pub enum Type < traits.Stringable {
182181
return match self.+ {
183182
.Result(result) -> result.inner.symbol(),
184183
.Option(option) -> option.inner.symbol(),
184+
.Boxed(boxed) -> boxed.type.symbol(),
185185
.Tuple(tuple_data) -> tuple_data.sym,
186186
.Variadic(variadic_data) -> variadic_data.sym,
187187
.Slice(slice_data) -> slice_data.sym,
@@ -205,11 +205,7 @@ pub enum Type < traits.Stringable {
205205

206206
#[inline]
207207
pub func is_boxed(+self) -> bool {
208-
return if type_sym := self.symbol() {
209-
type_sym.is_boxed()
210-
} else {
211-
false
212-
};
208+
return self is .Boxed;
213209
}
214210

215211
#[inline]
@@ -238,12 +234,8 @@ pub enum Type < traits.Stringable {
238234
#[inline]
239235
pub func is_any_kind_of_pointer(+self) -> bool {
240236
return match self.+ {
241-
.Pointer, .Rawptr, .Boxedptr, .Func -> true,
242-
else -> if type_sym := self.symbol() {
243-
type_sym.is_boxed()
244-
} else {
245-
false
246-
}
237+
.Pointer, .Rawptr, .Boxedptr, .Func, .Boxed -> true,
238+
else -> false
247239
};
248240
}
249241

@@ -252,6 +244,7 @@ pub enum Type < traits.Stringable {
252244
return match self.+ {
253245
.Void, .None -> token.no_pos,
254246
.Never(never_pos) -> never_pos,
247+
.Boxed(boxed) -> boxed.pos,
255248
.Option(opt_t) -> opt_t.pos,
256249
.Result(res_t) -> res_t.pos,
257250
.Tuple(tuple_t) -> tuple_t.pos,
@@ -277,6 +270,7 @@ pub enum Type < traits.Stringable {
277270
.None if rhs is .None -> true,
278271
.Void if rhs is .Void -> true,
279272
.Never if rhs is .Never -> true,
273+
.Boxed(boxed_lhs) if rhs is .Boxed(boxed_rhs) -> boxed_lhs.type == boxed_rhs.type,
280274
.Result(result_lhs) if rhs is .Result(result_rhs) ->
281275
result_lhs.inner == result_rhs.inner,
282276
.Option(option_lhs) if rhs is .Option(option_rhs) ->
@@ -324,9 +318,7 @@ pub enum Type < traits.Stringable {
324318
},
325319
.Basic(basic_lhs) if rhs is .Basic(basic_rhs) ->
326320
!(basic_lhs.is_unresolved && basic_rhs.is_unresolved)
327-
&& basic_lhs.sym? == basic_rhs.sym?
328-
&& basic_lhs.is_boxed == basic_rhs.is_boxed
329-
&& basic_lhs.is_mut == basic_rhs.is_mut,
321+
&& basic_lhs.sym? == basic_rhs.sym?,
330322
else -> false
331323
};
332324
}
@@ -348,6 +340,11 @@ pub enum Type < traits.Stringable {
348340
.None -> "<none>",
349341
.Void -> "<void>",
350342
.Never -> "never",
343+
.Boxed(boxed) -> if boxed.is_mut {
344+
"+mut ".concat(boxed.type.to_string())
345+
} else {
346+
"+".concat(boxed.type.to_string())
347+
},
351348
.Result(result) -> if result.inner is .Void {
352349
"!"
353350
} else {
@@ -434,12 +431,6 @@ pub enum Type < traits.Stringable {
434431
},
435432
.Basic(basic) -> {
436433
mut sb := Builder.new(150);
437-
if basic.is_boxed {
438-
sb.write("+");
439-
if basic.is_mut {
440-
sb.write("mut ");
441-
}
442-
}
443434
sb.write(if type_sym := basic.sym {
444435
if qualstr {
445436
type_sym.qualname()
@@ -539,8 +530,12 @@ extend Env {
539530
pub func type_size(+mut self, type: +mut Type, is_raw: bool := false) -> (uint, uint) {
540531
return match type.+ {
541532
.Result, .Option -> self.type_symbol_size(self.throwable_sym, is_raw),
542-
.Rawptr, .Boxedptr, .Pointer, .Func -> (self.pointer_size, self.pointer_size),
543-
.Basic(basic_t) if basic_t.is_boxed && !is_raw -> (self.pointer_size, self.pointer_size),
533+
.Rawptr, .Boxedptr, .Pointer, .Func, .Boxed -> (self.pointer_size, self.pointer_size),
534+
.Boxed(boxed) -> if is_raw {
535+
(self.pointer_size, self.pointer_size)
536+
} else {
537+
self.type_size(boxed.type, is_raw)
538+
},
544539
else -> if type_sym := type.symbol() {
545540
self.type_symbol_size(type_sym, is_raw)
546541
} else {
@@ -554,94 +549,86 @@ extend Env {
554549
(type_sym.size, type_sym.align)
555550
} else {
556551
(mut size: uint, mut align: uint) := (0, 0);
557-
(size, align) = if type_sym.is_boxed() && !is_raw {
558-
(self.pointer_size, self.pointer_size)
559-
} else {
560-
match type_sym.info.+ {
561-
.Func -> (self.pointer_size, self.pointer_size),
562-
.Alias(alias_info) -> self.type_size(alias_info.parent),
563-
.Bool -> (1, 1),
564-
.Uint, .Int -> (self.pointer_size, self.pointer_size),
565-
.SizedInt(int_) -> match int_.size {
566-
8 -> (1, 1),
567-
16 -> (2, 2),
568-
32 -> (4, 4),
569-
64 -> (8, 8),
570-
else -> (0, 0)
571-
},
572-
.SizedUint(uint_) -> match uint_.size {
573-
8 -> (1, 1),
574-
16 -> (2, 2),
575-
32 -> (4, 4),
576-
64 -> (8, 8),
577-
else -> (0, 0)
578-
},
579-
.Float(float) -> match float.size {
580-
32 -> (4, 4),
581-
64 -> (8, 8),
582-
else -> (0, 0)
583-
},
584-
.Rune -> (4, 4),
585-
.ComptimeFloat, .ComptimeInt -> (8, 8),
586-
.Enum(enum_info) -> if enum_info.is_tagged {
587-
if enum_info.is_boxed {
588-
((type_sym.fields.len + 2) * self.pointer_size, self.pointer_size)
589-
} else {
590-
mut total_size := self.pointer_size;
591-
mut max_alignment := self.pointer_size;
592-
for variant in enum_info.variants {
593-
if variant.has_type {
594-
(variant_size, alignment) := self.type_size(variant.type);
595-
if alignment > max_alignment {
596-
max_alignment = alignment;
597-
}
598-
total_size = utils.round_up(total_size, alignment) + variant_size;
599-
}
600-
}
601-
(utils.round_up(total_size, max_alignment), max_alignment)
602-
}
603-
} else {
604-
self.type_size(enum_info.underlying_type)
605-
},
606-
.Slice -> (self.pointer_size * 3, self.pointer_size),
607-
.DynArray -> self.type_symbol_size(self.dyn_array_sym, is_raw),
608-
.Array(array_info) -> {
609-
(elem_size, elem_align) := self.type_size(array_info.elem_type);
610-
(array_info.size * elem_size, elem_align)
611-
},
612-
.Struct, .Tuple -> {
613-
mut total_size: uint := 0;
614-
mut max_alignment: uint := 0;
615-
types := if type_sym.info is .Tuple(tuple_lit) {
616-
tuple_lit.types
617-
} else {
618-
mut tmp := []+mut Type();
619-
for field in type_sym.full_fields() {
620-
tmp.push(field.type);
621-
}
622-
tmp
623-
};
624-
for ftype in types {
625-
(field_size, alignment) := self.type_size(ftype);
552+
(size, align) = match type_sym.info.+ {
553+
.Func -> (self.pointer_size, self.pointer_size),
554+
.Alias(alias_info) -> self.type_size(alias_info.parent),
555+
.Bool -> (1, 1),
556+
.Uint, .Int -> (self.pointer_size, self.pointer_size),
557+
.SizedInt(int_) -> match int_.size {
558+
8 -> (1, 1),
559+
16 -> (2, 2),
560+
32 -> (4, 4),
561+
64 -> (8, 8),
562+
else -> (0, 0)
563+
},
564+
.SizedUint(uint_) -> match uint_.size {
565+
8 -> (1, 1),
566+
16 -> (2, 2),
567+
32 -> (4, 4),
568+
64 -> (8, 8),
569+
else -> (0, 0)
570+
},
571+
.Float(float) -> match float.size {
572+
32 -> (4, 4),
573+
64 -> (8, 8),
574+
else -> (0, 0)
575+
},
576+
.Rune -> (4, 4),
577+
.ComptimeFloat, .ComptimeInt -> (8, 8),
578+
.Enum(enum_info) -> if enum_info.is_tagged {
579+
mut total_size := self.pointer_size;
580+
mut max_alignment := self.pointer_size;
581+
for variant in enum_info.variants {
582+
if variant.has_type {
583+
(variant_size, alignment) := self.type_size(variant.type);
626584
if alignment > max_alignment {
627585
max_alignment = alignment;
628586
}
629-
total_size = utils.round_up(total_size, alignment) + field_size;
587+
total_size = utils.round_up(total_size, alignment) + variant_size;
630588
}
631-
(utils.round_up(total_size, max_alignment), max_alignment)
632-
},
633-
.Trait(trait_info) -> {
634-
(size, align) = ((type_sym.fields.len + 2) * self.pointer_size, self.pointer_size);
635-
for btype in trait_info.bases {
636-
(bsize, _balign) := self.type_symbol_size(btype, is_raw);
637-
size += bsize - 2 * self.pointer_size;
589+
}
590+
(utils.round_up(total_size, max_alignment), max_alignment)
591+
} else {
592+
self.type_size(enum_info.underlying_type)
593+
},
594+
.Slice -> (self.pointer_size * 3, self.pointer_size),
595+
.DynArray -> self.type_symbol_size(self.dyn_array_sym, is_raw),
596+
.Array(array_info) -> {
597+
(elem_size, elem_align) := self.type_size(array_info.elem_type);
598+
(array_info.size * elem_size, elem_align)
599+
},
600+
.Struct, .Tuple -> {
601+
mut total_size: uint := 0;
602+
mut max_alignment: uint := 0;
603+
types := if type_sym.info is .Tuple(tuple_lit) {
604+
tuple_lit.types
605+
} else {
606+
mut tmp := []+mut Type();
607+
for field in type_sym.full_fields() {
608+
tmp.push(field.type);
638609
}
639-
(size, align)
640-
},
641-
else -> process.panic(
642-
"Env.type_size: unsupported type `{}`", type_sym.qualname()
643-
)
644-
}
610+
tmp
611+
};
612+
for ftype in types {
613+
(field_size, alignment) := self.type_size(ftype);
614+
if alignment > max_alignment {
615+
max_alignment = alignment;
616+
}
617+
total_size = utils.round_up(total_size, alignment) + field_size;
618+
}
619+
(utils.round_up(total_size, max_alignment), max_alignment)
620+
},
621+
.Trait(trait_info) -> {
622+
(size, align) = ((type_sym.fields.len + 2) * self.pointer_size, self.pointer_size);
623+
for btype in trait_info.bases {
624+
(bsize, _balign) := self.type_symbol_size(btype, is_raw);
625+
size += bsize - 2 * self.pointer_size;
626+
}
627+
(size, align)
628+
},
629+
else -> process.panic(
630+
"Env.type_size: unsupported type `{}`", type_sym.qualname()
631+
)
645632
};
646633
type_sym.size = size;
647634
type_sym.align = align;

lib/rivet/src/checker/exprs.ri

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -588,9 +588,7 @@ extend Checker {
588588
unary.pos
589589
);
590590
},
591-
.Plus -> if unary.type is .Basic(basic_t) {
592-
unary.type = +mut .Basic(basic_t.sym, is_boxed: true, is_mut: unary.is_mut_ptr, pos: basic_t.pos);
593-
},
591+
.Plus -> unary.type = +mut .Boxed(unary.type, unary.is_mut_ptr, unary.type.position()),
594592
.Amp -> {
595593
mut expected_pointer := false;
596594
mut indexable_pointer := false;

lib/rivet/src/checker/mutability.ri

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ extend Checker {
2828
"cannot use a immutable pointer as mutable value", selector.pos
2929
);
3030
}
31-
} else if selector.left_type is .Basic(basic_t) && basic_t.is_boxed {
32-
if !basic_t.is_mut {
31+
} else if selector.left_type is .Boxed(boxed_t) {
32+
if !boxed_t.is_mut {
3333
report.error(
3434
"cannot use a immutable boxed value as mutable value", selector.pos
3535
);
@@ -76,8 +76,8 @@ extend Checker {
7676
"cannot modify elements of an immutable pointer", index.pos
7777
);
7878
}
79-
} else if index.left_type is .Basic(basic_t) && basic_t.is_boxed {
80-
if !basic_t.is_mut {
79+
} else if index.left_type is .Boxed(boxed_t) {
80+
if !boxed_t.is_mut {
8181
report.error(
8282
"cannot use a immutable boxed value as mutable value", index.pos
8383
);

0 commit comments

Comments
 (0)