From f54f630b38afc240fcb07de2c8aa5c8252edd032 Mon Sep 17 00:00:00 2001
From: Michael Sippel <micha@fragmental.art>
Date: Sun, 12 May 2024 04:22:32 +0200
Subject: [PATCH] adapt Abstraction variant of LTExpr to allow multiple
 parameters

This avoids unneccesary recursive chaining and also allows abstractions with zero parameters.
---
 src/expr.rs               | 15 ++++++++-------
 src/main.rs               | 12 +++++++++---
 src/parser.rs             | 11 +++++++----
 src/procedure_compiler.rs | 28 +++++++++++++++-------------
 4 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/src/expr.rs b/src/expr.rs
index 9c85731..592d938 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -39,9 +39,8 @@ pub enum LTExpr {
         body: Vec<LTExpr>
     },
     Abstraction {
-        arg_id: String,
-        arg_type: Option< laddertypes::TypeTerm >,
-        val_expr: Box<LTExpr>
+        args: Vec<(String, Option<laddertypes::TypeTerm>)>,
+        body: Box<LTExpr>
     },
     Branch {
         condition: Box<LTExpr>,
@@ -68,11 +67,13 @@ impl LTExpr {
         }
     }
 
-    pub fn abstraction(arg_id: &str, arg_typ: &str, val_expr: LTExpr) -> LTExpr {
+    pub fn abstraction(args: Vec<(&str, &str)>, val_expr: LTExpr) -> LTExpr {
         LTExpr::Abstraction {
-            arg_id: String::from(arg_id),
-            arg_type: None,//typectx.write().unwrap().parse(arg_typ).expect("parse typeterm"),
-            val_expr: Box::new(val_expr)
+            args: args.into_iter().map(|(arg_name, arg_type)|
+                ( arg_name.into(), None )    
+                //typectx.write().unwrap().parse(t).expect("parse typeterm")
+            ).collect(),
+            body: Box::new(val_expr)
         }
     }
 
diff --git a/src/main.rs b/src/main.rs
index db260a8..07b62a9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -80,13 +80,19 @@ fn main() {
                 }
             };
 
-            let hello = λ _ {
+            let hello = λ{
                 print-nullterm hello-string;
                 print-lenprefix pfxstr;
             };
-            let isquare = λx (i* x x);
 
-            hello 'X';
+            hello;
+
+            let isquare = λx (i* x x);
+            let magnitude2 = λx y {
+                i+ (isquare x) (isquare y);
+            };
+            magnitude2 8 16;
+
             emit '\n';
             emit (i+ '0' (isquare 3));
             emit '\n';
diff --git a/src/parser.rs b/src/parser.rs
index d80724c..6a4f48b 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -175,13 +175,16 @@ where It: Iterator<Item = char>
             Ok(LTIRToken::Lambda) => {
                 if children.len() == 0 {
                     tokens.next();
-                    let name = parse_symbol(tokens)?;
+
+                    let mut args = Vec::new();
+                    while let Some(Ok(LTIRToken::Symbol(_))) = tokens.peek() {
+                        args.push((parse_symbol(tokens)?, None));
+                    }
                     let body = parse_expr(tokens)?;
 
                     return Ok(LTExpr::Abstraction{
-                        arg_id: name,
-                        arg_type: None,
-                        val_expr: Box::new(body)
+                        args,
+                        body: Box::new(body)
                     });
                 } else {
                     return Err(ParseError::UnexpectedToken);
diff --git a/src/procedure_compiler.rs b/src/procedure_compiler.rs
index b7a23a4..a361146 100644
--- a/src/procedure_compiler.rs
+++ b/src/procedure_compiler.rs
@@ -100,7 +100,7 @@ impl ProcedureCompiler {
             }
             Statement::LetAssign{ var_id, val_expr } => { 
                 match val_expr {
-                    LTExpr::Abstraction { arg_id:_, arg_type:_, val_expr:_ } => {                        
+                    LTExpr::Abstraction { args:_, body:_ } => {
                         self.symbols.write().unwrap()
                             .declare_proc(
                                 var_id.clone(),
@@ -186,18 +186,20 @@ impl ProcedureCompiler {
                 }
                 self = self.compile(head);
             }
-            LTExpr::Abstraction { arg_id: arg_name, arg_type, val_expr } => {
-                let id = self.symbols
-                    .write().unwrap()
-                    .declare_var(
-                        arg_name.clone(),
-                        laddertypes::TypeTerm::unit());
-
-                self.asm = self.asm
-                    .lit( id )
-                    .call("data-frame-set");
-
-                self = self.compile(val_expr);
+            LTExpr::Abstraction { args, body } => {
+                for (arg_name, arg_type) in args.iter() {
+                    let id = self.symbols
+                       .write().unwrap()
+                       .declare_var(
+                            arg_name.clone(),
+                            arg_type.clone().unwrap_or(
+                            laddertypes::TypeTerm::unit())
+                        );
+                    self.asm = self.asm
+                        .lit( id )
+                        .call("data-frame-set");
+                }
+                self = self.compile(body);
             }
             LTExpr::Branch { condition, if_expr, else_expr } => {
                 self = self.compile(condition);