aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-16 03:25:45 +0300
committerJoel Kronqvist <joel.kronqvist@iki.fi>2025-08-16 03:25:45 +0300
commit4daf7b149622a16a2271630a19f0833702477a86 (patch)
treebc09cbc387ab4e551557f94b67c72e7095a07658
parentfad9bf51e9ecd48473046a5e7bb9b5005893ae89 (diff)
downloadmyslip-4daf7b149622a16a2271630a19f0833702477a86.tar.gz
myslip-4daf7b149622a16a2271630a19f0833702477a86.zip
feat: vector concatenation
-rw-r--r--src/parse/parsetree.rs1
-rw-r--r--src/sexp/display.rs1
-rw-r--r--src/sexp/mod.rs1
-rw-r--r--src/sexp/step.rs21
-rw-r--r--src/type/check.rs7
5 files changed, 31 insertions, 0 deletions
diff --git a/src/parse/parsetree.rs b/src/parse/parsetree.rs
index bd15e79..c773f3b 100644
--- a/src/parse/parsetree.rs
+++ b/src/parse/parsetree.rs
@@ -119,6 +119,7 @@ fn tokens_to_ast_inner(
Some(Sym(s)) if s == "false" => Ok(Atom(False)),
Some(Sym(s)) if s == "quote" => Ok(Atom(Quote)),
Some(Sym(s)) if s == "vector" => Ok(Atom(Vector)),
+ Some(Sym(s)) if s == "<>" => Ok(Atom(Concat)),
Some(Sym(s)) if s == "print" => Ok(Atom(Print)),
Some(Sym(s)) if s == "let" => Ok(Atom(Let)),
Some(Sym(s)) if s == "fn" => Ok(Atom(Fun)),
diff --git a/src/sexp/display.rs b/src/sexp/display.rs
index e2f4ffc..ec1b421 100644
--- a/src/sexp/display.rs
+++ b/src/sexp/display.rs
@@ -28,6 +28,7 @@ impl fmt::Display for SLeaf {
RestPat(s) => format!("..{s}"),
Quote => "quote".to_string(),
Vector => "vector".to_string(),
+ Concat => "<>".to_string(),
Print => "print".to_string(),
Let => "let".to_string(),
Fun => "fn".to_string(),
diff --git a/src/sexp/mod.rs b/src/sexp/mod.rs
index aa51811..1a90f52 100644
--- a/src/sexp/mod.rs
+++ b/src/sexp/mod.rs
@@ -30,6 +30,7 @@ pub enum SLeaf {
Or,
Not,
Xor,
+ Concat,
Quote,
Vector,
diff --git a/src/sexp/step.rs b/src/sexp/step.rs
index 9077401..59b201c 100644
--- a/src/sexp/step.rs
+++ b/src/sexp/step.rs
@@ -441,6 +441,27 @@ impl SExp {
},
+ // Concatenation
+ SCons(op, l) if *op == Atom(Concat) => {
+ let ls = l.parts();
+ let firstvec = ls.get(0).unwrap();
+ let secondvec = ls.get(1).unwrap();
+ let firstvec = match firstvec {
+ SCons(a, b) if **a == Atom(Vector) => *b.clone(),
+ t => t.clone(),
+ };
+ let secondvec = match secondvec {
+ SCons(a, b) if **a == Atom(Vector) => *b.clone(),
+ t => t.clone(),
+ };
+ let mut res = Atom(Nil);
+ for exp in firstvec.parts().into_iter().chain(secondvec.parts()).rev() {
+ res = scons(exp, res);
+ }
+ Ok(scons(Vector, res))
+ },
+
+
// Arithmetic
diff --git a/src/type/check.rs b/src/type/check.rs
index 170feec..fd5d1d3 100644
--- a/src/type/check.rs
+++ b/src/type/check.rs
@@ -244,6 +244,13 @@ impl SExp {
Ok(arr(List(vec![Integer, Integer]), Boolean)),
Atom(Or | And | Xor) => Ok(arr(List(vec![Boolean, Boolean]), Boolean)),
Atom(Not) => Ok(arr(Boolean, Boolean)),
+ Atom(Concat) => Ok(arr(
+ List(vec![
+ List(vec![VecType, vecof(vt("T"))]),
+ List(vec![VecType, vecof(vt("T"))])
+ ]),
+ List(vec![VecType, vecof(vt("T"))])
+ )),
Atom(Nil) => Ok(NilType),
Atom(Quote) => Ok(arr(
vt("T"),