From 419d152cf7c4a7d3ee1d36991c10a821b3c3a210 Mon Sep 17 00:00:00 2001 From: Natapat Samutpong Date: Sat, 19 Mar 2022 08:44:43 +0700 Subject: [PATCH] one or more holes in piping, (almost) mutable variable --- crates/codegen/src/ts.rs | 5 +++-- crates/hir/src/lib.rs | 30 ++++++++++++++++++++---------- crates/lexer/src/lib.rs | 3 ++- crates/parser/src/lib.rs | 7 +++++-- example/pipe2.hz | 4 ++++ 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/crates/codegen/src/ts.rs b/crates/codegen/src/ts.rs index e8dc141..bf4e6e4 100644 --- a/crates/codegen/src/ts.rs +++ b/crates/codegen/src/ts.rs @@ -31,9 +31,10 @@ impl Codegen { macro_rules! semicolon { () => { if should_gen_semicolon { ";" } else { "" } }; } match ir { - IRKind::Define { name, type_hint, value } => { + IRKind::Define { name, type_hint, value, mutable } => { format!( - "const {}: {} = {}{}\n", + "{} {}: {} = {}{}\n", + if *mutable { "let" } else { "const" }, name, type_hint, self.gen_ir(value, false), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index c6758e1..bafb91c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -13,7 +13,7 @@ pub enum Value { Int(i64), Boolean(bool), String(String), Ident(String) } #[derive(Debug, Clone)] pub enum IRKind { - Define { name: String, type_hint: String, value: Box }, + Define { name: String, type_hint: String, value: Box, mutable: bool }, Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box }, Call { name: String, args: Vec }, Intrinsic { name: String, args: Vec }, @@ -115,14 +115,16 @@ pub fn expr_to_ir(expr: &Expr) -> (Option, Option) { _ => return (None, Some(LoweringError { span: name.1.clone(), message: "Expected identifier".to_string(), note: None })) }; - // Get the index where the `Hole` is at - let index = args.0.iter().position(|arg| match arg.0 { - Expr::Hole(..) => true, - _ => false - }); + // Get all the `Hole` indexes + let mut indexes = Vec::new(); + for (i, arg) in args.0.iter().enumerate() { + if let Expr::Hole(..) = &arg.0 { + indexes.push(i); + } + } // If there is no `Hole` in the args then return early - if let None = index { + if indexes.is_empty() { return (None, Some(LoweringError { span: rhs.1.clone(), message: "Expected hole in piping".to_string(), @@ -132,7 +134,9 @@ pub fn expr_to_ir(expr: &Expr) -> (Option, Option) { // Remove the `Hole` from the args let mut new_args = args.0.clone(); - new_args.remove(index.unwrap()); + for index in indexes.iter().rev() { + new_args.remove(*index); + } // Make a new call expression with the new args let new_call = match call { @@ -182,12 +186,18 @@ pub fn expr_to_ir(expr: &Expr) -> (Option, Option) { }; }, - Expr::Let { name, type_hint, value } => { + Expr::Let { name, type_hint, value, mutable } => { let value = expr_to_ir(&value.0); if_err_return!(value.1); let value = value.0.unwrap(); - let ir_kind = IRKind::Define { name: name.clone(), type_hint: gen_type_hint(type_hint), value: Box::new(value) }; + let ir_kind = IRKind::Define { + name: name.clone(), + type_hint: gen_type_hint(type_hint), + value: Box::new(value), + mutable: *mutable + }; + return (Some(ir_kind), None); }, diff --git a/crates/lexer/src/lib.rs b/crates/lexer/src/lib.rs index 6823476..dcc3fe9 100644 --- a/crates/lexer/src/lib.rs +++ b/crates/lexer/src/lib.rs @@ -3,7 +3,7 @@ use chumsky::prelude::*; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Token { // Keywords - KwLet, KwFun, + KwLet, KwMut, KwFun, KwDo, KwEnd, KwIf, KwThen, KwElse, KwReturn, @@ -30,6 +30,7 @@ impl std::fmt::Display for Token { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Token::KwLet => write!(f, "let"), + Token::KwMut => write!(f, "mut"), Token::KwFun => write!(f, "fun"), Token::KwDo => write!(f, "do"), Token::KwEnd => write!(f, "end"), diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs index 982e141..20ad8ea 100644 --- a/crates/parser/src/lib.rs +++ b/crates/parser/src/lib.rs @@ -18,6 +18,7 @@ pub enum Expr { name: String, type_hint: String, value: Box>, + mutable: bool, }, Fun { name: String, @@ -193,17 +194,19 @@ fn expr_parser() -> impl Parser>, Error = Simple }); let let_ = just(Token::KwLet) - .ignore_then(identifier) + .ignore_then(just(Token::KwMut)).or_not() + .then(identifier) .then_ignore(just(Token::Colon)) .then(identifier) .then_ignore(just(Token::Assign)) .then(expr.clone()) - .map(|((name, type_hint), value)| { + .map(|(((mutable, name), type_hint), value)| { ( Expr::Let { name: name.0.clone(), type_hint: type_hint.0, value: Box::new(value.clone()), + mutable: mutable.is_some(), }, name.1.start..value.1.end, ) diff --git a/example/pipe2.hz b/example/pipe2.hz index 197cb38..fe3ee08 100644 --- a/example/pipe2.hz +++ b/example/pipe2.hz @@ -12,4 +12,8 @@ fun main: void = do |> qux(_) |> quux(1, _) |> @write(_); + + 210 + |> bar(_, _) + |> @write(_); end; \ No newline at end of file