From 4daf7b149622a16a2271630a19f0833702477a86 Mon Sep 17 00:00:00 2001 From: Joel Kronqvist Date: Sat, 16 Aug 2025 03:25:45 +0300 Subject: feat: vector concatenation --- src/parse/parsetree.rs | 1 + src/sexp/display.rs | 1 + src/sexp/mod.rs | 1 + src/sexp/step.rs | 21 +++++++++++++++++++++ src/type/check.rs | 7 +++++++ 5 files changed, 31 insertions(+) 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"), -- cgit v1.2.3