From 9c66ff66ed991b35f2bc5d56172f9040a43992da Mon Sep 17 00:00:00 2001 From: kuviman Date: Tue, 3 Dec 2024 14:00:22 +0400 Subject: [PATCH] and/or --- src/compiler.rs | 62 ++++++++++++++++++++++++++++++++++++++++++++++ src/interpreter.rs | 18 ++++++++++++++ src/ir.rs | 18 ++++++++++++++ std/syntax.ks | 4 +-- 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index a68a348..ab4a2ec 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -169,6 +169,8 @@ impl Cache { macro_list, macro_mutable_pattern, macro_assign, + macro_and, + macro_or, ); Self { builtin_macros, @@ -1585,6 +1587,34 @@ impl Kast { kast.compiler.bindings_mutable = true; kast.compile_into(cty, pattern).await } + async fn macro_or(&mut self, cty: CompiledType, ast: &Ast) -> eyre::Result { + assert_eq!(cty, CompiledType::Expr); + let (values, span) = get_complex(ast); + let [lhs, rhs] = values.as_ref().into_named(["lhs", "rhs"])?; + Ok(Compiled::Expr( + Expr::Or { + lhs: Box::new(self.compile(lhs).await?), + rhs: Box::new(self.compile(rhs).await?), + data: span, + } + .init(self) + .await?, + )) + } + async fn macro_and(&mut self, cty: CompiledType, ast: &Ast) -> eyre::Result { + assert_eq!(cty, CompiledType::Expr); + let (values, span) = get_complex(ast); + let [lhs, rhs] = values.as_ref().into_named(["lhs", "rhs"])?; + Ok(Compiled::Expr( + Expr::And { + lhs: Box::new(self.compile(lhs).await?), + rhs: Box::new(self.compile(rhs).await?), + data: span, + } + .init(self) + .await?, + )) + } async fn macro_assign(&mut self, cty: CompiledType, ast: &Ast) -> eyre::Result { assert_eq!(cty, CompiledType::Expr); let (values, span) = get_complex(ast); @@ -1735,6 +1765,38 @@ impl Expr { pub fn init(self, kast: &Kast) -> BoxFuture<'_, eyre::Result> { let r#impl = async { Ok(match self { + Expr::And { + lhs, + rhs, + data: span, + } => { + lhs.data().ty.expect_inferred(TypeShape::Bool)?; + rhs.data().ty.expect_inferred(TypeShape::Bool)?; + Expr::And { + lhs, + rhs, + data: ExprData { + ty: TypeShape::Bool.into(), + span, + }, + } + } + Expr::Or { + lhs, + rhs, + data: span, + } => { + lhs.data().ty.expect_inferred(TypeShape::Bool)?; + rhs.data().ty.expect_inferred(TypeShape::Bool)?; + Expr::Or { + lhs, + rhs, + data: ExprData { + ty: TypeShape::Bool.into(), + span, + }, + } + } Expr::Assign { pattern, value, diff --git a/src/interpreter.rs b/src/interpreter.rs index 5dd2ab8..e637bb7 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -643,6 +643,22 @@ impl Kast { tracing::trace!("as {expected_ty}"); let r#impl = async move { let result = match expr { + Expr::And { lhs, rhs, data: _ } => { + let lhs = self.eval(lhs).await?.expect_bool()?; + if lhs { + self.eval(rhs).await? + } else { + Value::Bool(false) + } + } + Expr::Or { lhs, rhs, data: _ } => { + let lhs = self.eval(lhs).await?.expect_bool()?; + if !lhs { + self.eval(rhs).await? + } else { + Value::Bool(true) + } + } Expr::List { values: values_exprs, data, @@ -1086,6 +1102,8 @@ impl Kast { }; let should_check_result_ty = match expr { Expr::Unit { .. } + | Expr::And { .. } + | Expr::Or { .. } | Expr::List { .. } | Expr::Unwind { .. } | Expr::Unwindable { .. } diff --git a/src/ir.rs b/src/ir.rs index a30d6ac..e8bdd00 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -14,6 +14,16 @@ pub struct MatchBranch { #[derive(Clone)] pub enum Expr { + And { + lhs: Box, + rhs: Box, + data: Data, + }, + Or { + lhs: Box, + rhs: Box, + data: Data, + }, Assign { pattern: Pattern, value: Box, @@ -180,6 +190,8 @@ impl Expr { ) { match self { Expr::Binding { .. } + | Expr::And { .. } + | Expr::Or { .. } | Expr::List { .. } | Expr::Assign { .. } | Expr::Unwind { .. } @@ -251,6 +263,8 @@ impl> Expr { impl> std::fmt::Display for Show<'_, Data> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.0 { + Expr::And { .. } => write!(f, "and expr")?, + Expr::Or { .. } => write!(f, "or expr")?, Expr::Assign { .. } => write!(f, "assign expr")?, Expr::Unwind { .. } => write!(f, "unwind expr")?, Expr::List { .. } => write!(f, "list expr")?, @@ -296,6 +310,8 @@ impl> Expr { impl Expr { pub fn data(&self) -> &Data { let (Expr::Binding { data, .. } + | Expr::And { data, .. } + | Expr::Or { data, .. } | Expr::Assign { data, .. } | Expr::Unwind { data, .. } | Expr::List { data, .. } @@ -331,6 +347,8 @@ impl Expr { } pub fn data_mut(&mut self) -> &mut Data { let (Expr::Binding { data, .. } + | Expr::And { data, .. } + | Expr::Or { data, .. } | Expr::Assign { data, .. } | Expr::List { data, .. } | Expr::Unwind { data, .. } diff --git a/std/syntax.ks b/std/syntax.ks index db45593..8bbf130 100644 --- a/std/syntax.ks +++ b/std/syntax.ks @@ -83,8 +83,8 @@ syntax_module { syntax catch_impl <- 16 = expr "catch" e "{" catch_block "}"; syntax catch_impl <- 16 = expr "catch" e "(" catch_block ")"; - syntax @"builtin fn or" <- 17 = lhs "or" rhs; - syntax @"builtin fn and" <- 18 = lhs "and" rhs; + syntax @"builtin macro or" <- 17 = lhs "or" rhs; + syntax @"builtin macro and" <- 18 = lhs "and" rhs; syntax @"builtin macro is" <- 18.5 = value "is" pattern;