Hello, and thank you for taking the time to look at LambdaScript. After about a year of working on LambdaScript, I have decided to start from scratch write a new, more reliable, and efficient interpreter for a new language - LambdaScript 2. This new language is based on the same principles as LambdaScript, but with a more robust implementation in TypeScript, rather than OCaml.
Working on LambdaScript has been an incredible learning experience for me, and I hope to make LambdaScript 2 even better. I hope you enjoy looking at LambdaScript/LambdaScript 2 as much as I enjoyed working on it!
-Alex
LambdaScript is a statically-typed functional programming language designed to make it easy to write elegant and expressive code. It features a powerful type system underpinned by kinds, which allows for higher-order arithmetic on types.
It also features a type inference engine similar to the Hindley-Milner algorithm, which can infer the types of most expressions, so you don't have to write them out.
-
To view the rigerously-defined semantics for LambdaScript, please refer to https://github.com/LambdaAK/LambdaScript/blob/main/documentation/LambdaScript.pdf
-
Note that they are currently outdated, and have not yet been updated to reflect the new syntax and features.
input
17output
Int: 17input
trueoutput
Bool: trueinput
"hello world!"output
String: hello world!input
()output
Unit: ()input
[]output
[a]: []input
1 :: 2 :: 3 :: 4 :: 5 :: []output
[Int]: [1, 2, 3, 4, 5]input
[1, 2, 3, 4, 5]output
[Int]: [1, 2, 3, 4, 5]input
(1, true)output
(Int, Bool): (1, true)input
\ x -> xoutput
a -> a: functioninput
\ x -> x + 1output
Int -> Int: functioninput
let x = 1 in
let y = 2 in
x + youtput
Int: 3input
let f x y z = x (y + z) in foutput
f : (Int -> a) -> Int -> Int -> a = functioninput
if true then 1 else 2output
Int: 1input
switch [] =>
| [] -> true
| _ :: _ -> false
endoutput
Bool: trueinput
switch [1, 2] =>
| [] -> true
| _ :: _ -> false
endoutput
Bool: falseinput
type IntList =
| Nil
| Cons (Int, IntList)
let rec length l =
switch l =>
| Nil -> 0
| Cons (_, t) -> 1 + length t
end
output
length : IntList -> Int = functioninput
let rec map f arr =
switch arr =>
| [] -> []
| h :: t -> f h :: map f t
endoutput
(a -> b) -> [a] -> [b]: functioninput
map (\ x -> x * x) [1, 2, 3, 4, 5]output
[Int]: [1, 4, 9, 16, 25]input
let rec filter f arr =
switch arr =>
| [] -> []
| h :: t ->
if f h then h :: filter t
else filter t
endoutput
(a -> Bool) -> [a] -> [a]: functioninput
let rec reduce_left op arr acc =
switch arr =>
| [] -> acc
| h :: t -> reduce_left op t (op acc h)
endoutput
(a -> b -> a) -> [b] -> a -> a: functioninput
let rec reduce_right op arr acc =
switch arr =>
| [] -> acc
| h :: t -> op h (reduce_right op t acc)
endoutput
(a -> b -> b) -> [a] -> b -> b: functioninput
type IntPair = (Int, Int)output
type IntPair : (Int, Int)input
type IntList =
| Nil
| Cons (Int, IntList)
output
type IntList : Nil | Cons (Int, IntList)input
type IntBT =
| Leaf
| Node (Int, IntBT, IntBT)
output
type IntBT : Leaf | Node (Int, IntBT, IntBT)input
type IntOpt =
| None
| Some (Int
output
type IntOpt : None | Some (Int)input
type Option a = | None | Some (a)output
Option : * -> *input
type List a = | Nil | Cons (a, List a)output
List : * -> *input
type Either a b = | Left (a) | Right (b)output
Either : * -> * -> *input
type AssocList key val = [(key, val)]output
AssocList : * -> * -> *input
type App a b = a b
output
App : (* -> *) -> * -> *
input
type App2 a b c d e = e (b c a) doutput
* -> (* -> * -> *) -> * -> * -> (* -> * -> *) -> *
- OCaml 5.0.0 or higher
- Dune
- To clone the project, run the following command:
git clone https://github.com/LambdaAK/LambdaScript- Then,
cdinto the project directory and run the following command:
make- You can run the REPL by running the following command:
make repl- You can execute a LambdaScript file by running the following command:
dune exec ./bin/interpreter.exe <filename>There are currently around 450 unit tests in the test directory. In order to achieve greater exhaustiveness, I implemented a mechanism taking pre-built unit tests and generating new ones by applying random transformatios to them. This allows for a much greater number of tests to be generated, and thus a greater degree of confidence in the correctness of the implementation. With this, the 450 unit tests can be expanded to around 13,000 unit tests.
To run the unit tests, run the following command:
make test-
To use the random test generator, set the
modify_testsvariable intest/test.mltotrueand follow the instructions above. -
To run tests with coverage, run the following command:
make bisect- To generate the code documentation, run the following command:
make doc- To view the code documentation, run the following command
make opendoc