diff --git a/interpreter.rust/Cargo.toml b/interpreter.rust/Cargo.toml index fc04384..4034bd7 100644 --- a/interpreter.rust/Cargo.toml +++ b/interpreter.rust/Cargo.toml @@ -5,6 +5,8 @@ authors = ["Mart铆n Coll "] edition = "2018" [dependencies] +lambda_calculus = "^3.0" +lambda-calculus-yaml = { path = "./lambda-calculus-yaml" } reflection = { path = "./serde-yaml-reflection" } risp = "0.7.0" risp-yaml = { path = "./risp-yaml" } @@ -14,6 +16,7 @@ serde_yaml = "0.8" [workspace] members = [ + "lambda-calculus-yaml", "risp-yaml", "serde-yaml-reflection", ] diff --git a/interpreter.rust/examples/e0-playground.yaml b/interpreter.rust/examples/e0-playground.yaml new file mode 100644 index 0000000..39cdd0d --- /dev/null +++ b/interpreter.rust/examples/e0-playground.yaml @@ -0,0 +1 @@ +- diff --git a/interpreter.rust/examples/e1-scalar.yaml b/interpreter.rust/examples/e1-scalar.yaml new file mode 100644 index 0000000..0a87dde --- /dev/null +++ b/interpreter.rust/examples/e1-scalar.yaml @@ -0,0 +1,2 @@ +# a scalar +42 diff --git a/interpreter.rust/examples/e1.yaml b/interpreter.rust/examples/e1.yaml deleted file mode 100644 index b70d27c..0000000 --- a/interpreter.rust/examples/e1.yaml +++ /dev/null @@ -1,2 +0,0 @@ -# 17 -[+, 10, 5, 2] diff --git a/interpreter.rust/examples/e2.yaml b/interpreter.rust/examples/e2-list.yaml similarity index 100% rename from interpreter.rust/examples/e2.yaml rename to interpreter.rust/examples/e2-list.yaml diff --git a/interpreter.rust/examples/e3-nested-lists.yaml b/interpreter.rust/examples/e3-nested-lists.yaml new file mode 100644 index 0000000..6e2bee6 --- /dev/null +++ b/interpreter.rust/examples/e3-nested-lists.yaml @@ -0,0 +1,5 @@ +# 19 +- + +- 10 +- 5 +- [-, 10, 3, 3] diff --git a/interpreter.rust/examples/e3.yaml b/interpreter.rust/examples/e3.yaml deleted file mode 100644 index 655df65..0000000 --- a/interpreter.rust/examples/e3.yaml +++ /dev/null @@ -1,2 +0,0 @@ -# 19 -[+, 10, 5, [-, 10, 3, 3]] diff --git a/interpreter.rust/examples/e4-abstraction.yaml b/interpreter.rust/examples/e4-abstraction.yaml deleted file mode 100644 index c914e76..0000000 --- a/interpreter.rust/examples/e4-abstraction.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# 2 -- do -- a: - - + - - 1 - - a -- - a - - 1 diff --git a/interpreter.rust/examples/e4-mapping.yaml b/interpreter.rust/examples/e4-mapping.yaml new file mode 100644 index 0000000..2fee4dd --- /dev/null +++ b/interpreter.rust/examples/e4-mapping.yaml @@ -0,0 +1,15 @@ +- do + +- - def + - add-one + - x: [+, 1, x] + +- - def + - add-two + - x: [+, 2, x] + +# 105 +- - add-one + - - add-two + - - add-two + - 100 diff --git a/interpreter.rust/examples/e5-nested-mapping.yaml b/interpreter.rust/examples/e5-nested-mapping.yaml new file mode 100644 index 0000000..595c950 --- /dev/null +++ b/interpreter.rust/examples/e5-nested-mapping.yaml @@ -0,0 +1,27 @@ +# examples from https://github.com/shybyte/risp +- do + +# ; Define a function +# (defn double [x] (* x 2)) +- - def + - double + - x: ['*', x, 2] + +# ; Function which returns a function (some call it a closure), which adds x1 to its single argument +# (defn create_adder [x1] +# (fn [x2] (+ x1 x2))) +- - def + - create_adder + - x1: + x2: [+, x1, x2] + +# (def add_20 (create_adder 20)) +- - def + - add_20 + - - create_adder + - 20 + +# 220 +- - add_20 + - - double + - 100 diff --git a/interpreter.rust/lambda-calculus-yaml/Cargo.toml b/interpreter.rust/lambda-calculus-yaml/Cargo.toml new file mode 100644 index 0000000..b21519e --- /dev/null +++ b/interpreter.rust/lambda-calculus-yaml/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "lambda-calculus-yaml" +version = "0.1.0" +authors = ["Mart铆n Coll "] +edition = "2018" + +[dependencies] +lambda_calculus = "^3.0" +reflection = { path = "../serde-yaml-reflection" } +serde = { version = "1.0", features = ["derive"] } +serde_yaml = "0.8" +serde_test = "1.0.117" diff --git a/interpreter.rust/lambda-calculus-yaml/src/lib.rs b/interpreter.rust/lambda-calculus-yaml/src/lib.rs new file mode 100644 index 0000000..3aa99df --- /dev/null +++ b/interpreter.rust/lambda-calculus-yaml/src/lib.rs @@ -0,0 +1,34 @@ +use reflection::Yaml; +use std::fs::File; +use std::io::BufReader; +use lambda_calculus::*; +use lambda_calculus::data::num::church; +use std::path::Path; + +use std::error::Error; + +pub fn read_term_from_file>(path: P) -> Result> { + let file = File::open(path)?; + let reader = BufReader::new(file); + Ok(serde_yaml::from_reader(reader)?) +} + +pub fn to_lambda_calculus(yaml_term: &Yaml) -> Term { + match yaml_term { + Yaml::String(var) => match var.as_ref() { + "+" => church::add(), + "-" => church::sub(), + _ => panic!("variables are numbers because we use de Bruijn notation"), + } + Yaml::Integer(var) => var.into_church(), + // https://www.cs.cornell.edu/courses/cs4110/2018fa/lectures/lecture15.pdf + Yaml::Hash(_) => panic!("variables are numbers because we use de Bruijn notation"), + Yaml::Array(vec) => match vec.as_slice() { + [term] => to_lambda_calculus(term), + [lhs, rhs] => app(to_lambda_calculus(lhs), to_lambda_calculus(rhs)), + [t0, t1, t2] => app!(to_lambda_calculus(t0), to_lambda_calculus(t1), to_lambda_calculus(t2)), + [t0, t1, t2, t3] => app!(to_lambda_calculus(t0), to_lambda_calculus(t1), to_lambda_calculus(t2), to_lambda_calculus(t3)), + _ => panic!("unsupported") + }, + } +} diff --git a/interpreter.rust/risp-yaml/Cargo.toml b/interpreter.rust/risp-yaml/Cargo.toml index 274c1ec..c48e56c 100644 --- a/interpreter.rust/risp-yaml/Cargo.toml +++ b/interpreter.rust/risp-yaml/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +lambda_calculus = "^3.0" reflection = { path = "../serde-yaml-reflection" } risp = "0.7" serde = { version = "1.0", features = ["derive"] } diff --git a/interpreter.rust/risp-yaml/src/lib.rs b/interpreter.rust/risp-yaml/src/lib.rs index e52dfb4..6406b6f 100644 --- a/interpreter.rust/risp-yaml/src/lib.rs +++ b/interpreter.rust/risp-yaml/src/lib.rs @@ -1,3 +1,4 @@ +use std::convert::TryInto; use reflection::Yaml; use risp::types::RispType; use std::fs::File; @@ -15,7 +16,7 @@ pub fn read_term_from_file>(path: P) -> Result RispType { match yaml_term { Yaml::String(var) => RispType::Symbol(var.to_string()), - Yaml::Integer(var) => RispType::Int(*var), + Yaml::Integer(var) => RispType::Int((*var).try_into().unwrap()), Yaml::Hash(hm) => { let (key, val) = hm.iter().next().unwrap(); RispType::List(vec![ diff --git a/interpreter.rust/serde-yaml-reflection/src/lib.rs b/interpreter.rust/serde-yaml-reflection/src/lib.rs index ea0cd15..8a2fb12 100644 --- a/interpreter.rust/serde-yaml-reflection/src/lib.rs +++ b/interpreter.rust/serde-yaml-reflection/src/lib.rs @@ -6,7 +6,8 @@ use std::collections::HashMap; #[derive(Serialize, Deserialize)] #[serde(untagged)] pub enum Yaml { - Integer(i64), + Integer(usize), + // Integer(i64), String(String), Array(Vec), Hash(HashMap), diff --git a/interpreter.rust/src/bin/eval.rs b/interpreter.rust/src/bin/eval.rs new file mode 100644 index 0000000..90b6d2c --- /dev/null +++ b/interpreter.rust/src/bin/eval.rs @@ -0,0 +1,12 @@ +use interpreter::eval_file; +use risp::core::create_core_environment; +use std::env; +use std::path::Path; + +fn main() { + let env = &mut create_core_environment(); + match env::args().skip(1).next() { + Some(path) => eval_file(Path::new(&path), env), + None => println!("Usage:\n cargo run --example eval-file -- [path_to_yaml]"), + } +} diff --git a/interpreter.rust/src/bin/lambda.rs b/interpreter.rust/src/bin/lambda.rs new file mode 100644 index 0000000..0a22e18 --- /dev/null +++ b/interpreter.rust/src/bin/lambda.rs @@ -0,0 +1,10 @@ +use interpreter::eval_lambda_calculus; +use std::env; +use std::path::Path; + +fn main() { + match env::args().skip(1).next() { + Some(path) => eval_lambda_calculus(Path::new(&path)), + None => println!("Usage:\n cargo run --bin lambda -- [path_to_yaml]"), + } +} diff --git a/interpreter.rust/src/bin/repl.rs b/interpreter.rust/src/bin/repl.rs new file mode 100644 index 0000000..a64ceda --- /dev/null +++ b/interpreter.rust/src/bin/repl.rs @@ -0,0 +1,20 @@ +use risp::core::create_core_environment; +use risp::eval::eval; +use risp_yaml::to_risp; +use std::io; + +fn main() { + let env = &mut create_core_environment(); + loop { + println!("risp-yaml >"); + let mut expr = String::new(); + while io::stdin().read_line(&mut expr).expect("valid code") > 1 {} + + let yaml_expr = serde_yaml::from_str(&expr).expect("invalid yaml line"); + let risp_expr = to_risp(&yaml_expr); + match eval(risp_expr, env) { + Ok(res) => println!("馃敟 {:?}", res), + Err(e) => println!("馃檧 {:?}", e), + } + } +} diff --git a/interpreter.rust/src/lib.rs b/interpreter.rust/src/lib.rs index aee69c4..3ae7f47 100644 --- a/interpreter.rust/src/lib.rs +++ b/interpreter.rust/src/lib.rs @@ -1,3 +1,5 @@ +use lambda_calculus::reduction::*; +use lambda_calculus_yaml::to_lambda_calculus; use risp::environment::Environment; use risp::eval::eval; use risp_yaml::read_term_from_file; @@ -13,3 +15,11 @@ pub fn eval_file(path: &Path, env: &mut Environment) { Err(e) => println!("// 馃檧 => {:?}", e), } } + +pub fn eval_lambda_calculus(path: &Path) { + let file = read_term_from_file(path).unwrap(); + + let mut expr = to_lambda_calculus(&file); + println!("steps: {}", expr.reduce(NOR, 0)); + println!("{}", expr); +} diff --git a/yaml.yaml/data/bool/and.yaml.yaml b/yaml.yaml/data/bool/and.yaml.yaml index d35d1fb..04305ab 100644 --- a/yaml.yaml/data/bool/and.yaml.yaml +++ b/yaml.yaml/data/bool/and.yaml.yaml @@ -1,4 +1,4 @@ -# 位p.位q.(p q false) -- p -- q +# 位p.位q.(p q false) = 位位.(1 0 false) +- 1 +- 0 - false diff --git a/yaml.yaml/data/bool/yaml.yaml b/yaml.yaml/data/bool/yaml.yaml index 74859b9..a2b6171 100644 --- a/yaml.yaml/data/bool/yaml.yaml +++ b/yaml.yaml/data/bool/yaml.yaml @@ -1,3 +1,6 @@ # https://users.monash.edu.au/~lloyd/tildeFP/Lambda/Examples/const-bool/ -- true: a -- false: b +# and in de Bruijn notation: +# true := 位a.位b.a = 位位.1 +# false := 位a.位b.a = 位位.0 +- false +- true diff --git a/yaml.yaml/node/term.yaml.yaml b/yaml.yaml/node/term.yaml.yaml index f6fb94a..639cd30 100644 --- a/yaml.yaml/node/term.yaml.yaml +++ b/yaml.yaml/node/term.yaml.yaml @@ -6,6 +6,11 @@ # also very terse as a general-purpose # functional programming language +# https://www.win.tue.nl/automath/archive/pdf/aut029.pdf +# section 14. ALGORITHMS gave me an idea about the meaning. +# of mappings and variable names. those are given as free variable +# lists that carry semantics and are only understood by humans. + scalar: variable sequence: - mapping: