diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-05-08 20:55:04 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2024-05-08 20:55:04 +0200 |
commit | 5478e3733810bf609a08fb172786f9d8f7c07b4e (patch) | |
tree | 21efcdbae15c931be02201c40bf86ad6b5e01928 | |
parent | 453ead2a7b52ce6ffb9b90bf03c7d4d1e6f4e7a0 (diff) | |
download | rebel-5478e3733810bf609a08fb172786f9d8f7c07b4e.tar rebel-5478e3733810bf609a08fb172786f9d8f7c07b4e.zip |
rebel-parse, rebel-lang: a unit should be an empty tuple
The empty tuple becomes the representation of the unit. An empty struct
is still another way to construct a unit, but never stored as a struct.
-rw-r--r-- | crates/rebel-lang/src/typing.rs | 49 | ||||
-rw-r--r-- | crates/rebel-lang/src/value.rs | 28 | ||||
-rw-r--r-- | crates/rebel-parse/src/grammar/recipe.rs | 4 |
3 files changed, 45 insertions, 36 deletions
diff --git a/crates/rebel-lang/src/typing.rs b/crates/rebel-lang/src/typing.rs index 0af7fcb..ceb3770 100644 --- a/crates/rebel-lang/src/typing.rs +++ b/crates/rebel-lang/src/typing.rs @@ -55,7 +55,7 @@ pub enum Type { impl Type { pub fn unit() -> Self { - Type::Struct(Default::default()) + Type::Tuple(Vec::new()) } #[allow(clippy::only_used_in_recursion)] @@ -535,14 +535,19 @@ impl<'scope> Context<'scope> { )?; Type::Map(key.try_into()?, Box::new(value)) } - Literal::Struct(entries) => Struct( - entries - .iter() - .map(|expr::StructField { name, value }| { - Ok((name.as_ref().to_owned(), self.type_expr(value)?)) - }) - .collect::<Result<_>>()?, - ), + Literal::Struct(entries) => { + if entries.is_empty() { + return Ok(Type::unit()); + } + Struct( + entries + .iter() + .map(|expr::StructField { name, value }| { + Ok((name.as_ref().to_owned(), self.type_expr(value)?)) + }) + .collect::<Result<_>>()?, + ) + } }) } @@ -675,14 +680,19 @@ impl<'scope, T> TypeContext<'scope, T> { self.type_type(key)?.try_into()?, Box::new(self.type_type(value)?), ), - Literal::Struct(entries) => Struct( - entries - .iter() - .map(|typ::StructField { name, typ }| { - Ok((name.as_ref().to_owned(), self.type_type(typ)?)) - }) - .collect::<Result<_>>()?, - ), + Literal::Struct(entries) => { + if entries.is_empty() { + return Ok(Type::unit()); + } + Struct( + entries + .iter() + .map(|typ::StructField { name, typ }| { + Ok((name.as_ref().to_owned(), self.type_type(typ)?)) + }) + .collect::<Result<_>>()?, + ) + } }) } @@ -724,7 +734,7 @@ impl Display for Type { first = false; elem.fmt(f)?; } - if elems.len() < 2 { + if elems.len() == 1 { f.write_str(",")?; } f.write_str(")") @@ -732,9 +742,6 @@ impl Display for Type { Type::Array(typ) => write!(f, "[{typ}]"), Type::Map(key, value) => write!(f, "map{{{key} => {value}}}"), Type::Struct(entries) => { - if entries.is_empty() { - return f.write_str("()"); - } let mut first = true; f.write_str("{")?; for (key, typ) in entries { diff --git a/crates/rebel-lang/src/value.rs b/crates/rebel-lang/src/value.rs index e9afddc..a08a1d8 100644 --- a/crates/rebel-lang/src/value.rs +++ b/crates/rebel-lang/src/value.rs @@ -32,7 +32,7 @@ pub enum Value { impl Value { pub fn unit() -> Self { - Value::Struct(Default::default()) + Value::Tuple(Vec::new()) } pub fn typ(&self) -> Result<Type> { @@ -457,14 +457,19 @@ impl<'scope> Context<'scope> { } Map(map) } - Literal::Struct(entries) => Struct( - entries - .iter() - .map(|expr::StructField { name, value }| { - Ok((name.as_ref().to_owned(), self.eval_expr(value)?)) - }) - .collect::<Result<_>>()?, - ), + Literal::Struct(entries) => { + if entries.is_empty() { + return Ok(Value::unit()); + } + Struct( + entries + .iter() + .map(|expr::StructField { name, value }| { + Ok((name.as_ref().to_owned(), self.eval_expr(value)?)) + }) + .collect::<Result<_>>()?, + ) + } }) } @@ -562,7 +567,7 @@ impl Display for Value { first = false; elem.fmt(f)?; } - if elems.len() < 2 { + if elems.len() == 1 { f.write_str(",")?; } f.write_str(")") @@ -594,9 +599,6 @@ impl Display for Value { f.write_str("}") } Value::Struct(entries) => { - if entries.is_empty() { - return f.write_str("()"); - } let mut first = true; f.write_str("{")?; for (key, value) in entries { diff --git a/crates/rebel-parse/src/grammar/recipe.rs b/crates/rebel-parse/src/grammar/recipe.rs index 9b1b50b..f0605e4 100644 --- a/crates/rebel-parse/src/grammar/recipe.rs +++ b/crates/rebel-parse/src/grammar/recipe.rs @@ -81,7 +81,7 @@ peg::parser! { rule typ_literal() -> typ::Literal<'a> = p('(') p(')') { typ::Literal::Unit } - / p('(') elements:(typ() ** p(',')) p(',')? p(')') { + / p('(') elements:(typ() ++ p(',')) p(',')? p(')') { typ::Literal::Tuple(elements) } / p('[') typ:typ() p(']') { @@ -187,7 +187,7 @@ peg::parser! { Ok(expr::Literal::Str{ pieces, kind: *kind }) } / p('(') p(')') { expr::Literal::Unit } - / p('(') elements:(expr() ** p(',')) p(',')? p(')') { + / p('(') elements:(expr() ++ p(',')) p(',')? p(')') { expr::Literal::Tuple(elements) } / p('[') elements:delimited(<expr()>, <p(',')>) p(']') { |