summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2024-05-08 20:55:04 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2024-05-08 20:55:04 +0200
commit5478e3733810bf609a08fb172786f9d8f7c07b4e (patch)
tree21efcdbae15c931be02201c40bf86ad6b5e01928
parent453ead2a7b52ce6ffb9b90bf03c7d4d1e6f4e7a0 (diff)
downloadrebel-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.rs49
-rw-r--r--crates/rebel-lang/src/value.rs28
-rw-r--r--crates/rebel-parse/src/grammar/recipe.rs4
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(']') {