Showing preview only (634K chars total). Download the full file or copy to clipboard to get everything.
Repository: ytakano/blisp
Branch: master
Commit: b0ae5499141f
Files: 26
Total size: 603.8 KB
Directory structure:
gitextract_wiwtvaga/
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── docs/
│ ├── Makefile
│ ├── index.adoc
│ ├── index.html
│ ├── index.ja.adoc
│ └── index.ja.html
├── embed_macro/
│ ├── Cargo.toml
│ ├── LICENSE
│ ├── README.md
│ └── src/
│ └── lib.rs
├── history.md
├── specification/
│ ├── Makefile
│ ├── language.md
│ └── typing.tex
├── src/
│ ├── coq.rs
│ ├── lib.rs
│ ├── macro.rs
│ ├── parser.rs
│ ├── prelude.lisp
│ ├── runtime.rs
│ └── semantics.rs
└── tests/
├── embedded.rs
└── transpile.rs
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
target/
Cargo.lock
.DS_Store
================================================
FILE: Cargo.toml
================================================
[package]
name = "blisp"
version = "0.4.7"
authors = ["Yuuki Takano <ytakanoster@gmail.com>", "Fumiya Saito"]
edition = "2021"
description = "A lisp like statically typed programing language for no_std."
repository = "https://github.com/ytakano/blisp"
keywords = [
"no_std",
"scripting",
"scripting-engine",
"scripting-language",
"embedded",
]
categories = ["no-std", "embedded"]
license-file = "LICENSE"
readme = "README.md"
homepage = "https://ytakano.github.io/blisp/"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
blisp_embedded = "0.1"
[dependencies.num-bigint]
version = "0.4"
default-features = false
[dependencies.num-traits]
version = "0.2"
default-features = false
features = ["libm"]
[lib]
crate-type = ["rlib"]
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Yuuki Takano <ytakano@wide.ad.jp>, Fumiya Saito
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# BLisp
BLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.
BLisp supports higher order RPC like higher order functions of functional programming languages.
This repository provides only a library crate.
Please see [blisp-repl](https://github.com/ytakano/blisp-repl) to use BLisp,
and [baremetalisp](https://github.com/ytakano/baremetalisp) which is a toy OS.
**[Homepage](https://ytakano.github.io/blisp/) is here.**
## Features
- Algebraic data type
- Generics
- Hindley–Milner based type inference
- Effect system to separate side effects from pure functions
- Hygienic macro expansion for local binders introduced by macro templates
- Big integer
- Supporting no_std environments
## How to Use
```rust
use blisp;
fn main() {
let code = "(export factorial (n) (Pure (-> (Int) Int))
(if (<= n 0)
1
(* n (factorial (- n 1)))))";
let exprs = blisp::init(code, vec![]).unwrap();
let ctx = blisp::typing(exprs).unwrap();
let e = "(factorial 10)";
blisp::eval(e, &ctx).unwrap();
}
```
If Rust compiler or linker says warning of fmod,
please add fmod manually as follows.
```rust
#[no_mangle]
extern "C" fn fmod(x: f64, y: f64) -> f64 {
libm::fmod(x, y)
}
```
Cargo.toml
```toml
[dependencies.blisp]
version = "0.4"
```
## Examples
```lisp
"Hello, World!" ; "Hello, World!"
(+ 0x10 0x20) ; 48
(+ 0b111 0b101) ; 12
(+ 0o777 0o444) ; 803
(car '(1 2 3)) ; (Some 1)
(cdr '(1 2 3)) ; '(2 3)
(map (lambda (x) (* x 2)) '(8 9 10)) ; '(16 18 20)
(fold + 0 '(1 2 3 4 5 6 7 8 9)) ; 45
(reverse '(1 2 3 4 5 6 7 8 9)) ; '(9 8 7 6 5 4 3 2 1)
(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9)) ; '(2 4 6 8)
```
================================================
FILE: docs/Makefile
================================================
all: index.html index.ja.html
index.html: index.adoc
asciidoctor index.adoc
index.ja.html: index.ja.adoc
asciidoctor index.ja.adoc
================================================
FILE: docs/index.adoc
================================================
= BLisp: A Statically Typed Lisp Like Language
Yuuki Takano <ytakano@wide.ad.jp>
v0.4.0, 2023-02
:doctype: article
:toc:
:sectnums:
:encoding: utf-8
:stem: latexmath
:source-highlighter: pygments
BLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.
BLisp supports higher order RPC like higher order functions of functional programming languages.
* https://github.com/ytakano/blisp[GitHub's Repository]
* https://crates.io/crates/blisp[BLisp's crates.io]
This repository provides only a library crate.
Please see https://github.com/ytakano/blisp-repl[blisp-repl] to use BLisp,
and https://github.com/ytakano/baremetalisp[baremetalisp] which is a toy OS.
https://ytakano.github.io/blisp/index.ja.html[日本語版はこちら]
.BLisp on no_std Environment
image:https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytakano/20210221/20210221155657.gif[BLisp on no_std Environment]
== Features
* Algebraic data type
* Generics
* Hindley–Milner based type inference
* Effect system to separate side effects from pure functions
* Big integer
* Supporting no_std environments
== Values
.values
[source, lisp]
----
`A` ; character literal
"Hello" ; string literal
144 ; integer value
0xabcDEF ; hexadecimal
0o777 ; octal
0b1001 ; binary
true ; boolean value
false ; boolean value
[true 10] ; tuple
[] ; empty tuple
'(1 2 3) ; list
'() ; empty list, Nil
----
== Basic Types
.types
[source, lisp]
----
Char ; character
String ; string
Int ; signed integer
Bool ; boolean
'(Int) ; list of Int
[Int Bool] ; tuple of Int and Bool
(Pure (-> (Int Int) Bool)) ; Pure function, which takes 2 integers and return boolean value
(IO (-> (Int) [])) ; IO function, which takes an integer and return []
----
Pure and IO are function effects.
In IO functions, both Pure and IO functions can be called.
However, in Pure functions, calling only Pure functions is permitted.
== Function Definition
Functions can be defined by defun or export.
"defun" defines a local function which cannot be called from Rust's eval function.
Suppose following 2 functions.
.defun
[source, lisp]
----
(defun double (x) ; function name is "double" and "x" is an argument
(Pure (-> (Int) Int)) ; function Type
(* 2 x)) ; function body
----
.export
[source, lisp]
----
(export quad (x) ; function name is "quad" and "x" is an argument
(Pure (-> (Int) Int)) ; function Type
(double (double x))) ; function body
----
double cannot be called from Rust's eval, but can be called from internally defined functions.
quad can be called from Rust's eval, and it calls double internally.
This is the code what actually do in Rust.
.Rust's eval
[source, rust]
----
use blisp;
fn eval(e: &str, ctx: &blisp::semantics::Context) {
// evaluate expressions
let exprs = match blisp::eval(e, ctx) {
Ok(es) => es,
Err(err) => {
println!("error:{}:{}: {}", err.pos.line, err.pos.column, err.msg);
return;
}
};
for r in exprs {
match r {
Ok(msg) => {
println!("{}", msg);
}
Err(msg) => {
println!("error: {}", msg);
}
}
}
}
fn main() {
// internal code
let code = "
(defun double (x) ; function name is double and x is an argument
(Pure (-> (Int) Int)) ; function Type
(* 2 x)) ; function body
(export quad (x) ; function name is quad and x is an argument
(Pure (-> (Int) Int)) ; function Type
(double (double x))) ; function body
";
let exprs = blisp::init(code, vec![]).unwrap();
let ctx = blisp::typing(&exprs).unwrap();
let e = "(double 10) ; error";
eval(e, &ctx);
let e = "(quad 10) ; OK";
eval(e, &ctx);
}
----
This code output as follows.
error:0:1: Typing Error: double is not defined
40
== Arithmetic Operations
.basic
[source, lisp]
----
; (Pure (-> (Int Int) Int))
(+ 10 20)
(- 30 40)
(* 6 100)
(/ 100 2)
(% 10 3)
----
== Boolean Operations
.logical
[source, lisp]
----
; (Pure (-> (Bool Bool) Bool))
(and true false)
(or true false)
(xor true false)
----
.negation
[source, lisp]
----
; (Pure (-> (Bool) Bool))
(not true)
----
== Comparison
=, !=, <, >, \<=, >= can be used for 2 values whose types are same.
.comparison between 2 values whose types are same
[source, lisp]
----
; (Pure (-> (t t) Bool))
(= 4 4) ; true
(!= 4 4) ; false
(= "Hello" "Hello") ; true
(= (Some 1) (Some 2)) ; false
(< 6 7)
(> 6 7)
(<= 30 40)
(>= 30 40)
(< "Hello" "World")
(<= (Some 1) (Some 2))
----
_eq_, _neq_, _lt_, _gt_, _leq_, _geq_ can be used for any 2 values
.comparison between any 2 values
[source, lisp]
----
; (Pure (-> (t1 t1) Bool))
(geq (Some 1) "Hello") ; (Some 1) is greater than or qeual to "Hello"
(eq "Hello" 100) ; Is "Hello" qeual to 100?
(neq "Hello" 100) ; Is "Hello" not equal to 100?
(lt 100 (Some 20)) ; Is 100 less than (Some 20)?
(gt 200 "Hello") ; Is 200 greater than "Hello"
----
== Bitwise Operations
[source, lisp]
----
(band 1 0) ; bitwise and
(band 1 1) ; bitwise and
(bor 1 0) ; bitwise or
(bor 1 1) ; bitwise or
(bxor 1 0) ; bitwise xor
----
.bit shift
[source, lisp]
----
; (Pure (-> (Int Int) (Option Int)))
(<< 8 4) ; (Some 128)
(>> 128 4) ; (Some 8)
(>> -128 4) ; (Some -8)
----
If 2nd argument is greater or equal to 2^64^, then these function return None.
== Mathematical Operations
[source, lisp]
----
; (Pure (-> (Int Int) (Option Int)))
(pow 10 20) ; (Some 100000000000000000000)
; (Pure (-> (Int) (Option Int)))
(sqrt 16) ; (Some 4)
----
If _pow_'s exponent portion is greater or equal to 2^32^, then _pow_ returns None.
If _sqrt_'s argument is less than 0. then _sqrt_ returns None.
== Algebraic Data Type
Algebraic data type can be defined as follows.
[source, lisp]
----
; in BLisp
(data Cardinal ; type name
East ; value
North ; value
West ; value
South) ; value
----
Type name's and its value's first character must be uppercase.
This is equivalent to Rust's following code.
[source, rust]
----
// in Rust
enum Cardinal {
East,
North,
West,
South
}
----
Each element can have values as follows.
[source, lisp]
----
; in BLisp
(data Dim2
(Dim2 Int Int)) ; Dim2 has integers
----
Dim2 can be instantiated as follows.
[source, lisp]
----
(Dim2 10 20)
----
This type is equivalent to Rust's following type.
[source, rust]
----
// in Rust
use num_bigint::BigInt;
enum Dim2 {
Dim2(BigInt, BigInt)
}
----
== Generics
Option and Result types are defined internally.
[source, lisp]
----
(data (Option t)
(Some t)
None)
(data (Result t e)
(Ok t)
(Err e))
----
_t_ and _e_ are type variables.
This code is equivalent to Rust's following code.
[source, rust]
----
// in Rust
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
----
List type is a built-in type as follows.
[source, lisp]
----
(data (List t)
(Cons t (List t))
Nil)
----
So, following 2 lists are equivalent.
[source, lisp]
----
(Cons 1 (Cons 2 (Cons 3 Nil)))
'(1 2 3)
----
== Generic Function
_car_ and _cdr_ are internally defined generic functions.
These definitions are as follows.
[source, lisp]
----
(export car (x) (Pure (-> ('(t)) (Option t)))
(match x
((Cons n _) (Some n))
(_ None)))
(export cdr (x) (Pure (-> ('(t)) '(t)))
(match x
((Cons _ l) l)
(_ '())))
----
_t_ is a type variable. These functions can be used as follows.
[source, lisp]
----
(car '(3 8 9)) ; returns (Some 3)
(cdr '(8 10 4)) ; returns '(10 4)
----
Normal and type variables' first character must be lowercase.
== If Expression
Straightforward.
[source, lisp]
----
(if (< 10 20)
'(1 2 3)
'())
----
== Match Expression
A list can be matched as follows.
[source, lisp]
----
(match '(1 2 3)
((Cons n _) n)
('() 0))
----
The expression
(Cons n _)
is a pattern.
If the pattern is matched to '(1 2 3), 1 is assigned to a variable _n_. Then, _n_, namely 1, is returned.
This is an example of pattern matching of tuple.
[source, lisp]
----
(match [1 3]
([x y] [y x]))
----
This code swap 1st and 2nd elements of the tuple.
Integer values can be also used for pattern matching.
[source, lisp]
----
(match 20
(20 true)
(_ false))
----
More complex example is a as follows.
[source, lisp]
----
(match [(Some 10) true]
([(Some 10) false] 1)
([(Some 10) true] 2)
(_ 0))
----
BLisp checks exhaustively of pattern.
So, following code will be rejected.
[source, lisp]
----
(match '(1 2)
('() 0))
----
== Let Expression
Let expression is used to bind variables as follows.
[source, lisp]
----
(let ((x 10) (y 20)) ; x is 10, y is 20
(* x y))
(let ((x 10) (x (* x x)) (x (* x x))) ; x = 10, x = x * x, x = x * x
x)
----
Destructuring can be also performed as follows.
[source, lisp]
----
(let (((Some x) (Some 10))) ; x is 10
(* x 2))
(let (([x y] [10 20])) ; x is 10, y is 20
(* x y))
----
== Lambda Expression
Lambda expression is defined as follows.
[source, lisp]
----
(lambda (x y) (* x y))
----
This lambda takes 2 integers and return the multiplication.
Applying arguments to this is simple as follows.
[source, lisp]
----
((lambda (x y) (* x y)) 10 20)
----
Every lambda expression is Pure.
IO functions cannot be called in any lambda expressions.
_map_ and _fold_ functions are internally defined as follows.
[source, lisp]
----
(export map (f x) (Pure (-> ((Pure (-> (a) b)) '(a)) '(b)))
(match x
((Cons h l) (Cons (f h) (map f l)))
(_ '())))
(export fold (f init x) (Pure (-> ((Pure (-> (a b) b)) b '(a)) b))
(match x
((Cons h l) (fold f (f h init) l))
(_ init)))
----
_map_ can be used to apply functions to elements of a list as follows.
[source, lisp]
----
; square each element
(let ((l '(1 2 3))
(f (lambda (x) (* x x))))
(map f l))
----
_fold_ can be used to calculate over elements of a list.
For example, summation can be computed as follows.
[source, lisp]
----
; summation
(let ((l '(20 50 60))
(f (lambda (x y) (+ x y))))
(fold f 0 l)) ; 0 is an initial value
----
Of course, this can be written as follows.
[source, lisp]
----
; summation
(fold + 0 '(20 50 60))
----
== Macro
Macros can be defined by `macro`.
Each rule consists of a pattern and a template, and the first matching rule is expanded.
[source, lisp]
----
(macro add
((add $e1 $e2) (+ $e1 $e2))
((add $e1 $e2 $e3 ...) (+ $e1 (add $e2 $e3 ...))))
----
Identifiers beginning with `$` are pattern variables.
They are substituted with the expressions matched at the call site.
`...` can be used after a pattern variable or a template fragment to match and expand the remaining arguments.
[source, lisp]
----
(add 1 2) ; 3
(add 1 2 3 4 5) ; 15
----
Macros can also generate expressions that introduce local bindings.
For example, a temporary variable can be introduced in a lambda expression.
[source, lisp]
----
(macro with_tmp
((_ $x) ((lambda (tmp) (+ tmp $x)) 1)))
(export test (tmp) (Pure (-> (Int) Int))
(with_tmp tmp))
----
BLisp macros are hygienic for local binders introduced by macro templates.
Variables introduced by `lambda` arguments, `let` bindings, and `match` pattern variables are renamed to fresh internal names during expansion, so they do not capture variables from the call site.
Top-level names such as `defun`, `export`, and `data` definitions are not renamed automatically.
== String and Character
_chars_ converts String to (List Char).
[source, lisp]
----
; (Pure (-> (String) (List Char)))
(chars "Hello") ; '(`H` `e` `l` `l` `o`)
----
_str_ converts (List Char) to String.
[source, lisp]
----
; (Pure (-> ((List Char)) String))
(str '(`H` `e` `l` `l` `o`)) ; "Hello"
----
== Foreign Function Interface
_blisp::embedded_ is a macro for foreign function interface.
By using this, Rust's functions can be called from BLisp easily.
For example, first of all, define a Rust function as follows.
[source, rust]
----
use blisp::embedded;
use num_bigint::{BigInt, ToBigInt};
#[embedded]
fn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> Result<BigInt, String> {
let mut result = a + b.0 + b.1;
if let Some(n) = c {
result += n;
}
Ok(result)
}
----
_blisp::embedded_ macro generates a type definition for FFI.
This function can be called from BLisp as follows.
[source, lisp]
----
(export call_add_four_ints (n)
(IO (-> ((Option Int)) (Result Int String)))
(add_four_ints 1 [2 3] n))
----
To register FFIs, a vector of the definition generated by _embedded_ macro
must be passed to _blisp::init_ as follows.
[source, rust]
----
// add_for_ints
let code = "(export call_add_four_ints (n)
(IO (-> ((Option Int)) (Result Int String)))
(add_four_ints 1 [2 3] n)
)";
let exprs = blisp::init(code, vec![Box::new(AddFourInts)]).unwrap();
let ctx = blisp::typing(exprs).unwrap();
let result = blisp::eval("(call_add_four_ints (Some 4))", &ctx).unwrap();
----
The function name is _add_four_ints_, then _AddFourInts_, which is camel case,
must be passed to _blisp::init_ capsulated by _Box_ and _Vec_.
FFIs in Rust take and return only types described as follows.
Other types, like _Vec<u64>_, are not supported,
but _Vec<Option<bool>>_ is accepted.
Types between BLisp and Rust are automatically converted by
the function generated by _embedded_ macro.
.Type Conversion between BLisp and Rust
|===
|BLisp | Rust
|_Int_ | _BigInt_
|_Bool_ | _bool_
|_Char_ | _char_
|_String_ | _String_
|_'(T)_ | _Vec<T>_
|_[T0, T1]_ | _(T0, T1)_
|_(Option T)_ | _Option<T>_
|_(Result T E)_ | _Result<T, E>_
|===
Note that every FFI is treated as IO functions.
== Transpilation to Coq (Experimental)
BLisp experimentally implements a transpiler to Coq.
It can be invoked by calling _blisp::transpile_ as follows.
[source, coq]
----
let expr = "
(defun snoc (l y)
(Pure (-> (
'(t) t)
'(t)))
(match l
(nil (Cons y nil))
((Cons h b) (Cons h (snoc b y)))))
(defun rev (l)
(Pure (-> (
'(t))
'(t)))
(match l
(nil nil)
((Cons h t) (snoc (rev t) h))))
";
let exprs = blisp::init(expr, vec![]).unwrap();
let ctx = blisp::typing(exprs).unwrap();
println!("{}", blisp::transpile(&ctx));
----
This outputs Coq code as follows.
It includes as well as the prelude of BLisp.
[source, coq]
----
Require Import ZArith.
Require Import Coq.Lists.List.
Inductive Option (t: Type): Type :=
| Some (x0: t)
| None.
Arguments Some{t}.
Arguments None{t}.
Inductive Result (t e: Type): Type :=
| Ok (x0: t)
| Err (x0: e).
Arguments Ok{t e}.
Arguments Err{t e}.
Definition car {t: Type} (x: list t): Option t :=
match x with
| (cons n _) => (Some n)
| _ => (None)
end.
Definition cdr {t: Type} (x: list t): list t :=
match x with
| (cons _ l) => l
| _ => nil
end.
Definition filter {t: Type} (f: t -> bool) (x: list t): list t :=
(reverse (filter' f x nil ) ).
Fixpoint filter' {t: Type} (f: t -> bool) (x l: list t): list t :=
match x with
| (cons h a) => match (f h ) with
| true => (filter' f a (cons h l) )
| false => (filter' f a l )
end
| _ => l
end.
Fixpoint fold {a b: Type} (f: a -> b -> b) (init: b) (x: list a): b :=
match x with
| (cons h l) => (fold f (f h init ) l )
| _ => init
end.
Fixpoint map {a b: Type} (f: a -> b) (x: list a): list b :=
match x with
| (cons h l) => (cons (f h ) (map f l ))
| _ => nil
end.
Fixpoint rev {t: Type} (l: list t): list t :=
match l with
| nil => nil
| (cons h t) => (snoc (rev t ) h )
end.
Definition reverse {t: Type} (x: list t): list t :=
(reverse' x nil ).
Fixpoint reverse' {t: Type} (x l: list t): list t :=
match x with
| (cons h a) => (reverse' a (cons h l) )
| _ => l
end.
Fixpoint snoc {t: Type} (l: list t) (y: t): list t :=
match l with
| nil => (cons y nil)
| (cons h b) => (cons h (snoc b y ))
end.
----
Not that this transpiler is experimental.
So, Coq cannot interpret some outputs.
Please fix it manually when you encounter that situation.
It is probably easy.
== Examples
=== Reverse
_reverse_ is a internally defined function. It reverses order of a list.
[source, lisp]
----
(reverse '(1 2 3 4 5 6 7 8 9))
----
This outputs as follows.
'(9 8 7 6 5 4 3 2 1)
=== Filter
_filter_ is a internally defined function. It filters the elements in a list.
[source, lisp]
----
(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9))
----
This outputs as follows.
'(2 4 6 8)
_filter_'s type is as follows.
[source, lisp]
----
(Pure (->
((Pure (-> (t) Bool)) ; take a function
'(t)) ; take a list
'(t))) ; return a list
----
=== Factorial
Tail call factorial can be coded as follows.
[source, lisp]
----
(export factorial (n) (Pure (-> (Int) Int))
(fact n 1))
(defun fact (n total) (Pure (-> (Int Int) Int))
(if (<= n 0)
total
(fact (- n 1) (* n total))))
----
This function can be called as follows.
>> (factorial 10)
3628800
>>
>> (factorial 1000)
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
>>
>> (factorial 100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
>>
>> (factorial 500)
1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
================================================
FILE: docs/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.20">
<meta name="author" content="Yuuki Takano">
<title>BLisp: A Statically Typed Lisp Like Language</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>*>tr>*{border-width:1px}
table.grid-cols>*>tr>*{border-width:0 1px}
table.grid-rows>*>tr>*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li>p:empty:only-child::before{content:"";display:inline-block}
ul.checklist>li>p:first-child{margin-left:-1em}
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
<style>
pre.pygments .hll { background-color: #ffffcc }
pre.pygments { background: #f8f8f8; }
pre.pygments .tok-c { color: #3D7B7B; font-style: italic } /* Comment */
pre.pygments .tok-err { border: 1px solid #FF0000 } /* Error */
pre.pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */
pre.pygments .tok-o { color: #666666 } /* Operator */
pre.pygments .tok-ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
pre.pygments .tok-cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
pre.pygments .tok-cp { color: #9C6500 } /* Comment.Preproc */
pre.pygments .tok-cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
pre.pygments .tok-c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
pre.pygments .tok-cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
pre.pygments .tok-gd { color: #A00000 } /* Generic.Deleted */
pre.pygments .tok-ge { font-style: italic } /* Generic.Emph */
pre.pygments .tok-ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
pre.pygments .tok-gr { color: #E40000 } /* Generic.Error */
pre.pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */
pre.pygments .tok-gi { color: #008400 } /* Generic.Inserted */
pre.pygments .tok-go { color: #717171 } /* Generic.Output */
pre.pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */
pre.pygments .tok-gs { font-weight: bold } /* Generic.Strong */
pre.pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */
pre.pygments .tok-gt { color: #0044DD } /* Generic.Traceback */
pre.pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */
pre.pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
pre.pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
pre.pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */
pre.pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
pre.pygments .tok-kt { color: #B00040 } /* Keyword.Type */
pre.pygments .tok-m { color: #666666 } /* Literal.Number */
pre.pygments .tok-s { color: #BA2121 } /* Literal.String */
pre.pygments .tok-na { color: #687822 } /* Name.Attribute */
pre.pygments .tok-nb { color: #008000 } /* Name.Builtin */
pre.pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */
pre.pygments .tok-no { color: #880000 } /* Name.Constant */
pre.pygments .tok-nd { color: #AA22FF } /* Name.Decorator */
pre.pygments .tok-ni { color: #717171; font-weight: bold } /* Name.Entity */
pre.pygments .tok-ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
pre.pygments .tok-nf { color: #0000FF } /* Name.Function */
pre.pygments .tok-nl { color: #767600 } /* Name.Label */
pre.pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
pre.pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */
pre.pygments .tok-nv { color: #19177C } /* Name.Variable */
pre.pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
pre.pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */
pre.pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */
pre.pygments .tok-mf { color: #666666 } /* Literal.Number.Float */
pre.pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */
pre.pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */
pre.pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */
pre.pygments .tok-sa { color: #BA2121 } /* Literal.String.Affix */
pre.pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */
pre.pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */
pre.pygments .tok-dl { color: #BA2121 } /* Literal.String.Delimiter */
pre.pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
pre.pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */
pre.pygments .tok-se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
pre.pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */
pre.pygments .tok-si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
pre.pygments .tok-sx { color: #008000 } /* Literal.String.Other */
pre.pygments .tok-sr { color: #A45A77 } /* Literal.String.Regex */
pre.pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */
pre.pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */
pre.pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */
pre.pygments .tok-fm { color: #0000FF } /* Name.Function.Magic */
pre.pygments .tok-vc { color: #19177C } /* Name.Variable.Class */
pre.pygments .tok-vg { color: #19177C } /* Name.Variable.Global */
pre.pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */
pre.pygments .tok-vm { color: #19177C } /* Name.Variable.Magic */
pre.pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
</head>
<body class="article">
<div id="header">
<h1>BLisp: A Statically Typed Lisp Like Language</h1>
<div class="details">
<span id="author" class="author">Yuuki Takano</span><br>
<span id="email" class="email"><a href="mailto:ytakano@wide.ad.jp">ytakano@wide.ad.jp</a></span><br>
<span id="revnumber">version 0.4.0,</span>
<span id="revdate">2023-02</span>
</div>
<div id="toc" class="toc">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_features">1. Features</a></li>
<li><a href="#_values">2. Values</a></li>
<li><a href="#_basic_types">3. Basic Types</a></li>
<li><a href="#_function_definition">4. Function Definition</a></li>
<li><a href="#_arithmetic_operations">5. Arithmetic Operations</a></li>
<li><a href="#_boolean_operations">6. Boolean Operations</a></li>
<li><a href="#_comparison">7. Comparison</a></li>
<li><a href="#_bitwise_operations">8. Bitwise Operations</a></li>
<li><a href="#_mathematical_operations">9. Mathematical Operations</a></li>
<li><a href="#_algebraic_data_type">10. Algebraic Data Type</a></li>
<li><a href="#_generics">11. Generics</a></li>
<li><a href="#_generic_function">12. Generic Function</a></li>
<li><a href="#_if_expression">13. If Expression</a></li>
<li><a href="#_match_expression">14. Match Expression</a></li>
<li><a href="#_let_expression">15. Let Expression</a></li>
<li><a href="#_lambda_expression">16. Lambda Expression</a></li>
<li><a href="#_macro">17. Macro</a></li>
<li><a href="#_string_and_character">18. String and Character</a></li>
<li><a href="#_foreign_function_interface">19. Foreign Function Interface</a></li>
<li><a href="#_transpilation_to_coq_experimental">20. Transpilation to Coq (Experimental)</a></li>
<li><a href="#_examples">21. Examples</a>
<ul class="sectlevel2">
<li><a href="#_reverse">21.1. Reverse</a></li>
<li><a href="#_filter">21.2. Filter</a></li>
<li><a href="#_factorial">21.3. Factorial</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>BLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.
BLisp supports higher order RPC like higher order functions of functional programming languages.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://github.com/ytakano/blisp">GitHub’s Repository</a></p>
</li>
<li>
<p><a href="https://crates.io/crates/blisp">BLisp’s crates.io</a></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>This repository provides only a library crate.
Please see <a href="https://github.com/ytakano/blisp-repl">blisp-repl</a> to use BLisp,
and <a href="https://github.com/ytakano/baremetalisp">baremetalisp</a> which is a toy OS.</p>
</div>
<div class="paragraph">
<p><a href="https://ytakano.github.io/blisp/index.ja.html">日本語版はこちら</a></p>
</div>
<div class="paragraph">
<div class="title">BLisp on no_std Environment</div>
<p><span class="image"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytakano/20210221/20210221155657.gif" alt="BLisp on no_std Environment"></span></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_features">1. Features</h2>
<div class="sectionbody">
<div class="ulist">
<ul>
<li>
<p>Algebraic data type</p>
</li>
<li>
<p>Generics</p>
</li>
<li>
<p>Hindley–Milner based type inference</p>
</li>
<li>
<p>Effect system to separate side effects from pure functions</p>
</li>
<li>
<p>Big integer</p>
</li>
<li>
<p>Supporting no_std environments</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_values">2. Values</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title">values</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-o">`</span><span class="tok-nv">A</span><span class="tok-o">`</span><span class="tok-w"> </span><span class="tok-c1">; character literal</span>
<span class="tok-s">"Hello"</span><span class="tok-w"> </span><span class="tok-c1">; string literal</span>
<span class="tok-mi">144</span><span class="tok-w"> </span><span class="tok-c1">; integer value</span>
<span class="tok-nv">0xabcDEF</span><span class="tok-w"> </span><span class="tok-c1">; hexadecimal</span>
<span class="tok-nv">0o777</span><span class="tok-w"> </span><span class="tok-c1">; octal</span>
<span class="tok-nv">0b1001</span><span class="tok-w"> </span><span class="tok-c1">; binary</span>
<span class="tok-nv">true</span><span class="tok-w"> </span><span class="tok-c1">; boolean value</span>
<span class="tok-nv">false</span><span class="tok-w"> </span><span class="tok-c1">; boolean value</span>
<span class="tok-nv">[true</span><span class="tok-w"> </span><span class="tok-nv">10]</span><span class="tok-w"> </span><span class="tok-c1">; tuple</span>
<span class="tok-nv">[]</span><span class="tok-w"> </span><span class="tok-c1">; empty tuple</span>
<span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; list</span>
<span class="tok-o">'</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-c1">; empty list, Nil</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_basic_types">3. Basic Types</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title">types</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-nv">Char</span><span class="tok-w"> </span><span class="tok-c1">; character</span>
<span class="tok-nv">String</span><span class="tok-w"> </span><span class="tok-c1">; string</span>
<span class="tok-nv">Int</span><span class="tok-w"> </span><span class="tok-c1">; signed integer</span>
<span class="tok-nv">Bool</span><span class="tok-w"> </span><span class="tok-c1">; boolean</span>
<span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; list of Int</span>
<span class="tok-nv">[Int</span><span class="tok-w"> </span><span class="tok-nv">Bool]</span><span class="tok-w"> </span><span class="tok-c1">; tuple of Int and Bool</span>
<span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Bool</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; Pure function, which takes 2 integers and return boolean value</span>
<span class="tok-p">(</span><span class="tok-nv">IO</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">[]</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; IO function, which takes an integer and return []</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Pure and IO are function effects.
In IO functions, both Pure and IO functions can be called.
However, in Pure functions, calling only Pure functions is permitted.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_function_definition">4. Function Definition</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Functions can be defined by defun or export.
"defun" defines a local function which cannot be called from Rust’s eval function.</p>
</div>
<div class="paragraph">
<p>Suppose following 2 functions.</p>
</div>
<div class="listingblock">
<div class="title">defun</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">defun</span><span class="tok-w"> </span><span class="tok-nv">double</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; function name is "double" and "x" is an argument</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; function Type</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; function body</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">export</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nv">quad</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; function name is "quad" and "x" is an argument</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; function Type</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">double</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">double</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">)))</span><span class="tok-w"> </span><span class="tok-c1">; function body</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>double cannot be called from Rust’s eval, but can be called from internally defined functions.
quad can be called from Rust’s eval, and it calls double internally.</p>
</div>
<div class="paragraph">
<p>This is the code what actually do in Rust.</p>
</div>
<div class="listingblock">
<div class="title">Rust’s eval</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="rust"><span></span><span class="tok-k">use</span><span class="tok-w"> </span><span class="tok-n">blisp</span><span class="tok-p">;</span>
<span class="tok-k">fn</span> <span class="tok-nf">eval</span><span class="tok-p">(</span><span class="tok-n">e</span>: <span class="tok-kp">&</span><span class="tok-kt">str</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">ctx</span>: <span class="tok-kp">&</span><span class="tok-nc">blisp</span>::<span class="tok-n">semantics</span>::<span class="tok-n">Context</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-c1">// evaluate expressions</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">exprs</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-k">match</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">eval</span><span class="tok-p">(</span><span class="tok-n">e</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">ctx</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-nb">Ok</span><span class="tok-p">(</span><span class="tok-n">es</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=></span><span class="tok-w"> </span><span class="tok-n">es</span><span class="tok-p">,</span>
<span class="tok-w"> </span><span class="tok-nb">Err</span><span class="tok-p">(</span><span class="tok-n">err</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=></span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-fm">println!</span><span class="tok-p">(</span><span class="tok-s">"error:{}:{}: {}"</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">err</span><span class="tok-p">.</span><span class="tok-n">pos</span><span class="tok-p">.</span><span class="tok-n">line</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">err</span><span class="tok-p">.</span><span class="tok-n">pos</span><span class="tok-p">.</span><span class="tok-n">column</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">err</span><span class="tok-p">.</span><span class="tok-n">msg</span><span class="tok-p">);</span>
<span class="tok-w"> </span><span class="tok-k">return</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-p">};</span>
<span class="tok-w"> </span><span class="tok-k">for</span><span class="tok-w"> </span><span class="tok-n">r</span><span class="tok-w"> </span><span class="tok-k">in</span><span class="tok-w"> </span><span class="tok-n">exprs</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-k">match</span><span class="tok-w"> </span><span class="tok-n">r</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-nb">Ok</span><span class="tok-p">(</span><span class="tok-n">msg</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=></span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-fm">println!</span><span class="tok-p">(</span><span class="tok-s">"{}"</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">msg</span><span class="tok-p">);</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-nb">Err</span><span class="tok-p">(</span><span class="tok-n">msg</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=></span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-fm">println!</span><span class="tok-p">(</span><span class="tok-s">"error: {}"</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">msg</span><span class="tok-p">);</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-p">}</span>
<span class="tok-k">fn</span> <span class="tok-nf">main</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-c1">// internal code</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">code</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">"</span>
<span class="tok-s">(defun double (x) ; function name is double and x is an argument</span>
<span class="tok-s"> (Pure (-> (Int) Int)) ; function Type</span>
<span class="tok-s"> (* 2 x)) ; function body</span>
<span class="tok-s">(export quad (x) ; function name is quad and x is an argument</span>
<span class="tok-s"> (Pure (-> (Int) Int)) ; function Type</span>
<span class="tok-s"> (double (double x))) ; function body</span>
<span class="tok-s">"</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">exprs</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">init</span><span class="tok-p">(</span><span class="tok-n">code</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-fm">vec!</span><span class="tok-p">[]).</span><span class="tok-n">unwrap</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">ctx</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">typing</span><span class="tok-p">(</span><span class="tok-o">&</span><span class="tok-n">exprs</span><span class="tok-p">).</span><span class="tok-n">unwrap</span><span class="tok-p">();</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">e</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">"(double 10) ; error"</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-n">eval</span><span class="tok-p">(</span><span class="tok-n">e</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-o">&</span><span class="tok-n">ctx</span><span class="tok-p">);</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">e</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">"(quad 10) ; OK"</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-n">eval</span><span class="tok-p">(</span><span class="tok-n">e</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-o">&</span><span class="tok-n">ctx</span><span class="tok-p">);</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This code output as follows.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>error:0:1: Typing Error: double is not defined
40</pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_arithmetic_operations">5. Arithmetic Operations</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title">basic</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (Int Int) Int))</span>
<span class="tok-p">(</span><span class="tok-nb">+</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb">-</span><span class="tok-w"> </span><span class="tok-mi">30</span><span class="tok-w"> </span><span class="tok-mi">40</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-mi">6</span><span class="tok-w"> </span><span class="tok-mi">100</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb">/</span><span class="tok-w"> </span><span class="tok-mi">100</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nv">%</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">)</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_boolean_operations">6. Boolean Operations</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="title">logical</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (Bool Bool) Bool))</span>
<span class="tok-p">(</span><span class="tok-nb">and</span><span class="tok-w"> </span><span class="tok-nv">true</span><span class="tok-w"> </span><span class="tok-nv">false</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb">or</span><span class="tok-w"> </span><span class="tok-nv">true</span><span class="tok-w"> </span><span class="tok-nv">false</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nv">xor</span><span class="tok-w"> </span><span class="tok-nv">true</span><span class="tok-w"> </span><span class="tok-nv">false</span><span class="tok-p">)</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">negation</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (Bool) Bool))</span>
<span class="tok-p">(</span><span class="tok-nb">not</span><span class="tok-w"> </span><span class="tok-nv">true</span><span class="tok-p">)</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_comparison">7. Comparison</h2>
<div class="sectionbody">
<div class="paragraph">
<p>=, !=, <, >, <=, >= can be used for 2 values whose types are same.</p>
</div>
<div class="listingblock">
<div class="title">comparison between 2 values whose types are same</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (t t) Bool))</span>
<span class="tok-p">(</span><span class="tok-nb">=</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; true</span>
<span class="tok-p">(</span><span class="tok-nv">!=</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; false</span>
<span class="tok-p">(</span><span class="tok-nb">=</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; true</span>
<span class="tok-p">(</span><span class="tok-nb">=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; false</span>
<span class="tok-p">(</span><span class="tok-nb"><</span><span class="tok-w"> </span><span class="tok-mi">6</span><span class="tok-w"> </span><span class="tok-mi">7</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb">></span><span class="tok-w"> </span><span class="tok-mi">6</span><span class="tok-w"> </span><span class="tok-mi">7</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb"><=</span><span class="tok-w"> </span><span class="tok-mi">30</span><span class="tok-w"> </span><span class="tok-mi">40</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb">>=</span><span class="tok-w"> </span><span class="tok-mi">30</span><span class="tok-w"> </span><span class="tok-mi">40</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb"><</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-w"> </span><span class="tok-s">"World"</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nb"><=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>eq</em>, <em>neq</em>, <em>lt</em>, <em>gt</em>, <em>leq</em>, <em>geq</em> can be used for any 2 values</p>
</div>
<div class="listingblock">
<div class="title">comparison between any 2 values</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (t1 t1) Bool))</span>
<span class="tok-p">(</span><span class="tok-nv">geq</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; (Some 1) is greater than or qeual to "Hello"</span>
<span class="tok-p">(</span><span class="tok-nb">eq</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-w"> </span><span class="tok-mi">100</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; Is "Hello" qeual to 100?</span>
<span class="tok-p">(</span><span class="tok-nv">neq</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-w"> </span><span class="tok-mi">100</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; Is "Hello" not equal to 100?</span>
<span class="tok-p">(</span><span class="tok-nv">lt</span><span class="tok-w"> </span><span class="tok-mi">100</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; Is 100 less than (Some 20)?</span>
<span class="tok-p">(</span><span class="tok-nv">gt</span><span class="tok-w"> </span><span class="tok-mi">200</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; Is 200 greater than "Hello"</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_bitwise_operations">8. Bitwise Operations</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">band</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; bitwise and</span>
<span class="tok-p">(</span><span class="tok-nv">band</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; bitwise and</span>
<span class="tok-p">(</span><span class="tok-nv">bor</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; bitwise or</span>
<span class="tok-p">(</span><span class="tok-nv">bor</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; bitwise or</span>
<span class="tok-p">(</span><span class="tok-nv">bxor</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; bitwise xor</span></code></pre>
</div>
</div>
<div class="listingblock">
<div class="title">bit shift</div>
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (Int Int) (Option Int)))</span>
<span class="tok-p">(</span><span class="tok-nv"><<</span><span class="tok-w"> </span><span class="tok-mi">8</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; (Some 128)</span>
<span class="tok-p">(</span><span class="tok-nv">>></span><span class="tok-w"> </span><span class="tok-mi">128</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; (Some 8)</span>
<span class="tok-p">(</span><span class="tok-nv">>></span><span class="tok-w"> </span><span class="tok-mi">-128</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; (Some -8)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If 2nd argument is greater or equal to 2<sup>64</sup>, then these function return None.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_mathematical_operations">9. Mathematical Operations</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (Int Int) (Option Int)))</span>
<span class="tok-p">(</span><span class="tok-nv">pow</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; (Some 100000000000000000000)</span>
<span class="tok-c1">; (Pure (-> (Int) (Option Int)))</span>
<span class="tok-p">(</span><span class="tok-nb">sqrt</span><span class="tok-w"> </span><span class="tok-mi">16</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; (Some 4)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If <em>pow</em>'s exponent portion is greater or equal to 2<sup>32</sup>, then <em>pow</em> returns None.</p>
</div>
<div class="paragraph">
<p>If <em>sqrt</em>'s argument is less than 0. then <em>sqrt</em> returns None.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_algebraic_data_type">10. Algebraic Data Type</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Algebraic data type can be defined as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; in BLisp</span>
<span class="tok-p">(</span><span class="tok-nv">data</span><span class="tok-w"> </span><span class="tok-nv">Cardinal</span><span class="tok-w"> </span><span class="tok-c1">; type name</span>
<span class="tok-w"> </span><span class="tok-nv">East</span><span class="tok-w"> </span><span class="tok-c1">; value</span>
<span class="tok-w"> </span><span class="tok-nv">North</span><span class="tok-w"> </span><span class="tok-c1">; value</span>
<span class="tok-w"> </span><span class="tok-nv">West</span><span class="tok-w"> </span><span class="tok-c1">; value</span>
<span class="tok-w"> </span><span class="tok-nv">South</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; value</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Type name’s and its value’s first character must be uppercase.
This is equivalent to Rust’s following code.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="rust"><span></span><span class="tok-c1">// in Rust</span>
<span class="tok-k">enum</span> <span class="tok-nc">Cardinal</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">East</span><span class="tok-p">,</span>
<span class="tok-w"> </span><span class="tok-n">North</span><span class="tok-p">,</span>
<span class="tok-w"> </span><span class="tok-n">West</span><span class="tok-p">,</span>
<span class="tok-w"> </span><span class="tok-n">South</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Each element can have values as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; in BLisp</span>
<span class="tok-p">(</span><span class="tok-nv">data</span><span class="tok-w"> </span><span class="tok-nv">Dim2</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Dim2</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; Dim2 has integers</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Dim2 can be instantiated as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">Dim2</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This type is equivalent to Rust’s following type.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="rust"><span></span><span class="tok-c1">// in Rust</span>
<span class="tok-k">use</span><span class="tok-w"> </span><span class="tok-n">num_bigint</span>::<span class="tok-n">BigInt</span><span class="tok-p">;</span>
<span class="tok-k">enum</span> <span class="tok-nc">Dim2</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">Dim2</span><span class="tok-p">(</span><span class="tok-n">BigInt</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">BigInt</span><span class="tok-p">)</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_generics">11. Generics</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Option and Result types are defined internally.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">data</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Option</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-nv">None</span><span class="tok-p">)</span>
<span class="tok-p">(</span><span class="tok-nv">data</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Result</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-w"> </span><span class="tok-nv">e</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Ok</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Err</span><span class="tok-w"> </span><span class="tok-nv">e</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>t</em> and <em>e</em> are type variables.
This code is equivalent to Rust’s following code.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="rust"><span></span><span class="tok-c1">// in Rust</span>
<span class="tok-k">enum</span> <span class="tok-nb">Option</span><span class="tok-o"><</span><span class="tok-n">T</span><span class="tok-o">></span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-nb">Some</span><span class="tok-p">(</span><span class="tok-n">T</span><span class="tok-p">),</span>
<span class="tok-w"> </span><span class="tok-nb">None</span><span class="tok-p">,</span>
<span class="tok-p">}</span>
<span class="tok-k">enum</span> <span class="tok-nb">Result</span><span class="tok-o"><</span><span class="tok-n">T</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">E</span><span class="tok-o">></span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-nb">Ok</span><span class="tok-p">(</span><span class="tok-n">T</span><span class="tok-p">),</span>
<span class="tok-w"> </span><span class="tok-nb">Err</span><span class="tok-p">(</span><span class="tok-n">E</span><span class="tok-p">),</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>List type is a built-in type as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">data</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">List</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">List</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-no">Nil</span><span class="tok-p">)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>So, following 2 lists are equivalent.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-w"> </span><span class="tok-no">Nil</span><span class="tok-p">)))</span>
<span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">)</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_generic_function">12. Generic Function</h2>
<div class="sectionbody">
<div class="paragraph">
<p><em>car</em> and <em>cdr</em> are internally defined generic functions.
These definitions are as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nb">car</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-no">t</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Option</span><span class="tok-w"> </span><span class="tok-no">t</span><span class="tok-p">)))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-nv">x</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-nv">_</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-nv">None</span><span class="tok-p">)))</span>
<span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nb">cdr</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-no">t</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-no">t</span><span class="tok-p">)))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-nv">x</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">())))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>t</em> is a type variable. These functions can be used as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">car</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">3</span><span class="tok-w"> </span><span class="tok-mi">8</span><span class="tok-w"> </span><span class="tok-mi">9</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; returns (Some 3)</span>
<span class="tok-p">(</span><span class="tok-nb">cdr</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">8</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; returns '(10 4)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Normal and type variables' first character must be lowercase.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_if_expression">13. If Expression</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Straightforward.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb"><</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">())</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_match_expression">14. Match Expression</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A list can be matched as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-nv">_</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-o">'</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The expression</p>
</div>
<div class="literalblock">
<div class="content">
<pre>(Cons n _)</pre>
</div>
</div>
<div class="paragraph">
<p>is a pattern.
If the pattern is matched to '(1 2 3), 1 is assigned to a variable <em>n</em>. Then, <em>n</em>, namely 1, is returned.</p>
</div>
<div class="paragraph">
<p>This is an example of pattern matching of tuple.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-nv">[1</span><span class="tok-w"> </span><span class="tok-nv">3]</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">[x</span><span class="tok-w"> </span><span class="tok-nv">y]</span><span class="tok-w"> </span><span class="tok-nv">[y</span><span class="tok-w"> </span><span class="tok-nv">x]</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This code swap 1st and 2nd elements of the tuple.</p>
</div>
<div class="paragraph">
<p>Integer values can be also used for pattern matching.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-mi">20</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-mi">20</span><span class="tok-w"> </span><span class="tok-nv">true</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-nv">false</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>More complex example is a as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-nv">[</span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">true]</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">[</span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">false]</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">[</span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">true]</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>BLisp checks exhaustively of pattern.
So, following code will be rejected.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-o">'</span><span class="tok-p">()</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">))</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_let_expression">15. Let Expression</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let expression is used to bind variables as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-k">let</span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">y</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; x is 10, y is 20</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">))</span>
<span class="tok-p">(</span><span class="tok-k">let</span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">)))</span><span class="tok-w"> </span><span class="tok-c1">; x = 10, x = x * x, x = x * x</span>
<span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Destructuring can be also performed as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-k">let</span><span class="tok-w"> </span><span class="tok-p">(((</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Some</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-p">)))</span><span class="tok-w"> </span><span class="tok-c1">; x is 10</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">))</span>
<span class="tok-p">(</span><span class="tok-k">let</span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">[x</span><span class="tok-w"> </span><span class="tok-nv">y]</span><span class="tok-w"> </span><span class="tok-nv">[10</span><span class="tok-w"> </span><span class="tok-nv">20]</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; x is 10, y is 20</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">))</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_lambda_expression">16. Lambda Expression</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Lambda expression is defined as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-k">lambda</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This lambda takes 2 integers and return the multiplication.
Applying arguments to this is simple as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">((</span><span class="tok-k">lambda</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-mi">10</span><span class="tok-w"> </span><span class="tok-mi">20</span><span class="tok-p">)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Every lambda expression is Pure.
IO functions cannot be called in any lambda expressions.</p>
</div>
<div class="paragraph">
<p><em>map</em> and <em>fold</em> functions are internally defined as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nb">map</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">a</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">b</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-nv">a</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-nv">b</span><span class="tok-p">)))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-nv">x</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-nv">h</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-nv">h</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">map</span><span class="tok-w"> </span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">)))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">())))</span>
<span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nv">fold</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-nv">init</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">a</span><span class="tok-w"> </span><span class="tok-nv">b</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">b</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-nv">b</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-nv">a</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-nv">b</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">match</span><span class="tok-w"> </span><span class="tok-nv">x</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Cons</span><span class="tok-w"> </span><span class="tok-nv">h</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">fold</span><span class="tok-w"> </span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-nv">h</span><span class="tok-w"> </span><span class="tok-nv">init</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-nv">init</span><span class="tok-p">)))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>map</em> can be used to apply functions to elements of a list as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; square each element</span>
<span class="tok-p">(</span><span class="tok-k">let</span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">l</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-k">lambda</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-p">))))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">map</span><span class="tok-w"> </span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>fold</em> can be used to calculate over elements of a list.
For example, summation can be computed as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; summation</span>
<span class="tok-p">(</span><span class="tok-k">let</span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">l</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">20</span><span class="tok-w"> </span><span class="tok-mi">50</span><span class="tok-w"> </span><span class="tok-mi">60</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-k">lambda</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">+</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-nv">y</span><span class="tok-p">))))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">fold</span><span class="tok-w"> </span><span class="tok-nv">f</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-w"> </span><span class="tok-nv">l</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; 0 is an initial value</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Of course, this can be written as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; summation</span>
<span class="tok-p">(</span><span class="tok-nv">fold</span><span class="tok-w"> </span><span class="tok-nb">+</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">20</span><span class="tok-w"> </span><span class="tok-mi">50</span><span class="tok-w"> </span><span class="tok-mi">60</span><span class="tok-p">))</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_macro">17. Macro</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Macros can be defined by <code>macro</code>.
Each rule consists of a pattern and a template, and the first matching rule is expanded.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">macro</span><span class="tok-w"> </span><span class="tok-nv">add</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">add</span><span class="tok-w"> </span><span class="tok-nv">$e1</span><span class="tok-w"> </span><span class="tok-nv">$e2</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">+</span><span class="tok-w"> </span><span class="tok-nv">$e1</span><span class="tok-w"> </span><span class="tok-nv">$e2</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">add</span><span class="tok-w"> </span><span class="tok-nv">$e1</span><span class="tok-w"> </span><span class="tok-nv">$e2</span><span class="tok-w"> </span><span class="tok-nv">$e3</span><span class="tok-w"> </span><span class="tok-o">...</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">+</span><span class="tok-w"> </span><span class="tok-nv">$e1</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">add</span><span class="tok-w"> </span><span class="tok-nv">$e2</span><span class="tok-w"> </span><span class="tok-nv">$e3</span><span class="tok-w"> </span><span class="tok-o">...</span><span class="tok-p">))))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Identifiers beginning with <code>$</code> are pattern variables.
They are substituted with the expressions matched at the call site.
<code>…​</code> can be used after a pattern variable or a template fragment to match and expand the remaining arguments.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">add</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; 3</span>
<span class="tok-p">(</span><span class="tok-nv">add</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-w"> </span><span class="tok-mi">5</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; 15</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Macros can also generate expressions that introduce local bindings.
For example, a temporary variable can be introduced in a lambda expression.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">macro</span><span class="tok-w"> </span><span class="tok-nv">with_tmp</span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">_</span><span class="tok-w"> </span><span class="tok-nv">$x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-k">lambda</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">tmp</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">+</span><span class="tok-w"> </span><span class="tok-nv">tmp</span><span class="tok-w"> </span><span class="tok-nv">$x</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)))</span>
<span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nv">test</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">tmp</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">with_tmp</span><span class="tok-w"> </span><span class="tok-nv">tmp</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>BLisp macros are hygienic for local binders introduced by macro templates.
Variables introduced by <code>lambda</code> arguments, <code>let</code> bindings, and <code>match</code> pattern variables are renamed to fresh internal names during expansion, so they do not capture variables from the call site.
Top-level names such as <code>defun</code>, <code>export</code>, and <code>data</code> definitions are not renamed automatically.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_string_and_character">18. String and Character</h2>
<div class="sectionbody">
<div class="paragraph">
<p><em>chars</em> converts String to (List Char).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> (String) (List Char)))</span>
<span class="tok-p">(</span><span class="tok-nv">chars</span><span class="tok-w"> </span><span class="tok-s">"Hello"</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-c1">; '(`H` `e` `l` `l` `o`)</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>str</em> converts (List Char) to String.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-c1">; (Pure (-> ((List Char)) String))</span>
<span class="tok-p">(</span><span class="tok-nv">str</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-o">`</span><span class="tok-nv">H</span><span class="tok-o">`</span><span class="tok-w"> </span><span class="tok-o">`</span><span class="tok-nv">e</span><span class="tok-o">`</span><span class="tok-w"> </span><span class="tok-o">`</span><span class="tok-nv">l</span><span class="tok-o">`</span><span class="tok-w"> </span><span class="tok-o">`</span><span class="tok-nv">l</span><span class="tok-o">`</span><span class="tok-w"> </span><span class="tok-o">`</span><span class="tok-nv">o</span><span class="tok-o">`</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; "Hello"</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_foreign_function_interface">19. Foreign Function Interface</h2>
<div class="sectionbody">
<div class="paragraph">
<p><em>blisp::embedded</em> is a macro for foreign function interface.
By using this, Rust’s functions can be called from BLisp easily.</p>
</div>
<div class="paragraph">
<p>For example, first of all, define a Rust function as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="rust"><span></span><span class="tok-k">use</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">embedded</span><span class="tok-p">;</span>
<span class="tok-k">use</span><span class="tok-w"> </span><span class="tok-n">num_bigint</span>::<span class="tok-p">{</span><span class="tok-n">BigInt</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">ToBigInt</span><span class="tok-p">};</span>
<span class="tok-cp">#[embedded]</span>
<span class="tok-k">fn</span> <span class="tok-nf">add_four_ints</span><span class="tok-p">(</span><span class="tok-n">a</span>: <span class="tok-nc">BigInt</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">b</span>: <span class="tok-p">(</span><span class="tok-n">BigInt</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-n">BigInt</span><span class="tok-p">),</span><span class="tok-w"> </span><span class="tok-n">c</span>: <span class="tok-nb">Option</span><span class="tok-o"><</span><span class="tok-n">BigInt</span><span class="tok-o">></span><span class="tok-p">)</span><span class="tok-w"> </span>-> <span class="tok-nb">Result</span><span class="tok-o"><</span><span class="tok-n">BigInt</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-nb">String</span><span class="tok-o">></span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-k">mut</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">a</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">b</span><span class="tok-p">.</span><span class="tok-mi">0</span><span class="tok-w"> </span><span class="tok-o">+</span><span class="tok-w"> </span><span class="tok-n">b</span><span class="tok-p">.</span><span class="tok-mi">1</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-nb">Some</span><span class="tok-p">(</span><span class="tok-n">n</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">c</span><span class="tok-w"> </span><span class="tok-p">{</span>
<span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">+=</span><span class="tok-w"> </span><span class="tok-n">n</span><span class="tok-p">;</span>
<span class="tok-w"> </span><span class="tok-p">}</span>
<span class="tok-w"> </span><span class="tok-nb">Ok</span><span class="tok-p">(</span><span class="tok-n">result</span><span class="tok-p">)</span>
<span class="tok-p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><em>blisp::embedded</em> macro generates a type definition for FFI.
This function can be called from BLisp as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nv">call_add_four_ints</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">n</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">IO</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Option</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Result</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-w"> </span><span class="tok-nv">String</span><span class="tok-p">)))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">add_four_ints</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-nv">[2</span><span class="tok-w"> </span><span class="tok-nv">3]</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>To register FFIs, a vector of the definition generated by <em>embedded</em> macro
must be passed to <em>blisp::init</em> as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="rust"><span></span><span class="tok-c1">// add_for_ints</span>
<span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">code</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-s">"(export call_add_four_ints (n)</span>
<span class="tok-s"> (IO (-> ((Option Int)) (Result Int String)))</span>
<span class="tok-s"> (add_four_ints 1 [2 3] n)</span>
<span class="tok-s">)"</span><span class="tok-p">;</span>
<span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">exprs</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">init</span><span class="tok-p">(</span><span class="tok-n">code</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-fm">vec!</span><span class="tok-p">[</span><span class="tok-nb">Box</span>::<span class="tok-n">new</span><span class="tok-p">(</span><span class="tok-n">AddFourInts</span><span class="tok-p">)]).</span><span class="tok-n">unwrap</span><span class="tok-p">();</span>
<span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">ctx</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">typing</span><span class="tok-p">(</span><span class="tok-n">exprs</span><span class="tok-p">).</span><span class="tok-n">unwrap</span><span class="tok-p">();</span>
<span class="tok-kd">let</span><span class="tok-w"> </span><span class="tok-n">result</span><span class="tok-w"> </span><span class="tok-o">=</span><span class="tok-w"> </span><span class="tok-n">blisp</span>::<span class="tok-n">eval</span><span class="tok-p">(</span><span class="tok-s">"(call_add_four_ints (Some 4))"</span><span class="tok-p">,</span><span class="tok-w"> </span><span class="tok-o">&</span><span class="tok-n">ctx</span><span class="tok-p">).</span><span class="tok-n">unwrap</span><span class="tok-p">();</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The function name is <em>add_four_ints</em>, then <em>AddFourInts</em>, which is camel case,
must be passed to <em>blisp::init</em> capsulated by <em>Box</em> and <em>Vec</em>.</p>
</div>
<div class="paragraph">
<p>FFIs in Rust take and return only types described as follows.
Other types, like <em>Vec<u64></em>, are not supported,
but <em>Vec<Option<bool>></em> is accepted.
Types between BLisp and Rust are automatically converted by
the function generated by <em>embedded</em> macro.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Type Conversion between BLisp and Rust</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">BLisp</th>
<th class="tableblock halign-left valign-top">Rust</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Int</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>BigInt</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Bool</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>bool</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Char</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>char</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>String</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>String</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>'(T)</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Vec<T></em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>[T0, T1]</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>(T0, T1)</em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>(Option T)</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Option<T></em></p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>(Result T E)</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><em>Result<T, E></em></p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p>Note that every FFI is treated as IO functions.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_transpilation_to_coq_experimental">20. Transpilation to Coq (Experimental)</h2>
<div class="sectionbody">
<div class="paragraph">
<p>BLisp experimentally implements a transpiler to Coq.
It can be invoked by calling <em>blisp::transpile</em> as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="coq"><span></span><span class="tok-k">let</span> <span class="tok-n">expr</span> <span class="tok-o">=</span> <span class="tok-s2">"</span>
<span class="tok-s2">(defun snoc (l y)</span>
<span class="tok-s2">(Pure (-> (</span>
<span class="tok-s2"> '(t) t)</span>
<span class="tok-s2">'(t)))</span>
<span class="tok-s2">(match l</span>
<span class="tok-s2"> (nil (Cons y nil))</span>
<span class="tok-s2"> ((Cons h b) (Cons h (snoc b y)))))</span>
<span class="tok-s2">(defun rev (l)</span>
<span class="tok-s2">(Pure (-> (</span>
<span class="tok-s2"> '(t))</span>
<span class="tok-s2">'(t)))</span>
<span class="tok-s2">(match l</span>
<span class="tok-s2"> (nil nil)</span>
<span class="tok-s2"> ((Cons h t) (snoc (rev t) h))))</span>
<span class="tok-s2"> "</span><span class="tok-o">;</span>
<span class="tok-k">let</span> <span class="tok-n">exprs</span> <span class="tok-o">=</span> <span class="tok-n">blisp</span><span class="tok-o">::</span><span class="tok-n">init</span><span class="tok-o">(</span><span class="tok-n">expr</span><span class="tok-o">,</span> <span class="tok-n">vec</span><span class="tok-o">!</span><span class="tok-bp">[]</span><span class="tok-o">).</span><span class="tok-n">unwrap</span><span class="tok-bp">()</span><span class="tok-o">;</span>
<span class="tok-k">let</span> <span class="tok-n">ctx</span> <span class="tok-o">=</span> <span class="tok-n">blisp</span><span class="tok-o">::</span><span class="tok-n">typing</span><span class="tok-o">(</span><span class="tok-n">exprs</span><span class="tok-o">).</span><span class="tok-n">unwrap</span><span class="tok-bp">()</span><span class="tok-o">;</span>
<span class="tok-n">println</span><span class="tok-o">!(</span><span class="tok-s2">"{}"</span><span class="tok-o">,</span> <span class="tok-n">blisp</span><span class="tok-o">::</span><span class="tok-n">transpile</span><span class="tok-o">(&</span><span class="tok-n">ctx</span><span class="tok-o">));</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This outputs Coq code as follows.
It includes as well as the prelude of BLisp.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="coq"><span></span><span class="tok-kn">Require</span> <span class="tok-kn">Import</span> <span class="tok-n">ZArith</span><span class="tok-o">.</span>
<span class="tok-kn">Require</span> <span class="tok-kn">Import</span> <span class="tok-n">Coq.Lists.List</span><span class="tok-o">.</span>
<span class="tok-kn">Inductive</span> <span class="tok-n">Option</span> <span class="tok-o">(</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">):</span> <span class="tok-kt">Type</span> <span class="tok-o">:=</span>
<span class="tok-o">|</span> <span class="tok-n">Some</span> <span class="tok-o">(</span><span class="tok-n">x0</span><span class="tok-o">:</span> <span class="tok-n">t</span><span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-n">None</span><span class="tok-o">.</span>
<span class="tok-kn">Arguments</span> <span class="tok-n">Some</span><span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">}.</span>
<span class="tok-kn">Arguments</span> <span class="tok-n">None</span><span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">}.</span>
<span class="tok-kn">Inductive</span> <span class="tok-n">Result</span> <span class="tok-o">(</span><span class="tok-n">t</span> <span class="tok-n">e</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">):</span> <span class="tok-kt">Type</span> <span class="tok-o">:=</span>
<span class="tok-o">|</span> <span class="tok-n">Ok</span> <span class="tok-o">(</span><span class="tok-n">x0</span><span class="tok-o">:</span> <span class="tok-n">t</span><span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-n">Err</span> <span class="tok-o">(</span><span class="tok-n">x0</span><span class="tok-o">:</span> <span class="tok-n">e</span><span class="tok-o">).</span>
<span class="tok-kn">Arguments</span> <span class="tok-n">Ok</span><span class="tok-o">{</span><span class="tok-n">t</span> <span class="tok-n">e</span><span class="tok-o">}.</span>
<span class="tok-kn">Arguments</span> <span class="tok-n">Err</span><span class="tok-o">{</span><span class="tok-n">t</span> <span class="tok-n">e</span><span class="tok-o">}.</span>
<span class="tok-kn">Definition</span> <span class="tok-n">car</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">Option</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">x</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">n</span> <span class="tok-o">_)</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">Some</span> <span class="tok-n">n</span><span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-o">_</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">None</span><span class="tok-o">)</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Definition</span> <span class="tok-n">cdr</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">x</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-o">_</span> <span class="tok-n">l</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-n">l</span>
<span class="tok-o">|</span> <span class="tok-o">_</span> <span class="tok-o">=></span> <span class="tok-n">nil</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Definition</span> <span class="tok-n">filter</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">f</span><span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-n">bool</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-o">(</span><span class="tok-n">reverse</span> <span class="tok-o">(</span><span class="tok-n">filter'</span> <span class="tok-n">f</span> <span class="tok-n">x</span> <span class="tok-n">nil</span> <span class="tok-o">)</span> <span class="tok-o">).</span>
<span class="tok-kn">Fixpoint</span> <span class="tok-n">filter'</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">f</span><span class="tok-o">:</span> <span class="tok-n">t</span> <span class="tok-o">-></span> <span class="tok-n">bool</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">x</span> <span class="tok-n">l</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">x</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">a</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-k">match</span> <span class="tok-o">(</span><span class="tok-n">f</span> <span class="tok-n">h</span> <span class="tok-o">)</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-bp">true</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">filter'</span> <span class="tok-n">f</span> <span class="tok-n">a</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">l</span><span class="tok-o">)</span> <span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-bp">false</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">filter'</span> <span class="tok-n">f</span> <span class="tok-n">a</span> <span class="tok-n">l</span> <span class="tok-o">)</span>
<span class="tok-k">end</span>
<span class="tok-o">|</span> <span class="tok-o">_</span> <span class="tok-o">=></span> <span class="tok-n">l</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Fixpoint</span> <span class="tok-k">fold</span> <span class="tok-o">{</span><span class="tok-n">a</span> <span class="tok-n">b</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">f</span><span class="tok-o">:</span> <span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-n">b</span> <span class="tok-o">-></span> <span class="tok-n">b</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">init</span><span class="tok-o">:</span> <span class="tok-n">b</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">a</span><span class="tok-o">):</span> <span class="tok-n">b</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">x</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">l</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-k">fold</span> <span class="tok-n">f</span> <span class="tok-o">(</span><span class="tok-n">f</span> <span class="tok-n">h</span> <span class="tok-n">init</span> <span class="tok-o">)</span> <span class="tok-n">l</span> <span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-o">_</span> <span class="tok-o">=></span> <span class="tok-n">init</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Fixpoint</span> <span class="tok-n">map</span> <span class="tok-o">{</span><span class="tok-n">a</span> <span class="tok-n">b</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">f</span><span class="tok-o">:</span> <span class="tok-n">a</span> <span class="tok-o">-></span> <span class="tok-n">b</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">a</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">b</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">x</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">l</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-o">(</span><span class="tok-n">f</span> <span class="tok-n">h</span> <span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">map</span> <span class="tok-n">f</span> <span class="tok-n">l</span> <span class="tok-o">))</span>
<span class="tok-o">|</span> <span class="tok-o">_</span> <span class="tok-o">=></span> <span class="tok-n">nil</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Fixpoint</span> <span class="tok-n">rev</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">l</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">l</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-n">nil</span> <span class="tok-o">=></span> <span class="tok-n">nil</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">t</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">snoc</span> <span class="tok-o">(</span><span class="tok-n">rev</span> <span class="tok-n">t</span> <span class="tok-o">)</span> <span class="tok-n">h</span> <span class="tok-o">)</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Definition</span> <span class="tok-n">reverse</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">x</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-o">(</span><span class="tok-n">reverse'</span> <span class="tok-n">x</span> <span class="tok-n">nil</span> <span class="tok-o">).</span>
<span class="tok-kn">Fixpoint</span> <span class="tok-n">reverse'</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">x</span> <span class="tok-n">l</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">x</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">a</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">reverse'</span> <span class="tok-n">a</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">l</span><span class="tok-o">)</span> <span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-o">_</span> <span class="tok-o">=></span> <span class="tok-n">l</span>
<span class="tok-k">end</span><span class="tok-o">.</span>
<span class="tok-kn">Fixpoint</span> <span class="tok-n">snoc</span> <span class="tok-o">{</span><span class="tok-n">t</span><span class="tok-o">:</span> <span class="tok-kt">Type</span><span class="tok-o">}</span> <span class="tok-o">(</span><span class="tok-n">l</span><span class="tok-o">:</span> <span class="tok-n">list</span> <span class="tok-n">t</span><span class="tok-o">)</span> <span class="tok-o">(</span><span class="tok-n">y</span><span class="tok-o">:</span> <span class="tok-n">t</span><span class="tok-o">):</span> <span class="tok-n">list</span> <span class="tok-n">t</span> <span class="tok-o">:=</span>
<span class="tok-k">match</span> <span class="tok-n">l</span> <span class="tok-k">with</span>
<span class="tok-o">|</span> <span class="tok-n">nil</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">y</span> <span class="tok-n">nil</span><span class="tok-o">)</span>
<span class="tok-o">|</span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-n">b</span><span class="tok-o">)</span> <span class="tok-o">=></span> <span class="tok-o">(</span><span class="tok-n">cons</span> <span class="tok-n">h</span> <span class="tok-o">(</span><span class="tok-n">snoc</span> <span class="tok-n">b</span> <span class="tok-n">y</span> <span class="tok-o">))</span>
<span class="tok-k">end</span><span class="tok-o">.</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Not that this transpiler is experimental.
So, Coq cannot interpret some outputs.
Please fix it manually when you encounter that situation.
It is probably easy.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_examples">21. Examples</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_reverse">21.1. Reverse</h3>
<div class="paragraph">
<p><em>reverse</em> is a internally defined function. It reverses order of a list.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">reverse</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-w"> </span><span class="tok-mi">5</span><span class="tok-w"> </span><span class="tok-mi">6</span><span class="tok-w"> </span><span class="tok-mi">7</span><span class="tok-w"> </span><span class="tok-mi">8</span><span class="tok-w"> </span><span class="tok-mi">9</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This outputs as follows.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>'(9 8 7 6 5 4 3 2 1)</pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_filter">21.2. Filter</h3>
<div class="paragraph">
<p><em>filter</em> is a internally defined function. It filters the elements in a list.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">filter</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-k">lambda</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">x</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">=</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">%</span><span class="tok-w"> </span><span class="tok-nv">x</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-mi">1</span><span class="tok-w"> </span><span class="tok-mi">2</span><span class="tok-w"> </span><span class="tok-mi">3</span><span class="tok-w"> </span><span class="tok-mi">4</span><span class="tok-w"> </span><span class="tok-mi">5</span><span class="tok-w"> </span><span class="tok-mi">6</span><span class="tok-w"> </span><span class="tok-mi">7</span><span class="tok-w"> </span><span class="tok-mi">8</span><span class="tok-w"> </span><span class="tok-mi">9</span><span class="tok-p">))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This outputs as follows.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>'(2 4 6 8)</pre>
</div>
</div>
<div class="paragraph">
<p><em>filter</em>'s type is as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span>
<span class="tok-w"> </span><span class="tok-p">((</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-no">t</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Bool</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; take a function</span>
<span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-no">t</span><span class="tok-p">))</span><span class="tok-w"> </span><span class="tok-c1">; take a list</span>
<span class="tok-w"> </span><span class="tok-o">'</span><span class="tok-p">(</span><span class="tok-no">t</span><span class="tok-p">)))</span><span class="tok-w"> </span><span class="tok-c1">; return a list</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_factorial">21.3. Factorial</h3>
<div class="paragraph">
<p>Tail call factorial can be coded as follows.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="lisp"><span></span><span class="tok-p">(</span><span class="tok-nb">export</span><span class="tok-w"> </span><span class="tok-nv">factorial</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">n</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">fact</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">))</span>
<span class="tok-p">(</span><span class="tok-nb">defun</span><span class="tok-w"> </span><span class="tok-nv">fact</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-nv">total</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Pure</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">-></span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">Int</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-nv">Int</span><span class="tok-p">))</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-k">if</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb"><=</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-mi">0</span><span class="tok-p">)</span>
<span class="tok-w"> </span><span class="tok-nv">total</span>
<span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nv">fact</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">-</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-mi">1</span><span class="tok-p">)</span><span class="tok-w"> </span><span class="tok-p">(</span><span class="tok-nb">*</span><span class="tok-w"> </span><span class="tok-nv">n</span><span class="tok-w"> </span><span class="tok-nv">total</span><span class="tok-p">))))</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This function can be called as follows.</p>
</div>
<div class="literalblock">
<div class="content">
<pre>>> (factorial 10)
3628800
>>
>> (factorial 1000)
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
>>
>> (factorial 100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
>>
>> (factorial 500)
1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</pre>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="footer">
<div id="footer-text">
Version 0.4.0<br>
Last updated 2026-04-28 09:28:41 +0900
</div>
</div>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
messageStyle: "none",
tex2jax: {
inlineMath: [["\\(", "\\)"]],
displayMath: [["\\[", "\\]"]],
ignoreClass: "nostem|nolatexmath"
},
asciimath2jax: {
delimiters: [["\\$", "\\$"]],
ignoreClass: "nostem|noasciimath"
},
TeX: { equationNumbers: { autoNumber: "none" } }
})
MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
data.math.root.display = "block"
}
return data
})
})
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
</body>
</html>
================================================
FILE: docs/index.ja.adoc
================================================
= BLisp: Lispっぽい静的型付け言語
Yuuki Takano <ytakano@wide.ad.jp>
v0.4.0, 2023-02
:doctype: article
:toc:
:sectnums:
:lang: ja
:encoding: utf-8
:stem: latexmath
:source-highlighter: pygments
BLispは静的型付けされたLispライクなプログラミング言語で、no_std環境用のエフェクトシステムを採用しています。BLispは関数型プログラミング言語の高階関数のような高階のRPCをサポートしています。
* https://github.com/ytakano/blisp[GitHubリポジトリ]
* https://crates.io/crates/blisp[BLispのcrates.io]
本リポジトリではライブラリクレートのみを提供しています。BLispを利用するには https://github.com/ytakano/blisp-repl[blisp-repl] か、おもちゃのOSである https://github.com/ytakano/baremetalisp[baremetalisp] を参照してください。
https://ytakano.github.io/blisp/[English version is here.]
.no_stdで動くBLisp
image:https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytakano/20210221/20210221155657.gif[no_stdで動くBLisp]
== 特徴
* 代数的データ型
* ジェネリクス
* 型推論
* IOと純粋な関数を分離するためのエフェクトシステム
* 多倍長整数
* no_std環境のサポート
== 値
.values
[source, lisp]
----
`A` ; 文字リテラル
"Hello" ; 文字列リテラル
144 ; 整数値
0xabcDEF ; 16進数
0o777 ; 8進数
0b1001 ; 2進数
true ; 真偽値
false ; 真偽値
[true 10] ; タプル
[] ; 空のタプル
'(1 2 3) ; リスト
'() ; 空のリスト、Nil
----
== 基本型
.types
[source, lisp]
----
Char ; 文字型
String ; 文字列型
Int ; 整数型
Bool ; 真偽値型
'(Int) ; Int型のリスト型
[Int Bool] ; Int型とBool型のタプル型
(Pure (-> (Int Int) Bool)) ; Int型の値を2つとり、Bool型の値をリターンする純粋な関数
(IO (-> (Int) [])) ; Int型の値をとり[]をリターンするIOのある関数
----
PureとIOは関数の効果です。IO関数内では、Pure関数とIO関数の両方を呼び出すことができます。しかし、Pure関数内では、Pure関数の呼び出しのみ許可されています。
== 関数定義
関数はdefunやexportで定義することができます。"defun"はRustのeval関数からは呼び出せないローカル関数を定義します。
以下の2つの関数があるとしましょう。
.defun
[source, lisp]
----
(defun double (x) ; 関数名がdoubleでxは引数
(Pure (-> (Int) Int)) ; 関数の型
(* 2 x)) ; 関数の中身
----
.export
[source, lisp]
----
(export quad (x) ; 関数名がquadで引数はx
(Pure (-> (Int) Int)) ; 関数の型
(double (double x))) ; 関数の中身
----
doubleはRustのevalからは呼び出せませんが、内部で定義された関数からは呼び出せます。quadはRustのevalから呼び出すことができ、内部的にdoubleを呼び出します。
これはRustで実際に行うコードです。
.Rust's eval
[source, rust]
----
use blisp;
fn eval(e: &str, ctx: &blisp::semantics::Context) {
// evaluate expressions
let exprs = match blisp::eval(e, ctx) {
Ok(es) => es,
Err(err) => {
println!("error:{}:{}: {}", err.pos.line, err.pos.column, err.msg);
return;
}
};
for r in exprs {
match r {
Ok(msg) => {
println!("{}", msg);
}
Err(msg) => {
println!("error: {}", msg);
}
}
}
}
fn main() {
// internal code
let code = "
(defun double (x) ; 関数名がdoubleでxは引数
(Pure (-> (Int) Int)) ; 関数の型
(* 2 x)) ; 関数の中身
(export quad (x) ; 関数名がquadで引数はx
(Pure (-> (Int) Int)) ; 関数の型
(double (double x))) ; 関数の中身
";
let exprs = blisp::init(code, vec![]).unwrap();
let ctx = blisp::typing(exprs).unwrap();
let e = "(double 10) ; エラー";
eval(e, &ctx);
let e = "(quad 10) ; OK";
eval(e, &ctx);
}
----
このコードは以下のように出力します。
error:0:1: Typing Error: double is not defined
40
== 算術演算
.基本
[source, lisp]
----
; (Pure (-> (Int Int) Int))
(+ 10 20)
(- 30 40)
(* 6 100)
(/ 100 2)
(% 10 3)
----
== 真偽値演算
.logical
[source, lisp]
----
; (Pure (-> (Bool Bool) Bool))
(and true false)
(or true false)
(xor true false)
----
.negation
[source, lisp]
----
; (Pure (-> (Bool) Bool))
(not true)
----
== 比較演算
=, !=, <, >, \<=, >= といった関数は、同じ型の2つの値に対して適用できます。
.comparison between 2 values whose types are same
[source, lisp]
----
; (Pure (-> (t t) Bool))
(= 4 4) ; true
(!= 4 4) ; false
(= "Hello" "Hello") ; true
(= (Some 1) (Some 2)) ; false
(< 6 7)
(> 6 7)
(<= 30 40)
(>= 30 40)
(< "Hello" "World")
(<= (Some 1) (Some 2))
----
_eq_, _neq_, _lt_, _gt_, _leq_, _geq_ といった関数は、異なる型同士の値でも比較可能です。
.comparison between any 2 values
[source, lisp]
----
; (Pure (-> (t1 t1) Bool))
(geq (Some 1) "Hello") ; (Some 1)は"Hello"より大きい、もしくは等しいか?
(eq "Hello" 100) ; "Hello"と100は等しいか?
(neq "Hello" 100) ; "Hello"と100は等しくないか?
(lt 100 (Some 20)) ; 100は(Some 20)より小さいか?
(gt 200 "Hello") ; 200は"Hello"より大きいか?
----
== ビット演算
[source, lisp]
----
(band 1 0) ; ビット積
(band 1 1) ; ビット積
(bor 1 0) ; ビット和
(bor 1 1) ; ビット和
(bxor 1 0) ; ビット排他的論理和
----
.ビットシフト
[source, lisp]
----
; (Pure (-> (Int Int) (Option Int)))
(<< 8 4) ; (Some 128)
(>> 128 4) ; (Some 8)
(>> -128 4) ; (Some -8)
----
2番目の引数が2^64^以上の場合はNoneをリターンします。
== 数学的演算
[source, lisp]
----
; (Pure (-> (Int Int) (Option Int)))
(pow 10 20) ; (Some 100000000000000000000) namely 10^20
; (Pure (-> (Int) (Option Int)))
(sqrt 16) ; (Some 4)
----
powの指数部が2^32^以上の場合は、powはNoneをリターンします。
sqrtの引数が0以下の場合は、sqrtはNoneをリターンします。
== 代数的データ型
代数的データ型は以下のように定義できます。
[source, lisp]
----
; in BLisp
(data Cardinal ; 型名
East ; 値
North ; 値
West ; 値
South) ; 値
----
型名とその値の最初の文字は大文字でなければなりません。これはRustの以下のコードと同等です。
[source, rust]
----
// in Rust
enum Cardinal {
East,
North,
West,
South
}
----
各要素は以下のような値を持つことができます。
[source, lisp]
----
; in BLisp
(data Dim2
(Dim2 Int Int)) ; Dim2は2つのInt型の値を持つ
----
Dim2は以下のようにインスタンス化することができます。
[source, lisp]
----
(Dim2 10 20)
----
この型はRustの以下の型と同等です。
[source, rust]
----
// in Rust
use num_bigint::BigInt;
enum Dim2 {
Dim2(BigInt, BigInt)
}
----
== ジェネリクス
Option型とResult型は内部で定義されています。
[source, lisp]
----
(data (Option t)
(Some t)
None)
(data (Result t e)
(Ok t)
(Err e))
----
_t_ と _e_ は型変数です。このコードは、Rustの以下のコードと同等です。
[source, rust]
----
// in Rust
enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
----
リスト型は以下のような組み込み型です。
[source, lisp]
----
(data (List t)
(Cons t (List t))
Nil)
----
したがって、以下の2つのリストは等価です。
[source, lisp]
----
(Cons 1 (Cons 2 (Cons 3 Nil)))
'(1 2 3)
----
== ジェネリック関数
_car_ と _cdr_ は内部的に定義されたジェネリック関数です。これらの定義は以下の通りです。
[source, lisp]
----
(export car (x) (Pure (-> ('(t)) (Option t)))
(match x
((Cons n _) (Some n))
(_ None)))
(export cdr (x) (Pure (-> ('(t)) '(t)))
(match x
((Cons _ l) l)
(_ '())))
----
t_は型変数です。これらの関数は以下のように使うことができます。
[source, lisp]
----
(car '(3 8 9)) ; returns (Some 3)
(cdr '(8 10 4)) ; returns '(10 4)
----
通常変数と型変数の最初の文字は小文字でなければなりません。
== If式
単純です.
[source, lisp]
----
(if (< 10 20)
'(1 2 3)
'())
----
== Match式
リストは以下のようにマッチさせることができます。
[source, lisp]
----
(match '(1 2 3)
((Cons n _) n)
('() 0))
----
この、
(Cons n _)
という式はパターンです。
パターンが '(1 2 3) にマッチした場合、1は可変変数 _n_ に代入されます。そうすると、_n_ つまり1が返されます。
タプルのパターンマッチングの例です。
[source, lisp]
----
(match [1 3]
([x y] [y x]))
----
このコードはタプルの第1要素と第2要素を入れ替えます。
整数値はパターンマッチングにも使用できます。
[source, lisp]
----
(match 20
(20 true)
(_ false))
----
より複雑な例としては、以下のようなものがあります。
[source, lisp]
----
(match [(Some 10) true]
([(Some 10) false] 1)
([(Some 10) true] 2)
(_ 0))
----
BLispはパターンを網羅的にチェックします。そのため、以下のコードは拒否されます。
[source, lisp]
----
(match '(1 2)
('() 0))
----
== Let式
変数のバインドには、以下のようにLet式を使用します。
[source, lisp]
----
(let ((x 10) (y 20)) ; x is 10, y is 20
(* x y))
(let ((x 10) (x (* x x)) (x (* x x))) ; x = 10, x = x * x, x = x * x
x)
----
また、以下のように分配束縛を行うこともできます。
[source, lisp]
----
(let (((Some x) (Some 10))) ; x is 10
(* x 2))
(let (([x y] [10 20])) ; x is 10, y is 20
(* x y))
----
== ラムダ式
ラムダ式は以下のように定義されます。
[source, lisp]
----
(lambda (x y) (* x y))
----
このラムダは2つの整数を受け取り、それらの乗算を返します。これに引数を適用するのは次のように簡単に行えます。
[source, lisp]
----
((lambda (x y) (* x y)) 10 20)
----
すべてのラムダ式は純粋です。よって、ラムダ式からIO関数を呼び出すことはできません。
_map_ と _fold_ 関数は内部的に以下のように定義されています。
[source, lisp]
----
(export map (f x) (Pure (-> ((Pure (-> (a) b)) '(a)) '(b)))
(match x
((Cons h l) (Cons (f h) (map f l)))
(_ '())))
(export fold (f init x) (Pure (-> ((Pure (-> (a b) b)) b '(a)) b))
(match x
((Cons h l) (fold f (f h init) l))
(_ init)))
----
_map_ を使うと、以下のようにリストの要素に関数を適用することができます。
[source, lisp]
----
; それぞれをの要素を2乗
(let ((l '(1 2 3))
(f (lambda (x) (* x x))))
(map f l))
----
_fold_ を使用して、リストの要素にまたがって計算することができます。例えば、合計は以下のように計算できます。
[source, lisp]
----
; 合計
(let ((l '(20 50 60))
(f (lambda (x y) (+ x y))))
(fold f 0 l)) ; 0 is an initial value
----
当然、これは以下のようにも記述できます。
[source, lisp]
----
; summation
(fold + 0 '(20 50 60))
----
== マクロ
マクロは `macro` で定義できます。
各ルールはパターンとテンプレートの組からなり、最初に一致したルールが展開されます。
[source, lisp]
----
(macro add
((add $e1 $e2) (+ $e1 $e2))
((add $e1 $e2 $e3 ...) (+ $e1 (add $e2 $e3 ...))))
----
`$` で始まる識別子はパターン変数です。
パターン変数には、マクロ呼び出し側で一致した式がそのまま代入されます。
`...` は、パターン変数やテンプレート断片の後ろに置くことで、残りの引数を可変長部分としてまとめて扱えます。
[source, lisp]
----
(add 1 2) ; 3
(add 1 2 3 4 5) ; 15
----
マクロは局所変数を導入する式も生成できます。
たとえば、一時変数を含むラムダ式は以下のように書けます。
[source, lisp]
----
(macro with_tmp
((_ $x) ((lambda (tmp) (+ tmp $x)) 1)))
(export test (tmp) (Pure (-> (Int) Int))
(with_tmp tmp))
----
BLispのマクロは、テンプレートが導入する局所 binder に対して衛生的です。
`lambda` の引数、`let` の束縛、`match` のパターン変数は展開時に fresh な内部名へ自動的にリネームされるため、呼び出し側の同名変数を変数捕捉しません。
一方で、`defun`、`export`、`data` のようなトップレベル名は自動では改名されません。
== 文字列と文字
_chars_ はStringから(List Char)へ変換します。
[source, lisp]
----
; (Pure (-> (String) (List Char)))
(chars "Hello") ; '(`H` `e` `l` `l` `o`)
----
_str_ は(List Char)からStringへ変換します。
[source, lisp]
----
; (Pure (-> ((List Char)) String))
(str '(`H` `e` `l` `l` `o`)) ; "Hello"
----
== 外部関数呼び出し
_blisp::embedded_ は、外部関数呼び出し用のマクロです。
このマクロを利用すると、Rustの関数をBLispから容易に呼び出せるようになります。
たとえば、はじめに、Rustの関数を以下のように定義します。
[source, rust]
----
use blisp::embedded;
use num_bigint::{BigInt, ToBigInt};
#[embedded]
fn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> Result<BigInt, String> {
let mut result = a + b.0 + b.1;
if let Some(n) = c {
result += n;
}
Ok(result)
}
----
_blisp::embedded_ マクロは外部関数呼び出し用の型定義を生成します。
この関数は、以下のようにBLispから呼び出せます。
[source, lisp]
----
(export call_add_four_ints (n)
(IO (-> ((Option Int)) (Result Int String)))
(add_four_ints 1 [2 3] n))
----
外部関数を登録するためには、以下のように、 _embedded_ によって生成される型定義のベクタを
_blisp::init_ に渡します。
[source, rust]
----
// add_for_ints
let code = "(export call_add_four_ints (n)
(IO (-> ((Option Int)) (Result Int String)))
(add_four_ints 1 [2 3] n)
)";
let exprs = blisp::init(code, vec![Box::new(AddFourInts)]).unwrap();
let ctx = blisp::typing(exprs).unwrap();
let result = blisp::eval("(call_add_four_ints (Some 4))", &ctx).unwrap();
----
ここでは、関数名が _add_four_ints_ のため、そのキャメルケースの _AddFourInts_
を _Box_ と _Vec_ に包んで _blisp::init_ に渡さなければなりません。
Rustの外部関数は以下に示される型のみ引数と返り値で利用可能です。
_Vec<u64>_ のような他の型はサポート外ですが、
_Vec<Option<bool>>_ のような型はOKです。
BLispとRustの間の型変換は _embedded_ マクロが生成する関数によって自動的に行われます。
.Type Conversion between BLisp and Rust
|===
|BLisp | Rust
|_Int_ | _BigInt_
|_Bool_ | _bool_
|_Char_ | _char_
|_String_ | _String_
|_'(T)_ | _Vec<T>_
|_[T0, T1]_ | _(T0, T1)_
|_(Option T)_ | _Option<T>_
|_(Result T E)_ | _Result<T, E>_
|===
== Coqへのトランスパイラ (実験的)
BLispは実験的にCoqへのトランスパイラを実装しています。
トランスパイラは、以下のように _blisp::transpile_ を呼び出すことで実行されます。
[source, coq]
----
let expr = "
(defun snoc (l y)
(Pure (-> (
'(t) t)
'(t)))
(match l
(nil (Cons y nil))
((Cons h b) (Cons h (snoc b y)))))
(defun rev (l)
(Pure (-> (
'(t))
'(t)))
(match l
(nil nil)
((Cons h t) (snoc (rev t) h))))
";
let exprs = blisp::init(expr, vec![]).unwrap();
let ctx = blisp::typing(exprs).unwrap();
println!("{}", blisp::transpile(&ctx));
----
これは以下のようなCoqのコードを出力します。
この出力には、BLispのプレリュードも含まれます。
[source, coq]
----
Require Import ZArith.
Require Import Coq.Lists.List.
Inductive Option (t: Type): Type :=
| Some (x0: t)
| None.
Arguments Some{t}.
Arguments None{t}.
Inductive Result (t e: Type): Type :=
| Ok (x0: t)
| Err (x0: e).
Arguments Ok{t e}.
Arguments Err{t e}.
Definition car {t: Type} (x: list t): Option t :=
match x with
| (cons n _) => (Some n)
| _ => (None)
end.
Definition cdr {t: Type} (x: list t): list t :=
match x with
| (cons _ l) => l
| _ => nil
end.
Definition filter {t: Type} (f: t -> bool) (x: list t): list t :=
(reverse (filter' f x nil ) ).
Fixpoint filter' {t: Type} (f: t -> bool) (x l: list t): list t :=
match x with
| (cons h a) => match (f h ) with
| true => (filter' f a (cons h l) )
| false => (filter' f a l )
end
| _ => l
end.
Fixpoint fold {a b: Type} (f: a -> b -> b) (init: b) (x: list a): b :=
match x with
| (cons h l) => (fold f (f h init ) l )
| _ => init
end.
Fixpoint map {a b: Type} (f: a -> b) (x: list a): list b :=
match x with
| (cons h l) => (cons (f h ) (map f l ))
| _ => nil
end.
Fixpoint rev {t: Type} (l: list t): list t :=
match l with
| nil => nil
| (cons h t) => (snoc (rev t ) h )
end.
Definition reverse {t: Type} (x: list t): list t :=
(reverse' x nil ).
Fixpoint reverse' {t: Type} (x l: list t): list t :=
match x with
| (cons h a) => (reverse' a (cons h l) )
| _ => l
end.
Fixpoint snoc {t: Type} (l: list t) (y: t): list t :=
match l with
| nil => (cons y nil)
| (cons h b) => (cons h (snoc b y ))
end.
----
このトランスパイラは実験的なものであることに注意してください。
よって、いくつかの出力はCoqが解釈できません。
その場合は、手動でソースコードを修正してください。
簡単にできるはずです。
== 例
=== リバース
_reverse_ は内部で定義されている関数です。この関数はリストを反転します。
[source, lisp]
----
(reverse '(1 2 3 4 5 6 7 8 9))
----
このコードの出力は以下の通りです。
'(9 8 7 6 5 4 3 2 1)
=== Filter
_filter_ は内部で定義されている関数です。この関数はリストの中身をフィルターします。
[source, lisp]
----
(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9))
----
このコードの出力は以下の通りです。
'(2 4 6 8)
_filter_' の型は以下の通りです。
[source, lisp]
----
(Pure (->
((Pure (-> (t) Bool)) ; 関数を引数にとる
'(t)) ; リストを引数にとる
'(t))) ; リストをリターン
----
=== 階乗
末尾呼び出し版の階乗関数は、以下のように実装できます。
[source, lisp]
----
(export factorial (n) (Pure (-> (Int) Int))
(fact n 1))
(defun fact (n total) (Pure (-> (Int Int) Int))
(if (<= n 0)
total
(fact (- n 1) (* n total))))
----
この関数は以下のように呼び出すことができます。
>> (factorial 10)
3628800
>>
>> (factorial 1000)
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
>>
>> (factorial 100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
>>
>> (factorial 500)
1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
================================================
FILE: docs/index.ja.html
================================================
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.20">
<meta name="author" content="Yuuki Takano">
<title>BLisp: Lispっぽい静的型付け言語</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.square{list-style-type:square}
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|
gitextract_wiwtvaga/
├── .gitignore
├── Cargo.toml
├── LICENSE
├── README.md
├── docs/
│ ├── Makefile
│ ├── index.adoc
│ ├── index.html
│ ├── index.ja.adoc
│ └── index.ja.html
├── embed_macro/
│ ├── Cargo.toml
│ ├── LICENSE
│ ├── README.md
│ └── src/
│ └── lib.rs
├── history.md
├── specification/
│ ├── Makefile
│ ├── language.md
│ └── typing.tex
├── src/
│ ├── coq.rs
│ ├── lib.rs
│ ├── macro.rs
│ ├── parser.rs
│ ├── prelude.lisp
│ ├── runtime.rs
│ └── semantics.rs
└── tests/
├── embedded.rs
└── transpile.rs
SYMBOL INDEX (396 symbols across 9 files)
FILE: embed_macro/src/lib.rs
function embedded (line 9) | pub fn embedded(
function generate_ffi_body (line 70) | fn generate_ffi_body(data: &Signature, fn_name: &Ident, fn_name_ffi: &Id...
function call_ffi (line 106) | fn call_ffi(len: usize, fn_name: &Ident) -> TokenStream {
function typecast (line 142) | fn typecast(ty: &Type, arg_dst: Ident, arg_src: TokenStream) -> TokenStr...
function inputs_type (line 172) | fn inputs_type(data: &Signature) -> String {
function output_type (line 189) | fn output_type(data: &Signature) -> String {
function parse_type (line 198) | fn parse_type(ty: &Type) -> String {
function ex_type_check (line 250) | fn ex_type_check(id: &Ident) -> String {
FILE: src/coq.rs
function to_coq_type (line 9) | pub(crate) fn to_coq_type(
function import (line 105) | pub(crate) fn import() -> &'static str {
function to_coq_data (line 123) | pub(crate) fn to_coq_data(expr: &S::DataType) -> String {
function to_coq_data_def (line 148) | fn to_coq_data_def(expr: &S::DataTypeName) -> String {
function to_coq_data_mem (line 167) | fn to_coq_data_mem(expr: &S::DataTypeMem) -> String {
function to_args_type (line 185) | fn to_args_type(args: &LinkedList<String>, ty: &str) -> String {
function inductive_arguments (line 200) | fn inductive_arguments(expr: &S::DataType) -> String {
function to_coq_func (line 215) | pub(crate) fn to_coq_func(expr: &S::Defun) -> String {
function func_analyze (line 283) | fn func_analyze(expr: &S::LangExpr, count: &mut i32) -> String {
function pattern_analyze (line 426) | fn pattern_analyze(pattern: &S::Pattern) -> String {
function apply_arith (line 462) | fn apply_arith(expr: String) -> Option<String> {
function tabb (line 474) | fn tabb(count: i32) -> String {
function is_recursive (line 482) | fn is_recursive(expr: &S::Defun) -> bool {
function is_recursive_expr (line 486) | fn is_recursive_expr(expr: &S::LangExpr, id: &str) -> bool {
function is_recursive_exprs (line 520) | fn is_recursive_exprs(exprs: &[S::LangExpr], id: &str) -> bool {
FILE: src/lib.rs
type FileType (line 114) | pub enum FileType {
type Pos (line 123) | pub struct Pos {
method fmt (line 130) | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
type LispErr (line 137) | pub struct LispErr {
method new (line 143) | fn new(msg: String, pos: Pos) -> LispErr {
type TypingContext (line 148) | pub struct TypingContext {
function init (line 166) | pub fn init(code: &str, ext_funs: Vec<Box<dyn FFI + Send>>) -> Result<Ty...
function typing (line 230) | pub fn typing(exprs: TypingContext) -> Result<semantics::Context, LispEr...
function eval (line 257) | pub fn eval(
function transpile (line 264) | pub fn transpile(ctx: &semantics::Context) -> String {
function eval_first (line 281) | fn eval_first(code: &str, ctx: &semantics::Context) -> String {
function test_macro (line 292) | fn test_macro() {
function test_macro_hygiene_lambda (line 329) | fn test_macro_hygiene_lambda() {
function test_macro_hygiene_let (line 343) | fn test_macro_hygiene_let() {
function test_macro_hygiene_match (line 357) | fn test_macro_hygiene_match() {
function eval_result (line 373) | fn eval_result(code: &str, ctx: &semantics::Context) {
function ops (line 380) | fn ops() {
function lambda (line 415) | fn lambda() {
function list (line 430) | fn list() {
function tuple (line 454) | fn tuple() {
function prelude (line 466) | fn prelude() {
function callback (line 504) | fn callback() {
function do_transpile (line 525) | fn do_transpile() {
function test_multibyte (line 550) | fn test_multibyte() {
FILE: src/macro.rs
type MacroErr (line 9) | pub struct MacroErr {
function match_pattern (line 15) | pub fn match_pattern(e1: &Expr, e2: &Expr, ctx: &mut BTreeMap<String, Li...
function match_list (line 55) | pub fn match_list(
function eq_expr (line 106) | fn eq_expr(e1: &Expr, e2: &Expr) -> bool {
function eq_exprs (line 120) | fn eq_exprs(es1: &LinkedList<Expr>, es2: &LinkedList<Expr>) -> bool {
function process_macros (line 128) | pub(crate) fn process_macros(exprs: &mut LinkedList<Expr>) -> Result<Mac...
function apply (line 139) | pub(crate) fn apply(expr: &mut Expr, macros: &Macros) -> Result<(), Macr...
type MacroExpander (line 143) | struct MacroExpander<'a> {
function new (line 149) | fn new(macros: &'a Macros) -> MacroExpander<'a> {
function apply_macros (line 156) | fn apply_macros(&mut self, expr: &mut Expr) -> Result<(), MacroErr> {
function apply_macros_expr (line 168) | fn apply_macros_expr(
function apply_macros_recursively (line 199) | fn apply_macros_recursively(&mut self, expr: &mut Expr, count: u8) -> Re...
function expand (line 220) | fn expand(
function freshen_template (line 230) | fn freshen_template(&mut self, template: &Expr) -> Expr {
function rename_expr (line 235) | fn rename_expr(&mut self, expr: &Expr, env: &mut BTreeMap<String, String...
function rename_exprs (line 262) | fn rename_exprs(
function rename_lambda (line 276) | fn rename_lambda(
function rename_lambda_args (line 299) | fn rename_lambda_args(
function rename_let (line 316) | fn rename_let(
function rename_let_bindings (line 339) | fn rename_let_bindings(
function rename_match (line 374) | fn rename_match(
function rename_match_case (line 396) | fn rename_match_case(&mut self, case: &Expr, env: &mut BTreeMap<String, ...
function rename_pattern (line 416) | fn rename_pattern(&mut self, pattern: &Expr, env: &mut BTreeMap<String, ...
function rename_binder (line 444) | fn rename_binder(&mut self, expr: &Expr, env: &mut BTreeMap<String, Stri...
function fresh_name (line 459) | fn fresh_name(&mut self, id: &str) -> String {
type Macros (line 466) | pub(crate) type Macros = BTreeMap<String, LinkedList<MacroRule>>;
type MacroRule (line 469) | pub(crate) struct MacroRule {
function parse_macros (line 474) | fn parse_macros(exprs: &LinkedList<Expr>) -> Result<Macros, MacroErr> {
function is_pattern_var (line 553) | fn is_pattern_var(id: &str) -> bool {
function expand_expr (line 557) | fn expand_expr(pos: Pos, template: &Expr, ctx: &BTreeMap<String, LinkedL...
function expand_list (line 598) | fn expand_list(
FILE: src/parser.rs
type SyntaxErr (line 28) | pub struct SyntaxErr {
type Parser (line 33) | pub struct Parser<'a> {
type Expr (line 39) | pub enum Expr {
method get_pos (line 103) | pub fn get_pos(&self) -> Pos {
method fmt (line 51) | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
function new (line 118) | pub fn new(code: &'a str, file_id: FileType) -> Parser<'a> {
function parse (line 129) | pub fn parse(&mut self) -> Result<LinkedList<Expr>, SyntaxErr> {
function parse_id_bool (line 142) | fn parse_id_bool(&mut self) -> Result<Expr, SyntaxErr> {
function parse_oct (line 173) | fn parse_oct(&mut self) -> Result<Expr, SyntaxErr> {
function parse_hex (line 203) | fn parse_hex(&mut self) -> Result<Expr, SyntaxErr> {
function check_eof (line 237) | fn check_eof(&self, expr: Expr) -> Result<Expr, SyntaxErr> {
function parse_binary (line 260) | fn parse_binary(&mut self) -> Result<Expr, SyntaxErr> {
function parse_num (line 292) | fn parse_num(&mut self) -> Result<Expr, SyntaxErr> {
function skip_spaces (line 351) | fn skip_spaces(&mut self) {
function parse_exprs (line 386) | fn parse_exprs(&mut self) -> Result<LinkedList<Expr>, SyntaxErr> {
function parse_expr (line 402) | fn parse_expr(&mut self) -> Result<Expr, SyntaxErr> {
function parse_char (line 440) | fn parse_char(&mut self) -> Result<Expr, SyntaxErr> {
function parse_string (line 512) | fn parse_string(&mut self) -> Result<Expr, SyntaxErr> {
function parse_apply (line 583) | fn parse_apply(&mut self) -> Result<Expr, SyntaxErr> {
function parse_list (line 601) | fn parse_list(&mut self) -> Result<Expr, SyntaxErr> {
function parse_tuple (line 628) | fn parse_tuple(&mut self) -> Result<Expr, SyntaxErr> {
function is_space (line 647) | fn is_space(c: char) -> bool {
function is_paren (line 651) | fn is_paren(c: char) -> bool {
FILE: src/runtime.rs
type Expr (line 21) | type Expr = semantics::LangExpr;
type Pattern (line 22) | type Pattern = semantics::Pattern;
type RuntimeErr (line 24) | struct RuntimeErr {
type Variables (line 30) | pub struct Variables {
method new (line 35) | fn new() -> Variables {
method push (line 41) | fn push(&mut self) {
method pop (line 45) | fn pop(&mut self) {
method insert (line 49) | fn insert(&mut self, id: String, data: RTData) {
method get (line 54) | fn get(&mut self, id: &str) -> Option<&RTData> {
type TCall (line 65) | pub enum TCall {
type IntType (line 71) | pub struct IntType(*mut (BigInt, bool));
method get_int (line 74) | fn get_int(&self) -> &BigInt {
method get_ref (line 78) | fn get_ref(&mut self) -> &mut bool {
method cmp (line 84) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 92) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method eq (line 100) | fn eq(&self, other: &Self) -> bool {
type StrType (line 108) | pub struct StrType(*mut (String, bool));
method get_string (line 111) | fn get_string(&self) -> &String {
method get_ref (line 115) | fn get_ref(&mut self) -> &mut bool {
method cmp (line 121) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 129) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method eq (line 137) | fn eq(&self, other: &Self) -> bool {
type ClojureType (line 145) | pub struct ClojureType(*mut (Clojure, bool));
method get_clojure (line 148) | fn get_clojure(&self) -> &Clojure {
method get_clojure_mut (line 152) | fn get_clojure_mut(&mut self) -> &mut Clojure {
method get_ref (line 156) | fn get_ref(&mut self) -> &mut bool {
method cmp (line 162) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 170) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method eq (line 178) | fn eq(&self, other: &Self) -> bool {
type LDataType (line 186) | pub struct LDataType(*mut (LabeledData, bool));
method get_ldata (line 189) | fn get_ldata(&self) -> &LabeledData {
method get_ldata_mut (line 193) | fn get_ldata_mut(&mut self) -> &mut LabeledData {
method get_ref (line 197) | fn get_ref(&mut self) -> &mut bool {
method cmp (line 203) | fn cmp(&self, other: &Self) -> Ordering {
method partial_cmp (line 211) | fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
method eq (line 219) | fn eq(&self, other: &Self) -> bool {
type RTData (line 227) | pub enum RTData {
method get_in_lisp (line 249) | fn get_in_lisp(&self, list_head: bool) -> String {
method into (line 1239) | fn into(&self) -> BigInt {
method into (line 1250) | fn into(&self) -> char {
method into (line 1261) | fn into(&self) -> String {
method into (line 1272) | fn into(&self) -> bool {
method into (line 1286) | fn into(&self) -> Vec<T> {
method into (line 1304) | fn into(&self) -> Option<T> {
method into (line 1357) | fn into(&self) -> Result<T, E> {
method from (line 1541) | fn from(env: &mut Environment<'_>, value: BigInt) -> Self {
method from (line 1547) | fn from(_env: &mut Environment<'_>, value: char) -> Self {
method from (line 1553) | fn from(_env: &mut Environment<'_>, value: bool) -> Self {
method from (line 1559) | fn from(env: &mut Environment<'_>, value: String) -> Self {
method from (line 1568) | fn from(env: &mut Environment<'_>, value: Option<T>) -> Self {
method from (line 1582) | fn from(env: &mut Environment<'_>, value: Result<T, E>) -> Self {
method from (line 1597) | fn from(env: &mut Environment<'_>, _: ()) -> Self {
method from (line 1694) | fn from(env: &mut Environment<'_>, vec: Vec<T>) -> Self {
method from (line 1702) | fn from(env: &mut Environment<'_>, slice: [T; N]) -> Self {
function escape_char (line 238) | fn escape_char(c: char) -> String {
type LabeledData (line 344) | struct LabeledData {
type Clojure (line 350) | struct Clojure {
constant MIN_GC_NUM (line 355) | const MIN_GC_NUM: usize = 1024;
type RootObject (line 358) | pub(crate) struct RootObject {
method new (line 367) | fn new() -> RootObject {
method len (line 377) | fn len(&self) -> usize {
method make_int (line 381) | fn make_int(&mut self, n: BigInt) -> IntType {
method make_str (line 387) | fn make_str(&mut self, str: String) -> StrType {
method make_obj (line 393) | fn make_obj(&mut self, label: String, data: Option<Vec<RTData>>) -> LD...
method make_clojure (line 400) | fn make_clojure(&mut self, ident: u64, data: Option<BTreeMap<String, R...
type Environment (line 408) | pub struct Environment<'a> {
function eval (line 415) | pub(crate) fn eval(
function get_data_of_id (line 484) | fn get_data_of_id(id: &str, vars: &mut VecDeque<Variables>) -> RTData {
function eval_expr (line 491) | fn eval_expr(expr: &Expr, env: &mut Environment<'_>) -> Result<RTData, R...
function eval_lambda (line 509) | fn eval_lambda(expr: &semantics::Lambda, env: &mut Environment<'_>) -> R...
function eval_tuple (line 524) | fn eval_tuple(expr: &semantics::Exprs, env: &mut Environment<'_>) -> Res...
function get_fun (line 535) | fn get_fun<'a>(
function get_lambda (line 552) | fn get_lambda<'a>(
function call_lambda (line 578) | fn call_lambda(
function eval_apply (line 617) | fn eval_apply(expr: &semantics::Apply, env: &mut Environment<'_>) -> Res...
function eval_tail_call (line 696) | fn eval_tail_call<'a>(
function get_int (line 723) | fn get_int(args: &[RTData], pos: Pos) -> Result<*const BigInt, RuntimeEr...
function get_int_int (line 733) | fn get_int_int(args: &[RTData], pos: Pos) -> Result<(*const BigInt, *con...
function get_int_int_int (line 743) | fn get_int_int_int(
function get_bool_bool (line 758) | fn get_bool_bool(args: &[RTData], pos: Pos) -> Result<(bool, bool), Runt...
function get_bool (line 768) | fn get_bool(args: &[RTData], pos: Pos) -> Result<bool, RuntimeErr> {
function eval_built_in (line 778) | fn eval_built_in(
function eval_match (line 964) | fn eval_match(
function eval_id (line 987) | fn eval_id(expr: &semantics::IDNode, vars: &mut VecDeque<Variables>) -> ...
function eval_list (line 992) | fn eval_list(expr: &semantics::Exprs, env: &mut Environment<'_>) -> Resu...
function eval_if (line 1004) | fn eval_if(expr: &semantics::IfNode, env: &mut Environment<'_>) -> Resul...
function eval_data (line 1024) | fn eval_data(expr: &semantics::DataNode, env: &mut Environment<'_>) -> R...
function eval_let (line 1040) | fn eval_let(expr: &semantics::LetNode, env: &mut Environment<'_>) -> Res...
function eval_pat (line 1060) | fn eval_pat(pat: &Pattern, data: RTData, vars: &mut VecDeque<Variables>)...
function collect_garbage (line 1130) | fn collect_garbage(vars: &mut VecDeque<Variables>, root: &mut RootObject) {
function mark (line 1150) | fn mark(vars: &mut VecDeque<Variables>) {
function mark_obj (line 1161) | fn mark_obj(data: &mut RTData) {
function sweep (line 1194) | fn sweep<T>(root: &mut LinkedList<Pin<Box<(T, bool)>>>) {
type RTDataToRust (line 1233) | pub trait RTDataToRust<T> {
method into (line 1234) | fn into(&self) -> T;
function list_to_vec (line 1326) | fn list_to_vec<T>(mut ldata: &LabeledData, result: &mut Vec<T>)
type RustToRTData (line 1536) | pub trait RustToRTData<T> {
method from (line 1537) | fn from(env: &mut Environment<'_>, value: T) -> Self;
function collection_to_list (line 1708) | fn collection_to_list<I, T>(env: &mut Environment<'_>, iter: I) -> LData...
type FFI (line 1746) | pub trait FFI {
method blisp_extern (line 1748) | fn blisp_extern(&self) -> &'static str;
method ffi (line 1751) | fn ffi(&self) -> fn(env: &mut Environment<'_>, args: &[RTData]) -> RTD...
method name (line 1754) | fn name(&self) -> &'static str;
FILE: src/semantics.rs
type ID (line 21) | type ID = u64;
type Sbst (line 22) | type Sbst = BTreeMap<ID, Type>;
type Type (line 25) | enum Type {
method fmt (line 37) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method has_tvar (line 3925) | fn has_tvar(&self, id: ID) -> bool {
method apply_sbst (line 3932) | fn apply_sbst(&self, sbst: &Sbst) -> Type {
type Tycon (line 31) | struct Tycon {
method fmt (line 46) | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
method has_tvar (line 3944) | fn has_tvar(&self, id: ID) -> bool {
method apply_sbst (line 3956) | fn apply_sbst(&self, sbst: &Sbst) -> Type {
function ty_bool (line 74) | fn ty_bool() -> Type {
function ty_int (line 81) | fn ty_int() -> Type {
function ty_string (line 88) | fn ty_string() -> Type {
function ty_char (line 95) | fn ty_char() -> Type {
function ty_var (line 102) | fn ty_var(n: ID) -> Type {
function ty_tuple (line 106) | fn ty_tuple(types: Vec<Type>) -> Type {
function ty_list (line 113) | fn ty_list(ty: Type) -> Type {
function ty_args (line 120) | fn ty_args(types: Vec<Type>) -> Type {
function ty_fun (line 134) | fn ty_fun(effect: &Effect, args: Vec<Type>, ret: Type) -> Type {
function ty_fun_gen_effect (line 152) | fn ty_fun_gen_effect(n: ID, args: Vec<Type>, ret: Type) -> Type {
type FunTypes (line 161) | pub struct FunTypes {
method new (line 166) | fn new() -> FunTypes {
method insert (line 172) | fn insert(&mut self, key: &str, val: Type) {
method contains (line 185) | fn contains(&self, key: &str, val: &Type) -> bool {
type VarType (line 200) | struct VarType {
method new (line 205) | fn new() -> VarType {
method push (line 213) | fn push(&mut self) {
method pop (line 217) | fn pop(&mut self) {
method insert (line 221) | fn insert(&mut self, key: String, val: Type) {
method get (line 239) | fn get(&self, key: &str) -> Option<&Type> {
type TypingErr (line 251) | pub struct TypingErr {
method new (line 257) | fn new(msg: &str, ast: &parser::Expr) -> TypingErr {
type LangExpr (line 266) | pub(crate) enum LangExpr {
method get_pos (line 283) | pub(crate) fn get_pos(&self) -> Pos {
method apply_sbst (line 301) | fn apply_sbst(&mut self, sbst: &Sbst) {
type Lambda (line 372) | pub(crate) struct Lambda {
type StrNode (line 382) | pub(crate) struct StrNode {
type CharNode (line 389) | pub(crate) struct CharNode {
type NumNode (line 396) | pub(crate) struct NumNode {
type BoolNode (line 403) | pub(crate) struct BoolNode {
type IDNode (line 410) | pub(crate) struct IDNode {
type Extern (line 417) | pub(crate) struct Extern {
type IfNode (line 424) | pub(crate) struct IfNode {
type LetNode (line 433) | pub(crate) struct LetNode {
type DefVar (line 441) | pub(crate) struct DefVar {
type MatchNode (line 449) | pub(crate) struct MatchNode {
type DataNode (line 457) | pub(crate) struct DataNode {
type Pattern (line 465) | pub(crate) enum Pattern {
method get_pos (line 477) | pub(crate) fn get_pos(&self) -> Pos {
method get_type (line 490) | fn get_type(&self) -> &Option<Type> {
method apply_sbst (line 503) | fn apply_sbst(&mut self, sbst: &Sbst) {
type PatTupleNode (line 531) | pub(crate) struct PatTupleNode {
type PatDataNode (line 538) | pub(crate) struct PatDataNode {
type PatNilNode (line 546) | pub(crate) struct PatNilNode {
type MatchCase (line 552) | pub(crate) struct MatchCase {
type Apply (line 560) | pub(crate) struct Apply {
type Exprs (line 568) | pub(crate) struct Exprs {
type TIDNode (line 575) | pub(crate) struct TIDNode {
type TEBoolNode (line 581) | pub(crate) struct TEBoolNode;
type TEIntNode (line 584) | pub(crate) struct TEIntNode;
type TEStringNode (line 587) | pub(crate) struct TEStringNode;
type TECharNode (line 590) | pub(crate) struct TECharNode;
type DataType (line 593) | pub(crate) struct DataType {
type DataTypeName (line 600) | pub(crate) struct DataTypeName {
type DataTypeMem (line 607) | pub(crate) struct DataTypeMem {
type TypeExpr (line 614) | pub(crate) enum TypeExpr {
type TEListNode (line 627) | pub(crate) struct TEListNode {
type TETupleNode (line 633) | pub(crate) struct TETupleNode {
type Effect (line 639) | enum Effect {
type TEFunNode (line 645) | pub(crate) struct TEFunNode {
type TEDataNode (line 653) | pub(crate) struct TEDataNode {
type Defun (line 660) | pub(crate) struct Defun {
type TApp (line 671) | trait TApp: Sized {
method apply (line 672) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<Self, Typin...
method apply (line 676) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<DataType, T...
method apply (line 691) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<DataTypeMem...
method apply (line 706) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TypeExpr, T...
method apply (line 722) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TEListNode,...
method apply (line 731) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TETupleNode...
method apply (line 745) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TEFunNode, ...
method apply (line 761) | fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TEDataNode,...
type CallbackFn (line 775) | pub type CallbackFn = Box<dyn Fn(&BigInt, &BigInt, &BigInt) -> Option<Bi...
type FFIFn (line 776) | pub type FFIFn = BTreeMap<&'static str, fn(env: &mut Environment<'_>, ar...
type Context (line 778) | pub struct Context {
method new (line 792) | fn new(
method set_callback (line 847) | pub fn set_callback(&mut self, func: CallbackFn) {
method typing (line 851) | fn typing(&mut self) -> Result<(), TypingErr> {
method check_match_exhaustive (line 865) | fn check_match_exhaustive(&self) -> Result<(), TypingErr> {
method find_tail_call (line 872) | fn find_tail_call(&mut self) {
method check_label (line 881) | fn check_label(&mut self) -> Result<(), TypingErr> {
method typing_functions (line 900) | fn typing_functions(&mut self) -> Result<(), TypingErr> {
method typing_extern (line 922) | fn typing_extern(&self, fun: &mut Extern) -> Result<(), TypingErr> {
method typing_defun (line 929) | fn typing_defun(&self, defun: &mut Defun) -> Result<(), TypingErr> {
method typing_expr (line 983) | fn typing_expr(
method typing_lambda (line 1007) | fn typing_lambda(
method typing_data (line 1052) | fn typing_data(
method typing_app (line 1108) | fn typing_app(
method typing_tuple (line 1168) | fn typing_tuple(
method typing_list (line 1188) | fn typing_list(
method typing_match (line 1241) | fn typing_match(
method typing_var (line 1313) | fn typing_var(
method typing_if (line 1420) | fn typing_if(
method typing_let (line 1474) | fn typing_let(
method typing_pat (line 1507) | fn typing_pat(
method typing_pat_tuple (line 1526) | fn typing_pat_tuple(
method typing_pat_id (line 1546) | fn typing_pat_id(
method typing_pat_data (line 1565) | fn typing_pat_data(
method typing_pat_nil (line 1626) | fn typing_pat_nil(&self, expr: &mut PatNilNode, sbst: Sbst, num_tv: &m...
method to_type (line 1634) | fn to_type(&self, expr: &TypeExpr, num_tv: &mut ID) -> Result<Type, St...
method get_type_of_label (line 1648) | fn get_type_of_label(&self, label: &str, num_tv: &mut ID) -> Result<(T...
method check_data_def (line 1735) | fn check_data_def(&self) -> Result<(), TypingErr> {
method check_data_def_data (line 1743) | fn check_data_def_data(&self, data: &DataType) -> Result<(), TypingErr> {
method check_data_def_mem (line 1761) | fn check_data_def_mem(
method check_def_type (line 1773) | fn check_def_type(
method check_data_rec (line 1838) | fn check_data_rec(&self) -> Result<(), TypingErr> {
method check_data_rec_data (line 1875) | fn check_data_rec_data(
method check_data_rec_mem (line 1899) | fn check_data_rec_mem(
method check_data_rec_ty (line 1917) | fn check_data_rec_ty(
method type_data_node2data_type (line 1951) | fn type_data_node2data_type(&self, data: &TEDataNode) -> Result<DataTy...
method check_defun_type (line 1980) | fn check_defun_type(&self) -> Result<(), TypingErr> {
method check_defun_type_after_infer (line 1988) | fn check_defun_type_after_infer(&mut self) -> Result<(), TypingErr> {
method check_type_infer (line 2004) | fn check_type_infer(&self, defun: &Defun, fun_types: &mut FunTypes) ->...
method check_expr_type (line 2050) | fn check_expr_type(
method check_lambda_type (line 2083) | fn check_lambda_type(
method check_data_type (line 2104) | fn check_data_type(
method check_apply_type (line 2122) | fn check_apply_type(
method check_exprs_type (line 2140) | fn check_exprs_type(
method check_match_type (line 2158) | fn check_match_type(
method check_id_type (line 2182) | fn check_id_type(
method check_defun_type_recur (line 2230) | fn check_defun_type_recur(
method check_if_type (line 2307) | fn check_if_type(
method check_let_type (line 2324) | fn check_let_type(
method get_free_var_in_lambda (line 2351) | fn get_free_var_in_lambda(&mut self) {
function get_tv2type_from_type_expr (line 2374) | fn get_tv2type_from_type_expr(
function apply_tv2type_to_type_expr (line 2415) | fn apply_tv2type_to_type_expr(
function check_pat_type (line 2464) | fn check_pat_type(
function get_free_var_expr (line 2497) | fn get_free_var_expr(
function get_free_var_apply (line 2521) | fn get_free_var_apply(
function get_free_var_exprs (line 2534) | fn get_free_var_exprs(
function get_free_var_match (line 2547) | fn get_free_var_match(
function get_free_var_data (line 2565) | fn get_free_var_data(
function get_free_var_id (line 2578) | fn get_free_var_id(
function get_free_var_let (line 2595) | fn get_free_var_let(
function get_free_var_if (line 2613) | fn get_free_var_if(
function get_free_var_lambda (line 2647) | fn get_free_var_lambda(
function get_free_var_pattern (line 2693) | fn get_free_var_pattern(pat: &Pattern, local_vars: &mut VarType) {
function check_type_has_no_tvars (line 2718) | fn check_type_has_no_tvars(ty: &Option<Type>, pos: &Pos, sbst: &Sbst) ->...
function check_type_has_io (line 2736) | fn check_type_has_io(
function has_io (line 2763) | fn has_io(ty: &Type) -> bool {
function has_tvar (line 2785) | fn has_tvar(ty: &Type) -> bool {
function typing_expr (line 2801) | pub(crate) fn typing_expr(
function exprs2context (line 2848) | pub fn exprs2context(typing_context: TypingContext) -> Result<Context, T...
function expr2data (line 2932) | fn expr2data(expr: &parser::Expr) -> Result<DataType, TypingErr> {
function expr2data_name (line 2962) | fn expr2data_name(expr: &parser::Expr) -> Result<DataTypeName, TypingErr> {
function expr2type_id (line 3007) | fn expr2type_id(expr: &parser::Expr) -> Result<TIDNode, TypingErr> {
function expr2id (line 3026) | fn expr2id(expr: &parser::Expr) -> Result<IDNode, TypingErr> {
function expr2data_mem (line 3050) | fn expr2data_mem(expr: &parser::Expr) -> Result<DataTypeMem, TypingErr> {
function expr2extern (line 3088) | fn expr2extern(expr: &parser::Expr) -> Result<Extern, TypingErr> {
function expr2defun (line 3143) | fn expr2defun(expr: &parser::Expr) -> Result<Defun, TypingErr> {
function expr2type_arrow (line 3217) | fn expr2type_arrow(expr: &parser::Expr) -> Result<(Vec<TypeExpr>, TypeEx...
function expr2type_fun (line 3264) | fn expr2type_fun(expr: &parser::Expr) -> Result<TypeExpr, TypingErr> {
function expr2types (line 3308) | fn expr2types(expr: &parser::Expr) -> Result<Vec<TypeExpr>, TypingErr> {
function expr2type (line 3319) | fn expr2type(expr: &parser::Expr) -> Result<TypeExpr, TypingErr> {
function list_types2vec_types (line 3411) | fn list_types2vec_types(exprs: &LinkedList<parser::Expr>) -> Result<Vec<...
function expr2typed_expr (line 3423) | fn expr2typed_expr(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {
function expr2data_expr (line 3530) | fn expr2data_expr(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {
function expr2if (line 3555) | fn expr2if(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {
function expr2let (line 3585) | fn expr2let(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {
function expr2letpat (line 3632) | fn expr2letpat(expr: &parser::Expr) -> Result<Pattern, TypingErr> {
function expr2def_vars (line 3693) | fn expr2def_vars(expr: &parser::Expr) -> Result<DefVar, TypingErr> {
function expr2mpat (line 3717) | fn expr2mpat(expr: &parser::Expr) -> Result<Pattern, TypingErr> {
function expr2case (line 3819) | fn expr2case(expr: &parser::Expr) -> Result<MatchCase, TypingErr> {
function expr2match (line 3842) | fn expr2match(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {
function expr2lambda (line 3877) | fn expr2lambda(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {
function unify (line 3971) | fn unify(lhs: &Type, rhs: &Type) -> Option<Sbst> {
function compose (line 4030) | fn compose(s1: &Sbst, s2: &Sbst) -> Sbst {
function tail_call (line 4045) | fn tail_call(expr: &mut LangExpr) {
function tail_call_expr (line 4055) | fn tail_call_expr(expr: &mut LangExpr) -> LinkedList<&mut LangExpr> {
function exhaustive_expr (line 4083) | fn exhaustive_expr(expr: &LangExpr, ctx: &Context) -> Result<(), TypingE...
function exhaustive_exprs (line 4097) | fn exhaustive_exprs(exprs: &[LangExpr], ctx: &Context) -> Result<(), Typ...
function exhaustive_let (line 4104) | fn exhaustive_let(expr: &LetNode, ctx: &Context) -> Result<(), TypingErr> {
function exhaustive_if (line 4114) | fn exhaustive_if(expr: &IfNode, ctx: &Context) -> Result<(), TypingErr> {
function exhaustive_match (line 4121) | fn exhaustive_match(expr: &MatchNode, ctx: &Context) -> Result<(), Typin...
type Patterns (line 4138) | struct Patterns<'a> {
function new (line 4143) | fn new() -> Patterns<'a> {
function insert (line 4149) | fn insert(&mut self, label: &str, idx: usize, p: &'a Pattern) {
function check_pattern_exhaustive (line 4163) | fn check_pattern_exhaustive(
FILE: tests/embedded.rs
function test_fun (line 5) | fn test_fun(
function add_four_ints (line 17) | fn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> R...
function no_return (line 27) | fn no_return() {}
function test_embedded (line 30) | fn test_embedded() {
FILE: tests/transpile.rs
function test_transpile (line 4) | fn test_transpile() {
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (662K chars).
[
{
"path": ".gitignore",
"chars": 29,
"preview": "target/\nCargo.lock\n.DS_Store\n"
},
{
"path": "Cargo.toml",
"chars": 814,
"preview": "[package]\nname = \"blisp\"\nversion = \"0.4.7\"\nauthors = [\"Yuuki Takano <ytakanoster@gmail.com>\", \"Fumiya Saito\"]\nedition = "
},
{
"path": "LICENSE",
"chars": 1104,
"preview": "MIT License\n\nCopyright (c) 2020 Yuuki Takano <ytakano@wide.ad.jp>, Fumiya Saito\n\nPermission is hereby granted, free of c"
},
{
"path": "README.md",
"chars": 1731,
"preview": "# BLisp\n\nBLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.\n"
},
{
"path": "docs/Makefile",
"chars": 135,
"preview": "all: index.html index.ja.html\n\nindex.html: index.adoc\n\tasciidoctor index.adoc\n\nindex.ja.html: index.ja.adoc\n\tasciidoctor"
},
{
"path": "docs/index.adoc",
"chars": 21187,
"preview": "= BLisp: A Statically Typed Lisp Like Language\nYuuki Takano <ytakano@wide.ad.jp>\nv0.4.0, 2023-02\n:doctype: article\n:toc:"
},
{
"path": "docs/index.html",
"chars": 146609,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<me"
},
{
"path": "docs/index.ja.adoc",
"chars": 17916,
"preview": "= BLisp: Lispっぽい静的型付け言語\nYuuki Takano <ytakano@wide.ad.jp>\nv0.4.0, 2023-02\n:doctype: article\n:toc:\n:sectnums:\n:lang: ja\n:"
},
{
"path": "docs/index.ja.html",
"chars": 142393,
"preview": "<!DOCTYPE html>\n<html lang=\"ja\">\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<me"
},
{
"path": "embed_macro/Cargo.toml",
"chars": 706,
"preview": "[package]\nname = \"blisp_embedded\"\nversion = \"0.1.1\"\nauthors = [\"Yuuki Takano <ytakanoster@gmail.com>\", \"Fumiya Saito\"]\ne"
},
{
"path": "embed_macro/LICENSE",
"chars": 1104,
"preview": "MIT License\n\nCopyright (c) 2020 Yuuki Takano <ytakano@wide.ad.jp>, Fumiya Saito\n\nPermission is hereby granted, free of c"
},
{
"path": "embed_macro/README.md",
"chars": 245,
"preview": "# `embedded` macro for BLisp\n\nPlease see [blisp-repl](https://github.com/ytakano/blisp-repl) to use BLisp,\nand [baremeta"
},
{
"path": "embed_macro/src/lib.rs",
"chars": 8119,
"preview": "extern crate proc_macro;\n\nuse convert_case::{Case, Casing};\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\nuse"
},
{
"path": "history.md",
"chars": 1984,
"preview": "# Version History\n\n## 0.4.7\n\n- add `macro` to define macros\n\n## 0.4.0\n\n- add `embedded` macro for FFIs\n- add transpiler "
},
{
"path": "specification/Makefile",
"chars": 171,
"preview": "all: typing.pdf\n\ntyping.dvi: typing.tex\n\tplatex typing.tex\n\tplatex typing.tex\n\ntyping.pdf: typing.dvi\n\tdvipdfmx -p lette"
},
{
"path": "specification/language.md",
"chars": 3156,
"preview": "# Syntax and Semantics of BLisp\n\n## Literal\n\n- $LITERAL := $HEX | $OCT | $BIN | $DECIMAL | $BOOL | $STRING | $CHAR\n- $DE"
},
{
"path": "specification/typing.tex",
"chars": 20142,
"preview": "\\documentclass{article}\n\n\\usepackage{amsmath,amssymb}\n\\usepackage[dvipdfmx]{hyperref,graphicx}\n\\usepackage{listings}\n\n\\l"
},
{
"path": "src/coq.rs",
"chars": 16707,
"preview": "use super::semantics as S;\nuse alloc::{\n collections::LinkedList,\n format,\n string::{String, ToString},\n vec"
},
{
"path": "src/lib.rs",
"chars": 14480,
"preview": "//! # BLisp\n//!\n//! BLisp is a well typed Lisp like programming language which adopts effect\n//! system for no_std envir"
},
{
"path": "src/macro.rs",
"chars": 20489,
"preview": "use crate::{parser::Expr, Pos};\nuse alloc::{\n collections::{btree_map::Entry, BTreeMap, LinkedList},\n format,\n "
},
{
"path": "src/parser.rs",
"chars": 18936,
"preview": "/*\n * $NUM := [0-9]*\n * $HEX := 0x[0-9a-fA-F]*\n * $OCT := 0o[0-9a-fA-F]*\n * $BIN := 0b[01]*\n * $BOOL := true | "
},
{
"path": "src/prelude.lisp",
"chars": 1078,
"preview": "(data (Option t)\n (Some t)\n None)\n\n(data (Result t e)\n (Ok t)\n (Err e))\n\n(export car (x) (Pure (-> ('(t)) (O"
},
{
"path": "src/runtime.rs",
"chars": 50505,
"preview": "use crate::r#macro;\n\nuse super::{parser, semantics, LispErr, Pos};\nuse alloc::{\n boxed::Box,\n collections::{btree_"
},
{
"path": "src/semantics.rs",
"chars": 126296,
"preview": "use super::{parser, Pos};\nuse crate::{\n r#macro::Macros,\n runtime::{Environment, RTData},\n TypingContext,\n};\nus"
},
{
"path": "tests/embedded.rs",
"chars": 1757,
"preview": "use blisp::embedded;\nuse num_bigint::{BigInt, ToBigInt};\n\n#[embedded]\nfn test_fun(\n _z: BigInt,\n _a: Vec<BigInt>,\n"
},
{
"path": "tests/transpile.rs",
"chars": 494,
"preview": "use blisp;\n\n#[test]\nfn test_transpile() {\n let expr = \"\n (defun snoc (l y)\n (Pure (-> (\n '(t) t)\n '(t"
}
]
About this extraction
This page contains the full source code of the ytakano/blisp GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (603.8 KB), approximately 184.9k tokens, and a symbol index with 396 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.