diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-30 00:07:20 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-04-30 00:15:43 +0200 |
commit | 3d9d7fd594323d04f77c48ddc3ef2c2b6dc580b7 (patch) | |
tree | 1a5edf19a43cee9ad2543ff55521bd549536e22e | |
parent | 29ff7f69c654b5f0d3ea5a9d34ea747fab1e2d3d (diff) | |
download | rebel-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.rs | 4 | ||||
-rw-r--r-- | crates/rebel-lang/src/typing.rs | 91 | ||||
-rw-r--r-- | crates/rebel-lang/src/value.rs | 7 | ||||
-rw-r--r-- | crates/rebel-parse/src/ast/typ.rs | 9 | ||||
-rw-r--r-- | crates/rebel-parse/src/grammar/recipe.rs | 15 |
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) } |