Skip to content

Commit

Permalink
self-host: support slice types
Browse files Browse the repository at this point in the history
  • Loading branch information
StunxFS committed Dec 25, 2023
1 parent dc5740b commit ec2e007
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 30 deletions.
36 changes: 34 additions & 2 deletions lib/rivet/src/ast/Sym.ri
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// file.

import std/traits;
Expand Down Expand Up @@ -150,6 +150,38 @@ pub struct SymRef < Sym {

#[boxed]
pub struct Module < Sym {
pub func add_or_get_slice(mut self, elem_type: Type, is_mut: bool) -> TypeSym {
unique_name := if is_mut { "[:]mut " } else { "[:]" }.concat(elem_type.to_qualstring());
if type_sym := self.scope.find(unique_name) {
return @as(TypeSym, type_sym);
}
mut type_sym := TypeSym(
is_public: true,
name: unique_name,
info: .DynArray(elem_type, is_mut),
fields: +[
Field(
name: "len", is_public: true,
type: .Basic(self.scope.find_type_symbol_by_index_or_panic(11))
)
]
);
type_sym.scope.add(Func(
name: "to_dynamic_array",
is_public: true,
is_method: true,
self_is_ptr: true,
self_type: .Basic(type_sym),
ret_type: .Basic(self.add_or_get_dyn_array(elem_type, is_mut)),
has_body: true
)) catch {};
if slice_sym := self.scope.find("core")?.scope.find("Slice") {
type_sym.scope.add(slice_sym.scope.find("is_empty")?) catch {};
}
self.scope.add(type_sym) catch {};
return type_sym;
}

pub func add_or_get_array(mut self, elem_typ: Type, size: uint, is_mut: bool) -> TypeSym {
unique_name := if is_mut {
"[{}]mut {}"
Expand Down
23 changes: 21 additions & 2 deletions lib/rivet/src/ast/Type.ri
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// file.

import std/traits;
Expand Down Expand Up @@ -51,6 +51,12 @@ pub enum Type < traits.Stringable {
mut sym: TypeSym;
pos: token.Pos;
},
Slice {
mut inner: Type;
is_mut: bool;
mut sym: TypeSym;
pos: token.Pos;
},
DynArray {
mut inner: Type;
is_mut: bool;
Expand Down Expand Up @@ -124,6 +130,9 @@ pub enum Type < traits.Stringable {
}
.Tuple(unaliased_types, tuple_data.sym)
},
.Slice(mut slice_data) -> .Slice(
slice_data.inner.unalias() ?? slice_data.inner, slice_data.is_mut
),
.DynArray(mut dyn_array_data) -> .DynArray(
dyn_array_data.inner.unalias() ?? dyn_array_data.inner, dyn_array_data.is_mut
),
Expand Down Expand Up @@ -167,6 +176,7 @@ pub enum Type < traits.Stringable {
.Option(option) -> option.inner.symbol(),
.Tuple(tuple_data) -> tuple_data.sym,
.Variadic(variadic_data) -> variadic_data.sym,
.Slice(slice_data) -> slice_data.sym,
.DynArray(dyn_array_data) -> dyn_array_data.sym,
.Array(array_data) -> array_data.sym,
.Pointer(pointer_data) -> pointer_data.inner.symbol(),
Expand Down Expand Up @@ -238,6 +248,7 @@ pub enum Type < traits.Stringable {
.Result(res_t) -> res_t.pos,
.Tuple(tuple_t) -> tuple_t.pos,
.Variadic(variadic_t) -> variadic_t.pos,
.Slice(slice_t) -> slice_t.pos,
.DynArray(dyn_array_t) -> dyn_array_t.pos,
.Array(arr_t) -> arr_t.pos,
.Pointer(ptr_t) -> ptr_t.pos,
Expand All @@ -264,6 +275,8 @@ pub enum Type < traits.Stringable {
.Tuple(tuple_lhs) if rhs is .Tuple(tuple_rhs) -> tuple_lhs == tuple_rhs,
.Variadic(variadic_lhs) if rhs is .Variadic(variadic_rhs) ->
variadic_lhs.inner == variadic_rhs.inner,
.Slice(slice_lhs) if rhs is .Slice(slice_rhs) ->
slice_lhs.inner == slice_rhs.inner && slice_lhs.is_mut == slice_rhs.is_mut,
.DynArray(dyn_array_lhs) if rhs is .DynArray(dyn_array_rhs) ->
dyn_array_lhs.inner == dyn_array_rhs.inner && dyn_array_lhs.is_mut == dyn_array_rhs.is_mut,
.Array(array_lhs) if rhs is .Array(array_rhs) ->
Expand Down Expand Up @@ -346,6 +359,11 @@ pub enum Type < traits.Stringable {
sb.to_string()
},
.Variadic(variadic_data) -> "...".concat(variadic_data.inner.to_string_(qualstr)),
.Slice(slice_data) -> if slice_data.is_mut {
"[:]mut"
} else {
"[:]"
}.concat(slice_data.inner.to_string_(qualstr)),
.DynArray(dyn_array_data) -> if dyn_array_data.is_mut {
"[]mut"
} else {
Expand Down Expand Up @@ -561,6 +579,7 @@ extend Env {
} else {
self.type_size(enum_info.underlying_type)
},
.Slice -> (self.pointer_size * 3, self.pointer_size),
.DynArray -> self.type_symbol_size(self.dyn_array_sym, is_raw),
.Array(array_info) -> {
(elem_size, elem_align) := self.type_size(array_info.elem_type);
Expand Down
29 changes: 18 additions & 11 deletions lib/rivet/src/ast/TypeInfo.ri
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// file.

import std/traits;

pub struct EnumVariant {
pub name: string;
pub value: int;
pub has_type: bool;
pub mut type: Type;
pub has_fields: bool;
}

pub enum TypeInfo < traits.Stringable {
Invalid,
Placeholder,
Expand Down Expand Up @@ -34,6 +42,11 @@ pub enum TypeInfo < traits.Stringable {
is_mut: bool;
has_contains_method: bool;
},
Slice {
elem_type: Type;
is_mut: bool;
has_contains_method: bool;
},
DynArray {
elem_type: Type;
is_mut: bool;
Expand Down Expand Up @@ -141,8 +154,9 @@ pub enum TypeInfo < traits.Stringable {
}

#[inline]
pub func is_mut_arr_or_dyn_array(self) -> bool {
pub func is_mut_array(self) -> bool {
return match self {
.Slice(slice) -> slice.is_mut,
.Array(arr) -> arr.is_mut,
.DynArray(vec) -> vec.is_mut,
else -> false
Expand Down Expand Up @@ -179,6 +193,7 @@ pub enum TypeInfo < traits.Stringable {
.String -> "string",
.Func -> "func",
.Alias -> "alias",
.Slice -> "slice",
.Array -> "array",
.DynArray -> "dynamic array",
.Tuple -> "tuple",
Expand All @@ -192,11 +207,3 @@ pub enum TypeInfo < traits.Stringable {
};
}
}

pub struct EnumVariant {
pub name: string;
pub value: int;
pub has_type: bool;
pub mut type: Type;
pub has_fields: bool;
}
12 changes: 6 additions & 6 deletions lib/rivet/src/checker/exprs.ri
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ extend Checker {
if value_sym.info is .Array(array_info) {
size = array_info.size;
}
is_mut = value_sym.info.is_mut_arr_or_dyn_array();
is_mut = value_sym.info.is_mut_array();
} else if !self.expected_type.is_void() {
has_expected_type = true;
value_type = self.expected_type;
Expand Down Expand Up @@ -512,16 +512,16 @@ extend Checker {
);
}
index.type = match left_sym.info {
.Array, .DynArray -> {
.Array, .DynArray, .Slice -> {
elem_type := left_sym.info.elem_type()?;
if index.index is .Range {
is_mut := left_sym.info.is_mut_arr_or_dyn_array();
if left_sym.info is .DynArray {
is_mut := left_sym.info.is_mut_array();
if left_sym.info is .Slice {
index.left_type
} else {
.DynArray(
.Slice(
elem_type, is_mut,
self.env.universe.add_or_get_dyn_array(elem_type, is_mut)
self.env.universe.add_or_get_slice(elem_type, is_mut)
)
}
} else {
Expand Down
2 changes: 1 addition & 1 deletion lib/rivet/src/checker/mod.ri
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ pub struct Checker {
}
self.check_expr_is_mut(index.left);
expr_sym := index.left_type.symbol()?;
if !expr_sym.info.is_mut_arr_or_dyn_array() {
if !expr_sym.info.is_mut_array() {
report.error(
"cannot modify elements of an immutable {}".fmt(expr_sym.info),
index.pos
Expand Down
2 changes: 1 addition & 1 deletion lib/rivet/src/checker/stmts.ri
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ extend Checker {
if for_stmt.values.len == 1 {
value0 := for_stmt.values[0];
if value0.is_mut {
if !iterable_sym.info.is_mut_arr_or_dyn_array() {
if !iterable_sym.info.is_mut_array() {
report.error(
"cannot modify immutable {}".fmt(iterable_sym.info),
for_stmt.iterable.position()
Expand Down
10 changes: 8 additions & 2 deletions lib/rivet/src/checker/types.ri
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// file.

import ../ast;
Expand Down Expand Up @@ -155,6 +155,12 @@ extend Checker {
return true;
}
},
.Slice(slice_lhs) if got_sym.info is .Slice(slice_rhs) -> {
if slice_lhs.is_mut && !slice_rhs.is_mut {
return false;
}
return slice_lhs.elem_type == slice_rhs.elem_type;
},
.Array(array_info) if got_sym.info is .Array(array_info2) -> {
if array_info.is_mut && !array_info2.is_mut {
return false;
Expand Down
11 changes: 8 additions & 3 deletions lib/rivet/src/parser/types.ri
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// file.

import ../ast;
Expand Down Expand Up @@ -55,13 +55,18 @@ extend Parser {
self.accept(.Lbracket) -> {
// arrays or dynamic arrays
if self.tok.kind != .Rbracket {
// indexable pointers
if self.accept(.Amp) {
// indexable pointers
self.expect(.Rbracket);
is_mut := self.accept(.KwMut);
.Pointer(
self.parse_type(), is_mut, true, pos: pos + self.prev_tok.pos
)
} else if self.accept(.Colon) {
// slice
self.expect(.Rbracket);
is_mut := self.accept(.KwMut);
.Slice(self.parse_type(), is_mut, pos: pos + self.prev_tok.pos)
} else {
// array
size := self.parse_expr();
Expand Down
10 changes: 8 additions & 2 deletions lib/rivet/src/resolver/types.ri
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// Copyright (C) 2023-present Jose Mendoza - All rights reserved. Use of this
// source code is governed by an MIT license that can be found in the LICENSE
// file.

import ../ast;
Expand All @@ -21,6 +21,12 @@ extend Resolver {
} else {
false
},
.Slice(mut slice) -> if self.resolve_type(slice.inner) {
slice.sym = self.env.universe.add_or_get_slice(slice.inner, slice.is_mut);
true
} else {
false
},
.DynArray(mut dyn_arr) -> if self.resolve_type(dyn_arr.inner) {
dyn_arr.sym = self.env.universe.add_or_get_dyn_array(dyn_arr.inner, dyn_arr.is_mut);
true
Expand Down

0 comments on commit ec2e007

Please sign in to comment.