From f35afe8d65b48ece5b4336321893d739bd059123 Mon Sep 17 00:00:00 2001 From: microproofs Date: Fri, 16 Aug 2024 22:04:20 -0400 Subject: [PATCH] Implement SimpleExpr logic for configuration parsing We can now use boolean, lists & all in configuration. --- crates/aiken-lang/src/ast.rs | 13 +++++ crates/aiken-project/src/config.rs | 77 ++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index a76ab0f7..57fa6014 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -1259,6 +1259,19 @@ impl Annotation { } } + pub fn list(inner: Annotation, location: Span) -> Self { + Annotation::Constructor { + name: "List".to_string(), + module: None, + arguments: vec![inner], + location, + } + } + + pub fn tuple(elems: Vec, location: Span) -> Self { + Annotation::Tuple { elems, location } + } + pub fn is_logically_equal(&self, other: &Annotation) -> bool { match self { Annotation::Constructor { diff --git a/crates/aiken-project/src/config.rs b/crates/aiken-project/src/config.rs index bbd6bca9..03f8487b 100644 --- a/crates/aiken-project/src/config.rs +++ b/crates/aiken-project/src/config.rs @@ -45,7 +45,7 @@ pub enum SimpleExpr { } impl SimpleExpr { - pub fn as_untyped_expr(&self) -> UntypedExpr { + pub fn as_untyped_expr(&self, annotation: &Annotation) -> UntypedExpr { match self { SimpleExpr::Bool(b) => UntypedExpr::Var { location: Span::empty(), @@ -63,38 +63,73 @@ impl SimpleExpr { bytes: bs.to_vec(), preferred_format: *preferred_format, }, - SimpleExpr::List(es) => UntypedExpr::List { - location: Span::empty(), - elements: es.iter().map(|e| e.as_untyped_expr()).collect(), - tail: None, + SimpleExpr::List(es) => match annotation { + Annotation::Tuple { elems, .. } => UntypedExpr::Tuple { + location: Span::empty(), + elems: es + .iter() + .zip(elems) + .map(|(e, ann)| e.as_untyped_expr(ann)) + .collect(), + }, + Annotation::Constructor { + module, + name, + arguments, + .. + } if name == "List" && module.is_none() => UntypedExpr::List { + location: Span::empty(), + elements: es + .iter() + .map(|e| e.as_untyped_expr(arguments.first().unwrap())) + .collect(), + tail: None, + }, + _ => unreachable!( + "unexpected annotation for simple list expression: {annotation:#?}" + ), }, } } - pub fn as_definition(&self, identifier: &str) -> UntypedDefinition { + pub fn as_annotation(&self) -> Annotation { let location = Span::empty(); + match self { + SimpleExpr::Bool(..) => Annotation::boolean(location), + SimpleExpr::Int(_) => Annotation::int(location), + SimpleExpr::ByteArray(_, _) => Annotation::bytearray(location), + SimpleExpr::List(elems) => { + let elems = elems.iter().map(|e| e.as_annotation()).collect::>(); - let (value, annotation) = match self { - SimpleExpr::Bool(..) => todo!("requires https://github.com/aiken-lang/aiken/pull/992"), - SimpleExpr::Int(_) => ( - // TODO: Replace with 'self.as_untyped_expr()' after https://github.com/aiken-lang/aiken/pull/992 - self.as_untyped_expr(), - Some(Annotation::int(location)), - ), - SimpleExpr::ByteArray(_, _) => ( - // TODO: Replace with 'self.as_untyped_expr()' after https://github.com/aiken-lang/aiken/pull/992 - self.as_untyped_expr(), - Some(Annotation::bytearray(location)), - ), - SimpleExpr::List(..) => todo!("requires https://github.com/aiken-lang/aiken/pull/992"), - }; + let (is_uniform, inner) = + elems + .iter() + .fold((true, None), |(matches, ann), a| match ann { + None => (matches, Some(a)), + Some(b) => (matches && a == b, ann), + }); + if is_uniform { + Annotation::list( + inner.cloned().unwrap_or_else(|| Annotation::data(location)), + location, + ) + } else { + Annotation::tuple(elems, location) + } + } + } + } + + pub fn as_definition(&self, identifier: &str) -> UntypedDefinition { + let annotation = self.as_annotation(); + let value = self.as_untyped_expr(&annotation); UntypedDefinition::ModuleConstant(ModuleConstant { location: Span::empty(), doc: None, public: true, name: identifier.to_string(), - annotation, + annotation: Some(annotation), value, }) }