summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-04-30 00:07:20 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-04-30 00:15:43 +0200
commit3d9d7fd594323d04f77c48ddc3ef2c2b6dc580b7 (patch)
tree1a5edf19a43cee9ad2543ff55521bd549536e22e
parent29ff7f69c654b5f0d3ea5a9d34ea747fab1e2d3d (diff)
downloadrebel-3d9d7fd594323d04f77c48ddc3ef2c2b6dc580b7.tar
rebel-3d9d7fd594323d04f77c48ddc3ef2c2b6dc580b7.zip
rebel-parse, rebel-lang: remove array length from types
Tuples are sufficient for fixed-length data. For arrays, the small increase in type safety is not worth the large increase in complexity - both for the typechecker, and the usage of the language. The Coerce parameter of unify() is preserved for now, as it may become useful again for other types like sets.
-rw-r--r--crates/rebel-lang/examples/repl.rs4
-rw-r--r--crates/rebel-lang/src/typing.rs91
-rw-r--r--crates/rebel-lang/src/value.rs7
-rw-r--r--crates/rebel-parse/src/ast/typ.rs9
-rw-r--r--crates/rebel-parse/src/grammar/recipe.rs15
5 files changed, 23 insertions, 103 deletions
diff --git a/crates/rebel-lang/examples/repl.rs b/crates/rebel-lang/examples/repl.rs
index f2c714b..aa3cbf8 100644
--- a/crates/rebel-lang/examples/repl.rs
+++ b/crates/rebel-lang/examples/repl.rs
@@ -1,7 +1,7 @@
use rebel_lang::{
func::{Func, FuncDef, FuncType},
scope::Context,
- typing::{ArrayLen, Type, TypeFamily},
+ typing::{Type, TypeFamily},
value::{EvalError, Result, Value},
};
use rebel_parse::{recipe, tokenize};
@@ -43,7 +43,7 @@ fn main() {
"len",
Func {
typ: FuncType {
- params: vec![Type::Array(Box::new(Type::Free), ArrayLen::Dynamic)],
+ params: vec![Type::Array(Box::new(Type::Free))],
ret: Type::Int,
},
def: Some(FuncDef::Intrinsic(intrinsic_array_len)),
diff --git a/crates/rebel-lang/src/typing.rs b/crates/rebel-lang/src/typing.rs
index aad2fb3..5eb781e 100644
--- a/crates/rebel-lang/src/typing.rs
+++ b/crates/rebel-lang/src/typing.rs
@@ -27,12 +27,13 @@ pub enum Type {
Int,
Str,
Tuple(Vec<Type>),
- Array(Box<Type>, ArrayLen),
+ Array(Box<Type>),
Struct(HashMap<String, Type>),
Fn(Box<FuncType>),
}
impl Type {
+ #[allow(clippy::only_used_in_recursion)]
pub fn unify(self, other: Type, coerce: Coerce) -> Result<Type> {
use Type::*;
@@ -55,10 +56,9 @@ impl Type {
.collect::<Result<_>>()?,
)
}
- (Array(self_inner, self_len), Array(other_inner, other_len)) => Array(
- Box::new(self_inner.unify(*other_inner, coerce)?),
- ArrayLen::unify(self_len, other_len, coerce)?,
- ),
+ (Array(self_inner), Array(other_inner)) => {
+ Array(Box::new(self_inner.unify(*other_inner, coerce)?))
+ }
(Struct(self_entries), Struct(mut other_entries)) => {
if self_entries.len() != other_entries.len() {
return Err(TypeError);
@@ -111,7 +111,7 @@ impl Type {
.map(|elem| Self::ast_type(ctx, elem))
.collect::<Result<_>>()?,
),
- Literal::Array(typ, len) => Array(Box::new(Self::ast_type(ctx, typ)?), (*len).into()),
+ Literal::Array(typ) => Array(Box::new(Self::ast_type(ctx, typ)?)),
Literal::Struct(entries) => Struct(
entries
.iter()
@@ -158,14 +158,11 @@ impl Type {
Ok(match (tl, op, tr) {
(Str, Add, Str) => Str,
(Int, Add, Int) => Int,
- (Array(t1, l1), Add, Array(t2, l2)) => Array(
- Box::new(t1.unify(*t2, Coerce::Common)?),
- ArrayLen::add(l1, l2)?,
- ),
+ (Array(t1), Add, Array(t2)) => Array(Box::new(t1.unify(*t2, Coerce::Common)?)),
(Int, Sub, Int) => Int,
- (Array(t1, _), Sub, Array(t2, _)) => {
+ (Array(t1), Sub, Array(t2)) => {
(*t1).clone().unify(*t2, Coerce::Compare)?;
- Array(t1, ArrayLen::Dynamic)
+ Array(t1)
}
(Int, Mul, Int) => Int,
(Int, Div, Int) => Int,
@@ -215,7 +212,7 @@ impl Type {
let expr_type = Self::ast_expr_type(ctx, expr)?;
let index_type = Self::ast_expr_type(ctx, index)?;
- let Array(elem_type, _) = expr_type else {
+ let Array(elem_type) = expr_type else {
return Err(TypeError);
};
if index_type != Int {
@@ -326,7 +323,7 @@ impl Type {
(Type::Int, _) => Ok(()),
(Type::Str, _) => Ok(()),
(Type::Tuple(_), expr::StrKind::Script) => Ok(()),
- (Type::Array(_, _), expr::StrKind::Script) => Ok(()),
+ (Type::Array(_), expr::StrKind::Script) => Ok(()),
_ => Err(TypeError),
}
}
@@ -351,12 +348,11 @@ impl Type {
.map(|elem| Self::ast_expr_type(ctx, elem))
.collect::<Result<_>>()?,
),
- Literal::Array(elems) => Array(
- Box::new(elems.iter().try_fold(Type::Free, |acc, elem| {
+ Literal::Array(elems) => Array(Box::new(
+ elems.iter().try_fold(Type::Free, |acc, elem| {
acc.unify(Self::ast_expr_type(ctx, elem)?, Coerce::Common)
- })?),
- ArrayLen::Fixed(elems.len().try_into().or(Err(TypeError))?),
- ),
+ })?,
+ )),
Literal::Struct(entries) => Struct(
entries
.iter()
@@ -392,7 +388,7 @@ impl Display for Type {
}
f.write_str(")")
}
- Type::Array(typ, len) => write!(f, "[{typ}{len}]"),
+ Type::Array(typ) => write!(f, "[{typ}]"),
Type::Struct(entries) => {
let mut first = true;
f.write_str("{")?;
@@ -410,58 +406,3 @@ impl Display for Type {
}
}
}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub enum ArrayLen {
- Free,
- Fixed(u32),
- Dynamic,
-}
-
-impl ArrayLen {
- fn unify(self, other: Self, coerce: Coerce) -> Result<Self> {
- use ArrayLen::*;
-
- Ok(match (self, other, coerce) {
- (Free, len, _) => len,
- (len, Free, _) => len,
- (l1, l2, _) if l1 == l2 => l1,
- (_, _, Coerce::Common) => Dynamic,
- (Dynamic, Fixed(_), Coerce::Compare | Coerce::Assign) => Dynamic,
- (Fixed(_), Dynamic, Coerce::Compare) => Dynamic,
- _ => return Err(TypeError),
- })
- }
-
- fn add(self, other: Self) -> Result<Self> {
- use ArrayLen::*;
-
- Ok(match (self, other) {
- (Free, _) => return Err(TypeError),
- (_, Free) => return Err(TypeError),
- (Dynamic, _) => Dynamic,
- (_, Dynamic) => Dynamic,
- (Fixed(l1), Fixed(l2)) => Fixed(l1 + l2),
- })
- }
-}
-
-impl From<typ::ArrayLen> for ArrayLen {
- fn from(value: typ::ArrayLen) -> Self {
- match value {
- typ::ArrayLen::Free => ArrayLen::Free,
- typ::ArrayLen::Fixed(len) => ArrayLen::Fixed(len),
- typ::ArrayLen::Dynamic => ArrayLen::Dynamic,
- }
- }
-}
-
-impl Display for ArrayLen {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- ArrayLen::Free => write!(f, "; _"),
- ArrayLen::Fixed(len) => write!(f, "; {len}"),
- ArrayLen::Dynamic => Ok(()),
- }
- }
-}
diff --git a/crates/rebel-lang/src/value.rs b/crates/rebel-lang/src/value.rs
index fe2caa2..ab21d0b 100644
--- a/crates/rebel-lang/src/value.rs
+++ b/crates/rebel-lang/src/value.rs
@@ -9,7 +9,7 @@ use rebel_parse::ast::{self, expr};
use crate::{
func::{Func, FuncDef},
scope::Context,
- typing::{self, ArrayLen, Coerce, Type, TypeError, TypeFamily},
+ typing::{self, Coerce, Type, TypeFamily},
};
#[derive(Debug)]
@@ -42,10 +42,7 @@ impl Value {
.map(|elem| elem.typ())
.collect::<typing::Result<_>>()?,
),
- Value::Array(elems) => Type::Array(
- Box::new(Self::array_elem_type(elems)?),
- ArrayLen::Fixed(elems.len().try_into().or(Err(TypeError))?),
- ),
+ Value::Array(elems) => Type::Array(Box::new(Self::array_elem_type(elems)?)),
Value::Struct(entries) => Type::Struct(
entries
.iter()
diff --git a/crates/rebel-parse/src/ast/typ.rs b/crates/rebel-parse/src/ast/typ.rs
index 18ea827..939b67d 100644
--- a/crates/rebel-parse/src/ast/typ.rs
+++ b/crates/rebel-parse/src/ast/typ.rs
@@ -11,17 +11,10 @@ pub enum Type<'a> {
pub enum Literal<'a> {
Unit,
Tuple(Vec<Type<'a>>),
- Array(Box<Type<'a>>, ArrayLen),
+ Array(Box<Type<'a>>),
Struct(Vec<StructField<'a>>),
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub enum ArrayLen {
- Free,
- Fixed(u32),
- Dynamic,
-}
-
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructField<'a> {
pub name: &'a str,
diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs
index c9fe1e2..b1ac32f 100644
--- a/crates/rebel-parse/src/grammar/recipe.rs
+++ b/crates/rebel-parse/src/grammar/recipe.rs
@@ -72,24 +72,13 @@ peg::parser! {
/ p('(') elements:(typ() ** p(',')) p(',')? p(')') {
typ::Literal::Tuple(elements)
}
- / p('[') typ:typ() len:array_len() p(']') {
- typ::Literal::Array(Box::new(typ), len)
+ / p('[') typ:typ() p(']') {
+ typ::Literal::Array(Box::new(typ))
}
/ p('{') entries:delimited(<struct_field_typ()>, <p(',')>) p('}') {
typ::Literal::Struct(entries)
}
- rule array_len() -> typ::ArrayLen
- = p(';') len:number() { ?
- Ok(typ::ArrayLen::Fixed(len.try_into().or(Err("Invalid array length"))?))
- }
- / p(';') [Token::Ident(name) if *name == "_"] {
- typ::ArrayLen::Free
- }
- / {
- typ::ArrayLen::Dynamic
- }
-
rule pat() -> Pat<'a>
= path:path() { Pat::Path(path) }