[
  {
    "path": ".gitignore",
    "content": "target/\nCargo.lock\n.DS_Store\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"blisp\"\nversion = \"0.4.7\"\nauthors = [\"Yuuki Takano <ytakanoster@gmail.com>\", \"Fumiya Saito\"]\nedition = \"2021\"\ndescription = \"A lisp like statically typed programing language for no_std.\"\nrepository = \"https://github.com/ytakano/blisp\"\nkeywords = [\n    \"no_std\",\n    \"scripting\",\n    \"scripting-engine\",\n    \"scripting-language\",\n    \"embedded\",\n]\ncategories = [\"no-std\", \"embedded\"]\nlicense-file = \"LICENSE\"\nreadme = \"README.md\"\nhomepage = \"https://ytakano.github.io/blisp/\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\nblisp_embedded = \"0.1\"\n\n[dependencies.num-bigint]\nversion = \"0.4\"\ndefault-features = false\n\n[dependencies.num-traits]\nversion = \"0.2\"\ndefault-features = false\nfeatures = [\"libm\"]\n\n[lib]\ncrate-type = [\"rlib\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Yuuki Takano <ytakano@wide.ad.jp>, Fumiya Saito\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# BLisp\n\nBLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.\nBLisp supports higher order RPC like higher order functions of functional programming languages.\n\nThis repository provides only a library crate.\nPlease see [blisp-repl](https://github.com/ytakano/blisp-repl) to use BLisp,\nand [baremetalisp](https://github.com/ytakano/baremetalisp) which is a toy OS.\n\n**[Homepage](https://ytakano.github.io/blisp/) is here.**\n\n## Features\n\n- Algebraic data type\n- Generics\n- Hindley–Milner based type inference\n- Effect system to separate side effects from pure functions\n- Hygienic macro expansion for local binders introduced by macro templates\n- Big integer\n- Supporting no_std environments\n\n## How to Use\n\n```rust\nuse blisp;\n\nfn main() {\n    let code = \"(export factorial (n) (Pure (-> (Int) Int))\n    (if (<= n 0)\n        1\n        (* n (factorial (- n 1)))))\";\n    let exprs = blisp::init(code, vec![]).unwrap();\n    let ctx = blisp::typing(exprs).unwrap();\n\n    let e = \"(factorial 10)\";\n    blisp::eval(e, &ctx).unwrap();\n}\n```\n\nIf Rust compiler or linker says warning of fmod,\nplease add fmod manually as follows.\n\n```rust\n#[no_mangle]\nextern \"C\" fn fmod(x: f64, y: f64) -> f64 {\n    libm::fmod(x, y)\n}\n```\n\nCargo.toml\n\n```toml\n[dependencies.blisp]\nversion = \"0.4\"\n```\n\n## Examples\n\n```lisp\n\"Hello, World!\" ; \"Hello, World!\"\n(+ 0x10 0x20)   ; 48\n(+ 0b111 0b101) ; 12\n(+ 0o777 0o444) ; 803\n(car '(1 2 3))  ; (Some 1)\n(cdr '(1 2 3))  ; '(2 3)\n(map (lambda (x) (* x 2)) '(8 9 10)) ; '(16 18 20)\n(fold + 0 '(1 2 3 4 5 6 7 8 9))      ; 45\n(reverse '(1 2 3 4 5 6 7 8 9))       ; '(9 8 7 6 5 4 3 2 1)\n(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9)) ; '(2 4 6 8)\n```\n"
  },
  {
    "path": "docs/Makefile",
    "content": "all: index.html index.ja.html\n\nindex.html: index.adoc\n\tasciidoctor index.adoc\n\nindex.ja.html: index.ja.adoc\n\tasciidoctor index.ja.adoc\n"
  },
  {
    "path": "docs/index.adoc",
    "content": "= BLisp: A Statically Typed Lisp Like Language\nYuuki Takano <ytakano@wide.ad.jp>\nv0.4.0, 2023-02\n:doctype: article\n:toc:\n:sectnums:\n:encoding: utf-8\n:stem: latexmath\n:source-highlighter: pygments\n\n\nBLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.\nBLisp supports higher order RPC like higher order functions of functional programming languages.\n\n* https://github.com/ytakano/blisp[GitHub's Repository]\n* https://crates.io/crates/blisp[BLisp's crates.io]\n\nThis repository provides only a library crate.\nPlease see https://github.com/ytakano/blisp-repl[blisp-repl] to use BLisp,\nand https://github.com/ytakano/baremetalisp[baremetalisp] which is a toy OS.\n\nhttps://ytakano.github.io/blisp/index.ja.html[日本語版はこちら]\n\n.BLisp on no_std Environment\nimage:https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytakano/20210221/20210221155657.gif[BLisp on no_std Environment]\n\n== Features\n\n* Algebraic data type\n* Generics\n* Hindley–Milner based type inference\n* Effect system to separate side effects from pure functions\n* Big integer\n* Supporting no_std environments\n\n== Values\n\n.values\n[source, lisp]\n----\n`A`       ; character literal\n\"Hello\"   ; string literal\n144       ; integer value\n0xabcDEF  ; hexadecimal\n0o777     ; octal\n0b1001    ; binary\ntrue      ; boolean value\nfalse     ; boolean value\n[true 10] ; tuple\n[]        ; empty tuple\n'(1 2 3)  ; list\n'()       ; empty list, Nil\n----\n\n== Basic Types\n\n.types\n[source, lisp]\n----\nChar       ; character\nString     ; string\nInt        ; signed integer\nBool       ; boolean\n'(Int)     ; list of Int\n[Int Bool] ; tuple of Int and Bool\n(Pure (-> (Int Int) Bool)) ; Pure function, which takes 2 integers and return boolean value\n(IO (-> (Int) [])) ; IO function, which takes an integer and return []\n----\n\nPure and IO are function effects.\nIn IO functions, both Pure and IO functions can be called.\nHowever, in Pure functions, calling only Pure functions is permitted.\n\n== Function Definition\n\nFunctions can be defined by defun or export.\n\"defun\" defines a local function which cannot be called from Rust's eval function.\n\nSuppose following 2 functions.\n\n.defun\n[source, lisp]\n----\n(defun double (x)         ; function name is \"double\" and \"x\" is an argument\n    (Pure (-> (Int) Int)) ; function Type\n    (* 2 x))              ; function body\n----\n\n.export\n[source, lisp]\n----\n(export quad (x)          ; function name is \"quad\" and \"x\" is an argument\n    (Pure (-> (Int) Int)) ; function Type\n    (double (double x)))  ; function body\n----\n\ndouble cannot be called from Rust's eval, but can be called from internally defined functions.\nquad can be called from Rust's eval, and it calls double internally.\n\nThis is the code what actually do in Rust.\n\n.Rust's eval\n[source, rust]\n----\nuse blisp;\n\nfn eval(e: &str, ctx: &blisp::semantics::Context) {\n    // evaluate expressions\n    let exprs = match blisp::eval(e, ctx) {\n        Ok(es) => es,\n        Err(err) => {\n            println!(\"error:{}:{}: {}\", err.pos.line, err.pos.column, err.msg);\n            return;\n        }\n    };\n\n    for r in exprs {\n        match r {\n            Ok(msg) => {\n                println!(\"{}\", msg);\n            }\n            Err(msg) => {\n                println!(\"error: {}\", msg);\n            }\n        }\n    }\n}\n\nfn main() {\n    // internal code\n    let code = \"\n(defun double (x)         ; function name is double and x is an argument\n    (Pure (-> (Int) Int)) ; function Type\n    (* 2 x))              ; function body\n\n(export quad (x)          ; function name is quad and x is an argument\n    (Pure (-> (Int) Int)) ; function Type\n    (double (double x)))  ; function body\n\";\n    let exprs = blisp::init(code, vec![]).unwrap();\n    let ctx = blisp::typing(&exprs).unwrap();\n\n    let e = \"(double 10) ; error\";\n    eval(e, &ctx);\n\n    let e = \"(quad 10) ; OK\";\n    eval(e, &ctx);\n}\n----\n\nThis code output as follows.\n\n error:0:1: Typing Error: double is not defined\n 40\n\n== Arithmetic Operations\n\n.basic\n[source, lisp]\n----\n; (Pure (-> (Int Int) Int))\n(+ 10 20)\n(- 30 40)\n(* 6 100)\n(/ 100 2)\n(% 10 3)\n----\n\n== Boolean Operations\n\n.logical\n[source, lisp]\n----\n; (Pure (-> (Bool Bool) Bool))\n(and true false)\n(or true false)\n(xor true false)\n----\n\n.negation\n[source, lisp]\n----\n; (Pure (-> (Bool) Bool))\n(not true)\n----\n\n== Comparison\n\n=, !=, <, >, \\<=, >= can be used for 2 values whose types are same.\n\n.comparison between 2 values whose types are same\n[source, lisp]\n----\n; (Pure (-> (t t) Bool))\n(= 4 4)               ; true\n(!= 4 4)              ; false\n(= \"Hello\" \"Hello\")   ; true\n(= (Some 1) (Some 2)) ; false\n(< 6 7)\n(> 6 7)\n(<= 30 40)\n(>= 30 40)\n(< \"Hello\" \"World\")\n(<= (Some 1) (Some 2))\n----\n\n_eq_, _neq_, _lt_, _gt_, _leq_, _geq_ can be used for any 2 values\n\n.comparison between any 2 values\n[source, lisp]\n----\n; (Pure (-> (t1 t1) Bool))\n(geq (Some 1) \"Hello\") ; (Some 1) is greater than or qeual to \"Hello\"\n(eq \"Hello\" 100)       ; Is \"Hello\" qeual to 100?\n(neq \"Hello\" 100)      ; Is \"Hello\" not equal to 100?\n(lt 100 (Some 20))     ; Is 100 less than (Some 20)?\n(gt 200 \"Hello\")       ; Is 200 greater than \"Hello\"\n----\n\n== Bitwise Operations\n\n[source, lisp]\n----\n(band 1 0) ; bitwise and\n(band 1 1) ; bitwise and\n(bor 1 0)  ; bitwise or\n(bor 1 1)  ; bitwise or\n(bxor 1 0) ; bitwise xor\n----\n\n.bit shift\n[source, lisp]\n----\n; (Pure (-> (Int Int) (Option Int)))\n(<< 8 4)   ; (Some 128)\n(>> 128 4) ; (Some 8)\n(>> -128 4) ; (Some -8)\n----\n\nIf 2nd argument is greater or equal to 2^64^, then these function return None.\n\n== Mathematical Operations\n\n[source, lisp]\n----\n; (Pure (-> (Int Int) (Option Int)))\n(pow 10 20) ; (Some 100000000000000000000)\n\n; (Pure (-> (Int) (Option Int)))\n(sqrt 16)   ; (Some 4)\n----\n\nIf _pow_'s exponent portion is greater or equal to 2^32^, then _pow_ returns None.\n\nIf _sqrt_'s argument is less than 0. then _sqrt_ returns None.\n\n== Algebraic Data Type\n\nAlgebraic data type can be defined as follows.\n\n[source, lisp]\n----\n; in BLisp\n(data Cardinal ; type name\n    East       ; value\n    North      ; value\n    West       ; value\n    South)     ; value\n----\n\nType name's and its value's first character must be uppercase.\nThis is equivalent to Rust's following code.\n\n[source, rust]\n----\n// in Rust\nenum Cardinal {\n    East,\n    North,\n    West,\n    South\n}\n----\n\nEach element can have values as follows.\n\n[source, lisp]\n----\n; in BLisp\n(data Dim2\n    (Dim2 Int Int)) ; Dim2 has integers\n----\n\nDim2 can be instantiated as follows.\n\n[source, lisp]\n----\n(Dim2 10 20)\n----\n\nThis type is equivalent to Rust's following type.\n\n[source, rust]\n----\n// in Rust\nuse num_bigint::BigInt;\nenum Dim2 {\n    Dim2(BigInt, BigInt)\n}\n----\n\n== Generics\n\nOption and Result types are defined internally.\n\n[source, lisp]\n----\n(data (Option t)\n    (Some t)\n    None)\n\n(data (Result t e)\n    (Ok t)\n    (Err e))\n----\n\n_t_ and _e_ are type variables.\nThis code is equivalent to Rust's following code.\n\n[source, rust]\n----\n// in Rust\nenum Option<T> {\n    Some(T),\n    None,\n}\n\nenum Result<T, E> {\n    Ok(T),\n    Err(E),\n}\n----\n\nList type is a built-in type as follows.\n\n[source, lisp]\n----\n(data (List t)\n    (Cons t (List t))\n    Nil)\n----\n\nSo, following 2 lists are equivalent.\n\n[source, lisp]\n----\n(Cons 1 (Cons 2 (Cons 3 Nil)))\n'(1 2 3)\n----\n\n== Generic Function\n\n_car_ and _cdr_ are internally defined generic functions.\nThese definitions are as follows.\n\n[source, lisp]\n----\n(export car (x) (Pure (-> ('(t)) (Option t)))\n    (match x\n        ((Cons n _) (Some n))\n        (_ None)))\n\n(export cdr (x) (Pure (-> ('(t)) '(t)))\n    (match x\n        ((Cons _ l) l)\n        (_ '())))\n----\n\n_t_ is a type variable. These functions can be used as follows.\n\n[source, lisp]\n----\n(car '(3 8 9))  ; returns (Some 3)\n(cdr '(8 10 4)) ; returns '(10 4)\n----\n\nNormal and type variables' first character must be lowercase.\n\n== If Expression\n\nStraightforward.\n\n[source, lisp]\n----\n(if (< 10 20)\n    '(1 2 3)\n    '())\n----\n\n== Match Expression\n\nA list can be matched as follows.\n\n[source, lisp]\n----\n(match '(1 2 3)\n    ((Cons n _) n)\n    ('() 0))\n----\n\nThe expression\n\n (Cons n _)\n\nis a pattern.\nIf the pattern is matched to '(1 2 3), 1 is assigned to a variable _n_. Then, _n_, namely 1, is returned.\n\nThis is an example of pattern matching of tuple.\n\n[source, lisp]\n----\n(match [1 3]\n    ([x y] [y x]))\n----\n\nThis code swap 1st and 2nd elements of the tuple.\n\nInteger values can be also used for pattern matching.\n\n[source, lisp]\n----\n(match 20\n    (20 true)\n    (_ false))\n----\n\nMore complex example is a as follows.\n\n[source, lisp]\n----\n(match [(Some 10) true]\n    ([(Some 10) false] 1)\n    ([(Some 10) true] 2)\n    (_ 0))\n----\n\nBLisp checks exhaustively of pattern.\nSo, following code will be rejected.\n\n[source, lisp]\n----\n(match '(1 2)\n    ('() 0))\n----\n\n== Let Expression\n\nLet expression is used to bind variables as follows.\n\n[source, lisp]\n----\n(let ((x 10) (y 20)) ; x is 10, y is 20\n    (* x y))\n\n(let ((x 10) (x (* x x)) (x (* x x))) ; x = 10, x = x * x, x = x * x\n    x)\n----\n\nDestructuring can be also performed as follows.\n\n[source, lisp]\n----\n(let (((Some x) (Some 10))) ; x is 10\n    (* x 2))\n\n(let (([x y] [10 20])) ; x is 10, y is 20\n    (* x y))\n----\n\n== Lambda Expression\n\nLambda expression is defined as follows.\n\n[source, lisp]\n----\n(lambda (x y) (* x y))\n----\n\nThis lambda takes 2 integers and return the multiplication.\nApplying arguments to this is simple as follows.\n\n[source, lisp]\n----\n((lambda (x y) (* x y)) 10 20)\n----\n\nEvery lambda expression is Pure.\nIO functions cannot be called in any lambda expressions.\n\n_map_ and _fold_ functions are internally defined as follows.\n\n[source, lisp]\n----\n(export map (f x) (Pure (-> ((Pure (-> (a) b)) '(a)) '(b)))\n    (match x\n        ((Cons h l) (Cons (f h) (map f l)))\n        (_ '())))\n\n(export fold (f init x) (Pure (-> ((Pure (-> (a b) b)) b '(a)) b))\n    (match x\n        ((Cons h l) (fold f (f h init) l))\n        (_ init)))\n----\n\n_map_ can be used to apply functions to elements of a list as follows.\n\n[source, lisp]\n----\n; square each element\n(let ((l '(1 2 3))\n      (f (lambda (x) (* x x))))\n        (map f l))\n----\n\n_fold_ can be used to calculate over elements of a list.\nFor example, summation can be computed as follows.\n\n[source, lisp]\n----\n; summation\n(let ((l '(20 50 60))\n      (f (lambda (x y) (+ x y))))\n        (fold f 0 l)) ; 0 is an initial value\n----\n\nOf course, this can be written as follows.\n\n[source, lisp]\n----\n; summation\n(fold + 0 '(20 50 60))\n----\n\n== Macro\n\nMacros can be defined by `macro`.\nEach rule consists of a pattern and a template, and the first matching rule is expanded.\n\n[source, lisp]\n----\n(macro add\n    ((add $e1 $e2) (+ $e1 $e2))\n    ((add $e1 $e2 $e3 ...) (+ $e1 (add $e2 $e3 ...))))\n----\n\nIdentifiers beginning with `$` are pattern variables.\nThey are substituted with the expressions matched at the call site.\n`...` can be used after a pattern variable or a template fragment to match and expand the remaining arguments.\n\n[source, lisp]\n----\n(add 1 2)         ; 3\n(add 1 2 3 4 5)   ; 15\n----\n\nMacros can also generate expressions that introduce local bindings.\nFor example, a temporary variable can be introduced in a lambda expression.\n\n[source, lisp]\n----\n(macro with_tmp\n    ((_ $x) ((lambda (tmp) (+ tmp $x)) 1)))\n\n(export test (tmp) (Pure (-> (Int) Int))\n    (with_tmp tmp))\n----\n\nBLisp macros are hygienic for local binders introduced by macro templates.\nVariables 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.\nTop-level names such as `defun`, `export`, and `data` definitions are not renamed automatically.\n\n== String and Character\n\n_chars_ converts String to (List Char).\n\n[source, lisp]\n----\n; (Pure (-> (String) (List Char)))\n(chars \"Hello\") ; '(`H` `e` `l` `l` `o`)\n----\n\n_str_ converts (List Char) to String.\n\n[source, lisp]\n----\n; (Pure (-> ((List Char)) String))\n(str '(`H` `e` `l` `l` `o`)) ; \"Hello\"\n----\n\n== Foreign Function Interface\n\n_blisp::embedded_ is a macro for foreign function interface.\nBy using this, Rust's functions can be called from BLisp easily.\n\nFor example, first of all, define a Rust function as follows.\n\n[source, rust]\n----\nuse blisp::embedded;\nuse num_bigint::{BigInt, ToBigInt};\n\n#[embedded]\nfn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> Result<BigInt, String> {\n    let mut result = a + b.0 + b.1;\n    if let Some(n) = c {\n        result += n;\n    }\n\n    Ok(result)\n}\n----\n\n_blisp::embedded_ macro generates a type definition for FFI.\nThis function can be called from BLisp as follows.\n\n[source, lisp]\n----\n(export call_add_four_ints (n)\n    (IO (-> ((Option Int)) (Result Int String)))\n    (add_four_ints 1 [2 3] n))\n----\n\nTo register FFIs, a vector of the definition generated by _embedded_ macro\nmust be passed to _blisp::init_ as follows.\n\n[source, rust]\n----\n// add_for_ints\nlet code = \"(export call_add_four_ints (n)\n    (IO (-> ((Option Int)) (Result Int String)))\n    (add_four_ints 1 [2 3] n)\n)\";\nlet exprs = blisp::init(code, vec![Box::new(AddFourInts)]).unwrap();\nlet ctx = blisp::typing(exprs).unwrap();\nlet result = blisp::eval(\"(call_add_four_ints (Some 4))\", &ctx).unwrap();\n----\n\nThe function name is _add_four_ints_, then _AddFourInts_, which is camel case,\nmust be passed to _blisp::init_ capsulated by _Box_ and _Vec_.\n\nFFIs in Rust take and return only types described as follows.\nOther types, like _Vec<u64>_, are not supported,\nbut _Vec<Option<bool>>_ is accepted.\nTypes between BLisp and Rust are automatically converted by\nthe function generated by _embedded_ macro.\n\n.Type Conversion between BLisp and Rust\n|===\n|BLisp          | Rust\n\n|_Int_          | _BigInt_\n|_Bool_         | _bool_\n|_Char_         | _char_\n|_String_       | _String_\n|_'(T)_         | _Vec<T>_\n|_[T0, T1]_     | _(T0, T1)_\n|_(Option T)_   | _Option<T>_\n|_(Result T E)_ | _Result<T, E>_\n|===\n\nNote that every FFI is treated as IO functions.\n\n== Transpilation to Coq (Experimental)\n\nBLisp experimentally implements a transpiler to Coq.\nIt can be invoked by calling _blisp::transpile_ as follows.\n\n[source, coq]\n----\nlet expr = \"\n(defun snoc (l y)\n(Pure (-> (\n    '(t) t)\n'(t)))\n(match l\n    (nil (Cons y nil))\n    ((Cons h b) (Cons h (snoc b y)))))\n\n(defun rev (l)\n(Pure (-> (\n    '(t))\n'(t)))\n(match l\n    (nil nil)\n    ((Cons h t) (snoc (rev t) h))))\n    \";\nlet exprs = blisp::init(expr, vec![]).unwrap();\nlet ctx = blisp::typing(exprs).unwrap();\n\nprintln!(\"{}\", blisp::transpile(&ctx));\n----\n\nThis outputs Coq code as follows.\nIt includes as well as the prelude of BLisp.\n\n[source, coq]\n----\nRequire Import ZArith.\nRequire Import Coq.Lists.List.\n\nInductive Option (t: Type): Type :=\n| Some (x0: t)\n| None.\n\nArguments Some{t}.\nArguments None{t}.\n\nInductive Result (t e: Type): Type :=\n| Ok (x0: t)\n| Err (x0: e).\n\nArguments Ok{t e}.\nArguments Err{t e}.\n\nDefinition car {t: Type} (x: list t): Option t :=\nmatch x with\n  | (cons n _) => (Some n)\n  | _ => (None)\n  end.\n\nDefinition cdr {t: Type} (x: list t): list t :=\nmatch x with\n  | (cons _ l) => l\n  | _ => nil\n  end.\n\nDefinition filter {t: Type} (f: t -> bool) (x: list t): list t :=\n(reverse (filter' f x nil ) ).\n\nFixpoint filter' {t: Type} (f: t -> bool) (x l: list t): list t :=\nmatch x with\n  | (cons h a) => match (f h ) with\n    | true => (filter' f a (cons h l) )\n    | false => (filter' f a l )\n    end\n  | _ => l\n  end.\n\nFixpoint fold {a b: Type} (f: a -> b -> b) (init: b) (x: list a): b :=\nmatch x with\n  | (cons h l) => (fold f (f h init ) l )\n  | _ => init\n  end.\n\nFixpoint map {a b: Type} (f: a -> b) (x: list a): list b :=\nmatch x with\n  | (cons h l) => (cons (f h ) (map f l ))\n  | _ => nil\n  end.\n\nFixpoint rev {t: Type} (l: list t): list t :=\nmatch l with\n  | nil => nil\n  | (cons h t) => (snoc (rev t ) h )\n  end.\n\nDefinition reverse {t: Type} (x: list t): list t :=\n(reverse' x nil ).\n\nFixpoint reverse' {t: Type} (x l: list t): list t :=\nmatch x with\n  | (cons h a) => (reverse' a (cons h l) )\n  | _ => l\n  end.\n\nFixpoint snoc {t: Type} (l: list t) (y: t): list t :=\nmatch l with\n  | nil => (cons y nil)\n  | (cons h b) => (cons h (snoc b y ))\n  end.\n----\n\nNot that this transpiler is experimental.\nSo, Coq cannot interpret some outputs.\nPlease fix it manually when you encounter that situation.\nIt is probably easy.\n\n== Examples\n\n=== Reverse\n\n_reverse_ is a internally defined function. It reverses order of a list.\n\n[source, lisp]\n----\n(reverse '(1 2 3 4 5 6 7 8 9))\n----\n\nThis outputs as follows.\n\n '(9 8 7 6 5 4 3 2 1)\n\n=== Filter\n\n_filter_ is a internally defined function. It filters the elements in a list.\n\n[source, lisp]\n----\n(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9))\n----\n\nThis outputs as follows.\n\n '(2 4 6 8)\n\n_filter_'s type is as follows.\n\n[source, lisp]\n----\n(Pure (->\n    ((Pure (-> (t) Bool)) ; take a function\n     '(t))                ; take a list\n    '(t))) ; return a list\n----\n\n=== Factorial\n\nTail call factorial can be coded as follows.\n\n[source, lisp]\n----\n(export factorial (n) (Pure (-> (Int) Int))\n    (fact n 1))\n\n(defun fact (n total) (Pure (-> (Int Int) Int))\n    (if (<= n 0)\n        total\n        (fact (- n 1) (* n total))))\n----\n\nThis function can be called as follows.\n\n >> (factorial 10)\n 3628800\n >>\n >> (factorial 1000)\n 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n >>\n >> (factorial 100)\n 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n >>\n >> (factorial 500)\n 1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.20\">\n<meta name=\"author\" content=\"Yuuki Takano\">\n<title>BLisp: A Statically Typed Lisp Like Language</title>\n<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\">\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @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\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{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}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.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}\ndiv,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}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,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}\nh1 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}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable 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}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n: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}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre>code{display:block}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{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}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#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}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#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}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\n#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}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#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}\n#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}\n#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}\n#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}\n#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}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>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%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.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}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.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)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.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}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.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}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.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}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.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}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.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}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.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)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.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}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.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}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.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}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.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}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.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}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n<style>\npre.pygments .hll { background-color: #ffffcc }\npre.pygments { background: #f8f8f8; }\npre.pygments .tok-c { color: #3D7B7B; font-style: italic } /* Comment */\npre.pygments .tok-err { border: 1px solid #FF0000 } /* Error */\npre.pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */\npre.pygments .tok-o { color: #666666 } /* Operator */\npre.pygments .tok-ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\npre.pygments .tok-cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\npre.pygments .tok-cp { color: #9C6500 } /* Comment.Preproc */\npre.pygments .tok-cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\npre.pygments .tok-c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\npre.pygments .tok-cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\npre.pygments .tok-gd { color: #A00000 } /* Generic.Deleted */\npre.pygments .tok-ge { font-style: italic } /* Generic.Emph */\npre.pygments .tok-ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\npre.pygments .tok-gr { color: #E40000 } /* Generic.Error */\npre.pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */\npre.pygments .tok-gi { color: #008400 } /* Generic.Inserted */\npre.pygments .tok-go { color: #717171 } /* Generic.Output */\npre.pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */\npre.pygments .tok-gs { font-weight: bold } /* Generic.Strong */\npre.pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */\npre.pygments .tok-gt { color: #0044DD } /* Generic.Traceback */\npre.pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */\npre.pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\npre.pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\npre.pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */\npre.pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\npre.pygments .tok-kt { color: #B00040 } /* Keyword.Type */\npre.pygments .tok-m { color: #666666 } /* Literal.Number */\npre.pygments .tok-s { color: #BA2121 } /* Literal.String */\npre.pygments .tok-na { color: #687822 } /* Name.Attribute */\npre.pygments .tok-nb { color: #008000 } /* Name.Builtin */\npre.pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */\npre.pygments .tok-no { color: #880000 } /* Name.Constant */\npre.pygments .tok-nd { color: #AA22FF } /* Name.Decorator */\npre.pygments .tok-ni { color: #717171; font-weight: bold } /* Name.Entity */\npre.pygments .tok-ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\npre.pygments .tok-nf { color: #0000FF } /* Name.Function */\npre.pygments .tok-nl { color: #767600 } /* Name.Label */\npre.pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\npre.pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */\npre.pygments .tok-nv { color: #19177C } /* Name.Variable */\npre.pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\npre.pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */\npre.pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */\npre.pygments .tok-mf { color: #666666 } /* Literal.Number.Float */\npre.pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */\npre.pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */\npre.pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */\npre.pygments .tok-sa { color: #BA2121 } /* Literal.String.Affix */\npre.pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */\npre.pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */\npre.pygments .tok-dl { color: #BA2121 } /* Literal.String.Delimiter */\npre.pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\npre.pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */\npre.pygments .tok-se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\npre.pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */\npre.pygments .tok-si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\npre.pygments .tok-sx { color: #008000 } /* Literal.String.Other */\npre.pygments .tok-sr { color: #A45A77 } /* Literal.String.Regex */\npre.pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */\npre.pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */\npre.pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */\npre.pygments .tok-fm { color: #0000FF } /* Name.Function.Magic */\npre.pygments .tok-vc { color: #19177C } /* Name.Variable.Class */\npre.pygments .tok-vg { color: #19177C } /* Name.Variable.Global */\npre.pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */\npre.pygments .tok-vm { color: #19177C } /* Name.Variable.Magic */\npre.pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */\n</style>\n</head>\n<body class=\"article\">\n<div id=\"header\">\n<h1>BLisp: A Statically Typed Lisp Like Language</h1>\n<div class=\"details\">\n<span id=\"author\" class=\"author\">Yuuki Takano</span><br>\n<span id=\"email\" class=\"email\"><a href=\"mailto:ytakano@wide.ad.jp\">ytakano@wide.ad.jp</a></span><br>\n<span id=\"revnumber\">version 0.4.0,</span>\n<span id=\"revdate\">2023-02</span>\n</div>\n<div id=\"toc\" class=\"toc\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_features\">1. Features</a></li>\n<li><a href=\"#_values\">2. Values</a></li>\n<li><a href=\"#_basic_types\">3. Basic Types</a></li>\n<li><a href=\"#_function_definition\">4. Function Definition</a></li>\n<li><a href=\"#_arithmetic_operations\">5. Arithmetic Operations</a></li>\n<li><a href=\"#_boolean_operations\">6. Boolean Operations</a></li>\n<li><a href=\"#_comparison\">7. Comparison</a></li>\n<li><a href=\"#_bitwise_operations\">8. Bitwise Operations</a></li>\n<li><a href=\"#_mathematical_operations\">9. Mathematical Operations</a></li>\n<li><a href=\"#_algebraic_data_type\">10. Algebraic Data Type</a></li>\n<li><a href=\"#_generics\">11. Generics</a></li>\n<li><a href=\"#_generic_function\">12. Generic Function</a></li>\n<li><a href=\"#_if_expression\">13. If Expression</a></li>\n<li><a href=\"#_match_expression\">14. Match Expression</a></li>\n<li><a href=\"#_let_expression\">15. Let Expression</a></li>\n<li><a href=\"#_lambda_expression\">16. Lambda Expression</a></li>\n<li><a href=\"#_macro\">17. Macro</a></li>\n<li><a href=\"#_string_and_character\">18. String and Character</a></li>\n<li><a href=\"#_foreign_function_interface\">19. Foreign Function Interface</a></li>\n<li><a href=\"#_transpilation_to_coq_experimental\">20. Transpilation to Coq (Experimental)</a></li>\n<li><a href=\"#_examples\">21. Examples</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_reverse\">21.1. Reverse</a></li>\n<li><a href=\"#_filter\">21.2. Filter</a></li>\n<li><a href=\"#_factorial\">21.3. Factorial</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>BLisp is a statically typed Lisp like programming language which adopts effect system for no_std environments.\nBLisp supports higher order RPC like higher order functions of functional programming languages.</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><a href=\"https://github.com/ytakano/blisp\">GitHub&#8217;s Repository</a></p>\n</li>\n<li>\n<p><a href=\"https://crates.io/crates/blisp\">BLisp&#8217;s crates.io</a></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>This repository provides only a library crate.\nPlease see <a href=\"https://github.com/ytakano/blisp-repl\">blisp-repl</a> to use BLisp,\nand <a href=\"https://github.com/ytakano/baremetalisp\">baremetalisp</a> which is a toy OS.</p>\n</div>\n<div class=\"paragraph\">\n<p><a href=\"https://ytakano.github.io/blisp/index.ja.html\">日本語版はこちら</a></p>\n</div>\n<div class=\"paragraph\">\n<div class=\"title\">BLisp on no_std Environment</div>\n<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>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_features\">1. Features</h2>\n<div class=\"sectionbody\">\n<div class=\"ulist\">\n<ul>\n<li>\n<p>Algebraic data type</p>\n</li>\n<li>\n<p>Generics</p>\n</li>\n<li>\n<p>Hindley–Milner based type inference</p>\n</li>\n<li>\n<p>Effect system to separate side effects from pure functions</p>\n</li>\n<li>\n<p>Big integer</p>\n</li>\n<li>\n<p>Supporting no_std environments</p>\n</li>\n</ul>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_values\">2. Values</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">values</div>\n<div class=\"content\">\n<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>\n<span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-w\">   </span><span class=\"tok-c1\">; string literal</span>\n<span class=\"tok-mi\">144</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; integer value</span>\n<span class=\"tok-nv\">0xabcDEF</span><span class=\"tok-w\">  </span><span class=\"tok-c1\">; hexadecimal</span>\n<span class=\"tok-nv\">0o777</span><span class=\"tok-w\">     </span><span class=\"tok-c1\">; octal</span>\n<span class=\"tok-nv\">0b1001</span><span class=\"tok-w\">    </span><span class=\"tok-c1\">; binary</span>\n<span class=\"tok-nv\">true</span><span class=\"tok-w\">      </span><span class=\"tok-c1\">; boolean value</span>\n<span class=\"tok-nv\">false</span><span class=\"tok-w\">     </span><span class=\"tok-c1\">; boolean value</span>\n<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>\n<span class=\"tok-nv\">[]</span><span class=\"tok-w\">        </span><span class=\"tok-c1\">; empty tuple</span>\n<span class=\"tok-o\">&#39;</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>\n<span class=\"tok-o\">&#39;</span><span class=\"tok-p\">()</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; empty list, Nil</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_basic_types\">3. Basic Types</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">types</div>\n<div class=\"content\">\n<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>\n<span class=\"tok-nv\">String</span><span class=\"tok-w\">     </span><span class=\"tok-c1\">; string</span>\n<span class=\"tok-nv\">Int</span><span class=\"tok-w\">        </span><span class=\"tok-c1\">; signed integer</span>\n<span class=\"tok-nv\">Bool</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; boolean</span>\n<span class=\"tok-o\">&#39;</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>\n<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>\n<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\">-&gt;</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>\n<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\">-&gt;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Pure and IO are function effects.\nIn IO functions, both Pure and IO functions can be called.\nHowever, in Pure functions, calling only Pure functions is permitted.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_function_definition\">4. Function Definition</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Functions can be defined by defun or export.\n\"defun\" defines a local function which cannot be called from Rust&#8217;s eval function.</p>\n</div>\n<div class=\"paragraph\">\n<p>Suppose following 2 functions.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">defun</div>\n<div class=\"content\">\n<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 &quot;double&quot; and &quot;x&quot; is an argument</span>\n<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\">-&gt;</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>\n<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>\n</div>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">export</div>\n<div class=\"content\">\n<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 &quot;quad&quot; and &quot;x&quot; is an argument</span>\n<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\">-&gt;</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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>double cannot be called from Rust&#8217;s eval, but can be called from internally defined functions.\nquad can be called from Rust&#8217;s eval, and it calls double internally.</p>\n</div>\n<div class=\"paragraph\">\n<p>This is the code what actually do in Rust.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">Rust&#8217;s eval</div>\n<div class=\"content\">\n<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>\n\n<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\">&amp;</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\">&amp;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-c1\">// evaluate expressions</span>\n<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>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-n\">es</span><span class=\"tok-p\">,</span>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">            </span><span class=\"tok-fm\">println!</span><span class=\"tok-p\">(</span><span class=\"tok-s\">&quot;error:{}:{}: {}&quot;</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>\n<span class=\"tok-w\">            </span><span class=\"tok-k\">return</span><span class=\"tok-p\">;</span>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">}</span>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">};</span>\n\n<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>\n<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>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">                </span><span class=\"tok-fm\">println!</span><span class=\"tok-p\">(</span><span class=\"tok-s\">&quot;{}&quot;</span><span class=\"tok-p\">,</span><span class=\"tok-w\"> </span><span class=\"tok-n\">msg</span><span class=\"tok-p\">);</span>\n<span class=\"tok-w\">            </span><span class=\"tok-p\">}</span>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">                </span><span class=\"tok-fm\">println!</span><span class=\"tok-p\">(</span><span class=\"tok-s\">&quot;error: {}&quot;</span><span class=\"tok-p\">,</span><span class=\"tok-w\"> </span><span class=\"tok-n\">msg</span><span class=\"tok-p\">);</span>\n<span class=\"tok-w\">            </span><span class=\"tok-p\">}</span>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">}</span>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">}</span>\n<span class=\"tok-p\">}</span>\n\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-c1\">// internal code</span>\n<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\">&quot;</span>\n<span class=\"tok-s\">(defun double (x)         ; function name is double and x is an argument</span>\n<span class=\"tok-s\">    (Pure (-&gt; (Int) Int)) ; function Type</span>\n<span class=\"tok-s\">    (* 2 x))              ; function body</span>\n\n<span class=\"tok-s\">(export quad (x)          ; function name is quad and x is an argument</span>\n<span class=\"tok-s\">    (Pure (-&gt; (Int) Int)) ; function Type</span>\n<span class=\"tok-s\">    (double (double x)))  ; function body</span>\n<span class=\"tok-s\">&quot;</span><span class=\"tok-p\">;</span>\n<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>\n<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\">&amp;</span><span class=\"tok-n\">exprs</span><span class=\"tok-p\">).</span><span class=\"tok-n\">unwrap</span><span class=\"tok-p\">();</span>\n\n<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\">&quot;(double 10) ; error&quot;</span><span class=\"tok-p\">;</span>\n<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\">&amp;</span><span class=\"tok-n\">ctx</span><span class=\"tok-p\">);</span>\n\n<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\">&quot;(quad 10) ; OK&quot;</span><span class=\"tok-p\">;</span>\n<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\">&amp;</span><span class=\"tok-n\">ctx</span><span class=\"tok-p\">);</span>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This code output as follows.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>error:0:1: Typing Error: double is not defined\n40</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_arithmetic_operations\">5. Arithmetic Operations</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">basic</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Int Int) Int))</span>\n<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>\n<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>\n<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>\n<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>\n<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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_boolean_operations\">6. Boolean Operations</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">logical</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Bool Bool) Bool))</span>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">negation</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Bool) Bool))</span>\n<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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_comparison\">7. Comparison</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>=, !=, &lt;, &gt;, &lt;=, &gt;= can be used for 2 values whose types are same.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">comparison between 2 values whose types are same</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (t t) Bool))</span>\n<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>\n<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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">=</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\">   </span><span class=\"tok-c1\">; true</span>\n<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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&gt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;=</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&gt;=</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;World&quot;</span><span class=\"tok-p\">)</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;=</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<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>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">comparison between any 2 values</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (t1 t1) Bool))</span>\n<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\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\"> </span><span class=\"tok-c1\">; (Some 1) is greater than or qeual to &quot;Hello&quot;</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">eq</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</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 &quot;Hello&quot; qeual to 100?</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">neq</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</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 &quot;Hello&quot; not equal to 100?</span>\n<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>\n<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\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; Is 200 greater than &quot;Hello&quot;</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bitwise_operations\">8. Bitwise Operations</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">bit shift</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Int Int) (Option Int)))</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">&lt;&lt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">&gt;&gt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">&gt;&gt;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If 2nd argument is greater or equal to 2<sup>64</sup>, then these function return None.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_mathematical_operations\">9. Mathematical Operations</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Int Int) (Option Int)))</span>\n<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>\n\n<span class=\"tok-c1\">; (Pure (-&gt; (Int) (Option Int)))</span>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If <em>pow</em>'s exponent portion is greater or equal to 2<sup>32</sup>, then <em>pow</em> returns None.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <em>sqrt</em>'s argument is less than 0. then <em>sqrt</em> returns None.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_algebraic_data_type\">10. Algebraic Data Type</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Algebraic data type can be defined as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; in BLisp</span>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">East</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; value</span>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">North</span><span class=\"tok-w\">      </span><span class=\"tok-c1\">; value</span>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">West</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; value</span>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Type name&#8217;s and its value&#8217;s first character must be uppercase.\nThis is equivalent to Rust&#8217;s following code.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// in Rust</span>\n<span class=\"tok-k\">enum</span> <span class=\"tok-nc\">Cardinal</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">East</span><span class=\"tok-p\">,</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">North</span><span class=\"tok-p\">,</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">West</span><span class=\"tok-p\">,</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">South</span>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Each element can have values as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; in BLisp</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">data</span><span class=\"tok-w\"> </span><span class=\"tok-nv\">Dim2</span>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Dim2 can be instantiated as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This type is equivalent to Rust&#8217;s following type.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// in Rust</span>\n<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>\n<span class=\"tok-k\">enum</span> <span class=\"tok-nc\">Dim2</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_generics\">11. Generics</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Option and Result types are defined internally.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">None</span><span class=\"tok-p\">)</span>\n\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>t</em> and <em>e</em> are type variables.\nThis code is equivalent to Rust&#8217;s following code.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// in Rust</span>\n<span class=\"tok-k\">enum</span> <span class=\"tok-nb\">Option</span><span class=\"tok-o\">&lt;</span><span class=\"tok-n\">T</span><span class=\"tok-o\">&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nb\">None</span><span class=\"tok-p\">,</span>\n<span class=\"tok-p\">}</span>\n\n<span class=\"tok-k\">enum</span> <span class=\"tok-nb\">Result</span><span class=\"tok-o\">&lt;</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\">&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<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>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>List type is a built-in type as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-no\">Nil</span><span class=\"tok-p\">)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>So, following 2 lists are equivalent.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<span class=\"tok-o\">&#39;</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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_generic_function\">12. Generic Function</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>car</em> and <em>cdr</em> are internally defined generic functions.\nThese definitions are as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</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>\n<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>\n<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>\n<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>\n\n<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\">-&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</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\">&#39;</span><span class=\"tok-p\">(</span><span class=\"tok-no\">t</span><span class=\"tok-p\">)))</span>\n<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>\n<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>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">(</span><span class=\"tok-nv\">_</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">())))</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>t</em> is a type variable. These functions can be used as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">cdr</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</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 &#39;(10 4)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Normal and type variables' first character must be lowercase.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_if_expression\">13. If Expression</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Straightforward.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&lt;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-o\">&#39;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">())</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_match_expression\">14. Match Expression</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>A list can be matched as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">()</span><span class=\"tok-w\"> </span><span class=\"tok-mi\">0</span><span class=\"tok-p\">))</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The expression</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>(Cons n _)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>is a pattern.\nIf 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>\n</div>\n<div class=\"paragraph\">\n<p>This is an example of pattern matching of tuple.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This code swap 1st and 2nd elements of the tuple.</p>\n</div>\n<div class=\"paragraph\">\n<p>Integer values can be also used for pattern matching.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>More complex example is a as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>BLisp checks exhaustively of pattern.\nSo, following code will be rejected.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">()</span><span class=\"tok-w\"> </span><span class=\"tok-mi\">0</span><span class=\"tok-p\">))</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_let_expression\">15. Let Expression</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Let expression is used to bind variables as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">x</span><span class=\"tok-p\">)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Destructuring can be also performed as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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>\n<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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_lambda_expression\">16. Lambda Expression</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Lambda expression is defined as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This lambda takes 2 integers and return the multiplication.\nApplying arguments to this is simple as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Every lambda expression is Pure.\nIO functions cannot be called in any lambda expressions.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>map</em> and <em>fold</em> functions are internally defined as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</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\">-&gt;</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\">&#39;</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\">&#39;</span><span class=\"tok-p\">(</span><span class=\"tok-nv\">b</span><span class=\"tok-p\">)))</span>\n<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>\n<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>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">(</span><span class=\"tok-nv\">_</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">())))</span>\n\n<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\">-&gt;</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\">-&gt;</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\">&#39;</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>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>map</em> can be used to apply functions to elements of a list as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; square each element</span>\n<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\">&#39;</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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>fold</em> can be used to calculate over elements of a list.\nFor example, summation can be computed as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; summation</span>\n<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\">&#39;</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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Of course, this can be written as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; summation</span>\n<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\">&#39;</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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_macro\">17. Macro</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Macros can be defined by <code>macro</code>.\nEach rule consists of a pattern and a template, and the first matching rule is expanded.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Identifiers beginning with <code>$</code> are pattern variables.\nThey are substituted with the expressions matched at the call site.\n<code>&#8230;&#8203;</code> can be used after a pattern variable or a template fragment to match and expand the remaining arguments.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Macros can also generate expressions that introduce local bindings.\nFor example, a temporary variable can be introduced in a lambda expression.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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\">-&gt;</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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>BLisp macros are hygienic for local binders introduced by macro templates.\nVariables 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.\nTop-level names such as <code>defun</code>, <code>export</code>, and <code>data</code> definitions are not renamed automatically.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_string_and_character\">18. String and Character</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>chars</em> converts String to (List Char).</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (String) (List Char)))</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">chars</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\"> </span><span class=\"tok-c1\">; &#39;(`H` `e` `l` `l` `o`)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>str</em> converts (List Char) to String.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; ((List Char)) String))</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">str</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</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\">; &quot;Hello&quot;</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_foreign_function_interface\">19. Foreign Function Interface</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>blisp::embedded</em> is a macro for foreign function interface.\nBy using this, Rust&#8217;s functions can be called from BLisp easily.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example, first of all, define a Rust function as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<span class=\"tok-cp\">#[embedded]</span>\n<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\">&lt;</span><span class=\"tok-n\">BigInt</span><span class=\"tok-o\">&gt;</span><span class=\"tok-p\">)</span><span class=\"tok-w\"> </span>-&gt; <span class=\"tok-nb\">Result</span><span class=\"tok-o\">&lt;</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\">&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">}</span>\n\n<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>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>blisp::embedded</em> macro generates a type definition for FFI.\nThis function can be called from BLisp as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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\">-&gt;</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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To register FFIs, a vector of the definition generated by <em>embedded</em> macro\nmust be passed to <em>blisp::init</em> as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// add_for_ints</span>\n<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\">&quot;(export call_add_four_ints (n)</span>\n<span class=\"tok-s\">    (IO (-&gt; ((Option Int)) (Result Int String)))</span>\n<span class=\"tok-s\">    (add_four_ints 1 [2 3] n)</span>\n<span class=\"tok-s\">)&quot;</span><span class=\"tok-p\">;</span>\n<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>\n<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>\n<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\">&quot;(call_add_four_ints (Some 4))&quot;</span><span class=\"tok-p\">,</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&amp;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The function name is <em>add_four_ints</em>, then <em>AddFourInts</em>, which is camel case,\nmust be passed to <em>blisp::init</em> capsulated by <em>Box</em> and <em>Vec</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>FFIs in Rust take and return only types described as follows.\nOther types, like <em>Vec&lt;u64&gt;</em>, are not supported,\nbut <em>Vec&lt;Option&lt;bool&gt;&gt;</em> is accepted.\nTypes between BLisp and Rust are automatically converted by\nthe function generated by <em>embedded</em> macro.</p>\n</div>\n<table class=\"tableblock frame-all grid-all stretch\">\n<caption class=\"title\">Table 1. Type Conversion between BLisp and Rust</caption>\n<colgroup>\n<col style=\"width: 50%;\">\n<col style=\"width: 50%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-top\">BLisp</th>\n<th class=\"tableblock halign-left valign-top\">Rust</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Int</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>BigInt</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Bool</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>bool</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Char</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>char</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>String</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>String</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>'(T)</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Vec&lt;T&gt;</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>[T0, T1]</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>(T0, T1)</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>(Option T)</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Option&lt;T&gt;</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>(Result T E)</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Result&lt;T, E&gt;</em></p></td>\n</tr>\n</tbody>\n</table>\n<div class=\"paragraph\">\n<p>Note that every FFI is treated as IO functions.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_transpilation_to_coq_experimental\">20. Transpilation to Coq (Experimental)</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>BLisp experimentally implements a transpiler to Coq.\nIt can be invoked by calling <em>blisp::transpile</em> as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&quot;</span>\n<span class=\"tok-s2\">(defun snoc (l y)</span>\n<span class=\"tok-s2\">(Pure (-&gt; (</span>\n<span class=\"tok-s2\">    &#39;(t) t)</span>\n<span class=\"tok-s2\">&#39;(t)))</span>\n<span class=\"tok-s2\">(match l</span>\n<span class=\"tok-s2\">    (nil (Cons y nil))</span>\n<span class=\"tok-s2\">    ((Cons h b) (Cons h (snoc b y)))))</span>\n\n<span class=\"tok-s2\">(defun rev (l)</span>\n<span class=\"tok-s2\">(Pure (-&gt; (</span>\n<span class=\"tok-s2\">    &#39;(t))</span>\n<span class=\"tok-s2\">&#39;(t)))</span>\n<span class=\"tok-s2\">(match l</span>\n<span class=\"tok-s2\">    (nil nil)</span>\n<span class=\"tok-s2\">    ((Cons h t) (snoc (rev t) h))))</span>\n<span class=\"tok-s2\">    &quot;</span><span class=\"tok-o\">;</span>\n<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>\n<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>\n\n<span class=\"tok-n\">println</span><span class=\"tok-o\">!(</span><span class=\"tok-s2\">&quot;{}&quot;</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\">(&amp;</span><span class=\"tok-n\">ctx</span><span class=\"tok-o\">));</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This outputs Coq code as follows.\nIt includes as well as the prelude of BLisp.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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>\n<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>\n<span class=\"tok-o\">|</span> <span class=\"tok-n\">None</span><span class=\"tok-o\">.</span>\n\n<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>\n<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>\n\n<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>\n<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>\n<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>\n\n<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>\n<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>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">Some</span> <span class=\"tok-n\">n</span><span class=\"tok-o\">)</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">None</span><span class=\"tok-o\">)</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</span> <span class=\"tok-n\">l</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">nil</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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\">-&gt;</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>\n<span class=\"tok-o\">(</span><span class=\"tok-n\">reverse</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">filter&#39;</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>\n\n<span class=\"tok-kn\">Fixpoint</span> <span class=\"tok-n\">filter&#39;</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\">-&gt;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</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>\n    <span class=\"tok-o\">|</span> <span class=\"tok-bp\">true</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">filter&#39;</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>\n    <span class=\"tok-o\">|</span> <span class=\"tok-bp\">false</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">filter&#39;</span> <span class=\"tok-n\">f</span> <span class=\"tok-n\">a</span> <span class=\"tok-n\">l</span> <span class=\"tok-o\">)</span>\n    <span class=\"tok-k\">end</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">l</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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\">-&gt;</span> <span class=\"tok-n\">b</span> <span class=\"tok-o\">-&gt;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</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>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">init</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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\">-&gt;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</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>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">nil</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">l</span> <span class=\"tok-k\">with</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-n\">nil</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">nil</span>\n  <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\">=&gt;</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>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-o\">(</span><span class=\"tok-n\">reverse&#39;</span> <span class=\"tok-n\">x</span> <span class=\"tok-n\">nil</span> <span class=\"tok-o\">).</span>\n\n<span class=\"tok-kn\">Fixpoint</span> <span class=\"tok-n\">reverse&#39;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">reverse&#39;</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>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">l</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">l</span> <span class=\"tok-k\">with</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-n\">nil</span> <span class=\"tok-o\">=&gt;</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>\n  <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\">=&gt;</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>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Not that this transpiler is experimental.\nSo, Coq cannot interpret some outputs.\nPlease fix it manually when you encounter that situation.\nIt is probably easy.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_examples\">21. Examples</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_reverse\">21.1. Reverse</h3>\n<div class=\"paragraph\">\n<p><em>reverse</em> is a internally defined function. It reverses order of a list.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This outputs as follows.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>'(9 8 7 6 5 4 3 2 1)</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_filter\">21.2. Filter</h3>\n<div class=\"paragraph\">\n<p><em>filter</em> is a internally defined function. It filters the elements in a list.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This outputs as follows.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>'(2 4 6 8)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>filter</em>'s type is as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</span>\n<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\">-&gt;</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>\n<span class=\"tok-w\">     </span><span class=\"tok-o\">&#39;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-o\">&#39;</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>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_factorial\">21.3. Factorial</h3>\n<div class=\"paragraph\">\n<p>Tail call factorial can be coded as follows.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</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>\n<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>\n\n<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\">-&gt;</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>\n<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\">&lt;=</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>\n<span class=\"tok-w\">        </span><span class=\"tok-nv\">total</span>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function can be called as follows.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&gt;&gt; (factorial 10)\n3628800\n&gt;&gt;\n&gt;&gt; (factorial 1000)\n402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n&gt;&gt;\n&gt;&gt; (factorial 100)\n93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n&gt;&gt;\n&gt;&gt; (factorial 500)\n1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nVersion 0.4.0<br>\nLast updated 2026-04-28 09:28:41 +0900\n</div>\n</div>\n<script type=\"text/x-mathjax-config\">\nMathJax.Hub.Config({\n  messageStyle: \"none\",\n  tex2jax: {\n    inlineMath: [[\"\\\\(\", \"\\\\)\"]],\n    displayMath: [[\"\\\\[\", \"\\\\]\"]],\n    ignoreClass: \"nostem|nolatexmath\"\n  },\n  asciimath2jax: {\n    delimiters: [[\"\\\\$\", \"\\\\$\"]],\n    ignoreClass: \"nostem|noasciimath\"\n  },\n  TeX: { equationNumbers: { autoNumber: \"none\" } }\n})\nMathJax.Hub.Register.StartupHook(\"AsciiMath Jax Ready\", function () {\n  MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {\n    if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains(\"stemblock\")) {\n      data.math.root.display = \"block\"\n    }\n    return data\n  })\n})\n</script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML\"></script>\n</body>\n</html>"
  },
  {
    "path": "docs/index.ja.adoc",
    "content": "= BLisp: Lispっぽい静的型付け言語\nYuuki Takano <ytakano@wide.ad.jp>\nv0.4.0, 2023-02\n:doctype: article\n:toc:\n:sectnums:\n:lang: ja\n:encoding: utf-8\n:stem: latexmath\n:source-highlighter: pygments\n\n\nBLispは静的型付けされたLispライクなプログラミング言語で、no_std環境用のエフェクトシステムを採用しています。BLispは関数型プログラミング言語の高階関数のような高階のRPCをサポートしています。\n\n* https://github.com/ytakano/blisp[GitHubリポジトリ]\n* https://crates.io/crates/blisp[BLispのcrates.io]\n\n本リポジトリではライブラリクレートのみを提供しています。BLispを利用するには https://github.com/ytakano/blisp-repl[blisp-repl] か、おもちゃのOSである https://github.com/ytakano/baremetalisp[baremetalisp] を参照してください。\n\nhttps://ytakano.github.io/blisp/[English version is here.]\n\n.no_stdで動くBLisp\nimage:https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytakano/20210221/20210221155657.gif[no_stdで動くBLisp]\n\n== 特徴\n\n* 代数的データ型\n* ジェネリクス\n* 型推論\n* IOと純粋な関数を分離するためのエフェクトシステム\n* 多倍長整数\n* no_std環境のサポート\n\n== 値\n\n.values\n[source, lisp]\n----\n`A`       ; 文字リテラル\n\"Hello\"   ; 文字列リテラル\n144       ; 整数値\n0xabcDEF  ; 16進数\n0o777     ; 8進数\n0b1001    ; 2進数\ntrue      ; 真偽値\nfalse     ; 真偽値\n[true 10] ; タプル\n[]        ; 空のタプル\n'(1 2 3)  ; リスト\n'()       ; 空のリスト、Nil\n----\n\n== 基本型\n\n.types\n[source, lisp]\n----\nChar       ; 文字型\nString     ; 文字列型\nInt        ; 整数型\nBool       ; 真偽値型\n'(Int)     ; Int型のリスト型\n[Int Bool] ; Int型とBool型のタプル型\n(Pure (-> (Int Int) Bool)) ; Int型の値を2つとり、Bool型の値をリターンする純粋な関数\n(IO (-> (Int) [])) ; Int型の値をとり[]をリターンするIOのある関数\n----\n\nPureとIOは関数の効果です。IO関数内では、Pure関数とIO関数の両方を呼び出すことができます。しかし、Pure関数内では、Pure関数の呼び出しのみ許可されています。\n\n== 関数定義\n\n関数はdefunやexportで定義することができます。\"defun\"はRustのeval関数からは呼び出せないローカル関数を定義します。\n\n以下の2つの関数があるとしましょう。\n\n.defun\n[source, lisp]\n----\n(defun double (x)         ; 関数名がdoubleでxは引数\n    (Pure (-> (Int) Int)) ; 関数の型\n    (* 2 x))              ; 関数の中身\n----\n\n.export\n[source, lisp]\n----\n(export quad (x)          ; 関数名がquadで引数はx\n    (Pure (-> (Int) Int)) ; 関数の型\n    (double (double x)))  ; 関数の中身\n----\n\ndoubleはRustのevalからは呼び出せませんが、内部で定義された関数からは呼び出せます。quadはRustのevalから呼び出すことができ、内部的にdoubleを呼び出します。\n\nこれはRustで実際に行うコードです。\n\n.Rust's eval\n[source, rust]\n----\nuse blisp;\n\nfn eval(e: &str, ctx: &blisp::semantics::Context) {\n    // evaluate expressions\n    let exprs = match blisp::eval(e, ctx) {\n        Ok(es) => es,\n        Err(err) => {\n            println!(\"error:{}:{}: {}\", err.pos.line, err.pos.column, err.msg);\n            return;\n        }\n    };\n\n    for r in exprs {\n        match r {\n            Ok(msg) => {\n                println!(\"{}\", msg);\n            }\n            Err(msg) => {\n                println!(\"error: {}\", msg);\n            }\n        }\n    }\n}\n\nfn main() {\n    // internal code\n    let code = \"\n(defun double (x)         ; 関数名がdoubleでxは引数\n    (Pure (-> (Int) Int)) ; 関数の型\n    (* 2 x))              ; 関数の中身\n\n(export quad (x)          ; 関数名がquadで引数はx\n    (Pure (-> (Int) Int)) ; 関数の型\n    (double (double x)))  ; 関数の中身\n\";\n    let exprs = blisp::init(code, vec![]).unwrap();\n    let ctx = blisp::typing(exprs).unwrap();\n\n    let e = \"(double 10) ; エラー\";\n    eval(e, &ctx);\n\n    let e = \"(quad 10) ; OK\";\n    eval(e, &ctx);\n}\n----\n\nこのコードは以下のように出力します。\n\n error:0:1: Typing Error: double is not defined\n 40\n\n== 算術演算\n\n.基本\n[source, lisp]\n----\n; (Pure (-> (Int Int) Int))\n(+ 10 20)\n(- 30 40)\n(* 6 100)\n(/ 100 2)\n(% 10 3)\n----\n\n== 真偽値演算\n\n.logical\n[source, lisp]\n----\n; (Pure (-> (Bool Bool) Bool))\n(and true false)\n(or true false)\n(xor true false)\n----\n\n.negation\n[source, lisp]\n----\n; (Pure (-> (Bool) Bool))\n(not true)\n----\n\n== 比較演算\n\n=, !=, <, >, \\<=, >= といった関数は、同じ型の2つの値に対して適用できます。\n\n.comparison between 2 values whose types are same\n[source, lisp]\n----\n; (Pure (-> (t t) Bool))\n(= 4 4)               ; true\n(!= 4 4)              ; false\n(= \"Hello\" \"Hello\")   ; true\n(= (Some 1) (Some 2)) ; false\n(< 6 7)\n(> 6 7)\n(<= 30 40)\n(>= 30 40)\n(< \"Hello\" \"World\")\n(<= (Some 1) (Some 2))\n----\n\n_eq_, _neq_, _lt_, _gt_, _leq_, _geq_ といった関数は、異なる型同士の値でも比較可能です。\n\n.comparison between any 2 values\n[source, lisp]\n----\n; (Pure (-> (t1 t1) Bool))\n(geq (Some 1) \"Hello\") ; (Some 1)は\"Hello\"より大きい、もしくは等しいか？\n(eq \"Hello\" 100)       ; \"Hello\"と100は等しいか？\n(neq \"Hello\" 100)      ; \"Hello\"と100は等しくないか？\n(lt 100 (Some 20))     ; 100は(Some 20)より小さいか？\n(gt 200 \"Hello\")       ; 200は\"Hello\"より大きいか？\n----\n\n== ビット演算\n\n[source, lisp]\n----\n(band 1 0) ; ビット積\n(band 1 1) ; ビット積\n(bor 1 0)  ; ビット和\n(bor 1 1)  ; ビット和\n(bxor 1 0) ; ビット排他的論理和\n----\n\n.ビットシフト\n[source, lisp]\n----\n; (Pure (-> (Int Int) (Option Int)))\n(<< 8 4)   ; (Some 128)\n(>> 128 4) ; (Some 8)\n(>> -128 4) ; (Some -8)\n----\n\n2番目の引数が2^64^以上の場合はNoneをリターンします。\n\n== 数学的演算\n\n[source, lisp]\n----\n; (Pure (-> (Int Int) (Option Int)))\n(pow 10 20) ; (Some 100000000000000000000) namely 10^20\n\n; (Pure (-> (Int) (Option Int)))\n(sqrt 16)   ; (Some 4)\n----\n\npowの指数部が2^32^以上の場合は、powはNoneをリターンします。\n\nsqrtの引数が0以下の場合は、sqrtはNoneをリターンします。\n\n== 代数的データ型\n\n代数的データ型は以下のように定義できます。\n\n[source, lisp]\n----\n; in BLisp\n(data Cardinal ; 型名\n    East       ; 値\n    North      ; 値\n    West       ; 値\n    South)     ; 値\n----\n\n型名とその値の最初の文字は大文字でなければなりません。これはRustの以下のコードと同等です。\n\n[source, rust]\n----\n// in Rust\nenum Cardinal {\n    East,\n    North,\n    West,\n    South\n}\n----\n\n各要素は以下のような値を持つことができます。\n\n[source, lisp]\n----\n; in BLisp\n(data Dim2\n    (Dim2 Int Int)) ; Dim2は2つのInt型の値を持つ\n----\n\nDim2は以下のようにインスタンス化することができます。\n\n[source, lisp]\n----\n(Dim2 10 20)\n----\n\nこの型はRustの以下の型と同等です。\n\n[source, rust]\n----\n// in Rust\nuse num_bigint::BigInt;\nenum Dim2 {\n    Dim2(BigInt, BigInt)\n}\n----\n\n== ジェネリクス\n\nOption型とResult型は内部で定義されています。\n\n[source, lisp]\n----\n(data (Option t)\n    (Some t)\n    None)\n\n(data (Result t e)\n    (Ok t)\n    (Err e))\n----\n\n\n_t_ と _e_ は型変数です。このコードは、Rustの以下のコードと同等です。\n\n[source, rust]\n----\n// in Rust\nenum Option<T> {\n    Some(T),\n    None,\n}\n\nenum Result<T, E> {\n    Ok(T),\n    Err(E),\n}\n----\n\nリスト型は以下のような組み込み型です。\n\n[source, lisp]\n----\n(data (List t)\n    (Cons t (List t))\n    Nil)\n----\n\nしたがって、以下の2つのリストは等価です。\n\n[source, lisp]\n----\n(Cons 1 (Cons 2 (Cons 3 Nil)))\n'(1 2 3)\n----\n\n== ジェネリック関数\n\n_car_ と _cdr_ は内部的に定義されたジェネリック関数です。これらの定義は以下の通りです。\n\n[source, lisp]\n----\n(export car (x) (Pure (-> ('(t)) (Option t)))\n    (match x\n        ((Cons n _) (Some n))\n        (_ None)))\n\n(export cdr (x) (Pure (-> ('(t)) '(t)))\n    (match x\n        ((Cons _ l) l)\n        (_ '())))\n----\n\nt_は型変数です。これらの関数は以下のように使うことができます。\n\n[source, lisp]\n----\n(car '(3 8 9))  ; returns (Some 3)\n(cdr '(8 10 4)) ; returns '(10 4)\n----\n\n通常変数と型変数の最初の文字は小文字でなければなりません。\n\n== If式\n\n単純です.\n\n[source, lisp]\n----\n(if (< 10 20)\n    '(1 2 3)\n    '())\n----\n\n== Match式\n\nリストは以下のようにマッチさせることができます。\n\n[source, lisp]\n----\n(match '(1 2 3)\n    ((Cons n _) n)\n    ('() 0))\n----\n\nこの、\n\n (Cons n _)\n\nという式はパターンです。\nパターンが '(1 2 3) にマッチした場合、1は可変変数 _n_ に代入されます。そうすると、_n_ つまり1が返されます。\n\nタプルのパターンマッチングの例です。\n\n[source, lisp]\n----\n(match [1 3]\n    ([x y] [y x]))\n----\n\nこのコードはタプルの第1要素と第2要素を入れ替えます。\n\n整数値はパターンマッチングにも使用できます。\n\n[source, lisp]\n----\n(match 20\n    (20 true)\n    (_ false))\n----\n\nより複雑な例としては、以下のようなものがあります。\n\n[source, lisp]\n----\n(match [(Some 10) true]\n    ([(Some 10) false] 1)\n    ([(Some 10) true] 2)\n    (_ 0))\n----\n\nBLispはパターンを網羅的にチェックします。そのため、以下のコードは拒否されます。\n\n[source, lisp]\n----\n(match '(1 2)\n    ('() 0))\n----\n\n== Let式\n\n変数のバインドには、以下のようにLet式を使用します。\n\n[source, lisp]\n----\n(let ((x 10) (y 20)) ; x is 10, y is 20\n    (* x y))\n\n(let ((x 10) (x (* x x)) (x (* x x))) ; x = 10, x = x * x, x = x * x\n    x)\n----\n\nまた、以下のように分配束縛を行うこともできます。\n\n[source, lisp]\n----\n(let (((Some x) (Some 10))) ; x is 10\n    (* x 2))\n\n(let (([x y] [10 20])) ; x is 10, y is 20\n    (* x y))\n----\n\n== ラムダ式\n\nラムダ式は以下のように定義されます。\n\n[source, lisp]\n----\n(lambda (x y) (* x y))\n----\n\nこのラムダは2つの整数を受け取り、それらの乗算を返します。これに引数を適用するのは次のように簡単に行えます。\n\n[source, lisp]\n----\n((lambda (x y) (* x y)) 10 20)\n----\n\nすべてのラムダ式は純粋です。よって、ラムダ式からIO関数を呼び出すことはできません。\n\n_map_ と _fold_ 関数は内部的に以下のように定義されています。\n\n[source, lisp]\n----\n(export map (f x) (Pure (-> ((Pure (-> (a) b)) '(a)) '(b)))\n    (match x\n        ((Cons h l) (Cons (f h) (map f l)))\n        (_ '())))\n\n(export fold (f init x) (Pure (-> ((Pure (-> (a b) b)) b '(a)) b))\n    (match x\n        ((Cons h l) (fold f (f h init) l))\n        (_ init)))\n----\n\n_map_ を使うと、以下のようにリストの要素に関数を適用することができます。\n\n[source, lisp]\n----\n; それぞれをの要素を2乗\n(let ((l '(1 2 3))\n      (f (lambda (x) (* x x))))\n        (map f l))\n----\n\n_fold_ を使用して、リストの要素にまたがって計算することができます。例えば、合計は以下のように計算できます。\n\n[source, lisp]\n----\n; 合計\n(let ((l '(20 50 60))\n      (f (lambda (x y) (+ x y))))\n        (fold f 0 l)) ; 0 is an initial value\n----\n\n当然、これは以下のようにも記述できます。\n\n[source, lisp]\n----\n; summation\n(fold + 0 '(20 50 60))\n----\n\n== マクロ\n\nマクロは `macro` で定義できます。\n各ルールはパターンとテンプレートの組からなり、最初に一致したルールが展開されます。\n\n[source, lisp]\n----\n(macro add\n    ((add $e1 $e2) (+ $e1 $e2))\n    ((add $e1 $e2 $e3 ...) (+ $e1 (add $e2 $e3 ...))))\n----\n\n`$` で始まる識別子はパターン変数です。\nパターン変数には、マクロ呼び出し側で一致した式がそのまま代入されます。\n`...` は、パターン変数やテンプレート断片の後ろに置くことで、残りの引数を可変長部分としてまとめて扱えます。\n\n[source, lisp]\n----\n(add 1 2)         ; 3\n(add 1 2 3 4 5)   ; 15\n----\n\nマクロは局所変数を導入する式も生成できます。\nたとえば、一時変数を含むラムダ式は以下のように書けます。\n\n[source, lisp]\n----\n(macro with_tmp\n    ((_ $x) ((lambda (tmp) (+ tmp $x)) 1)))\n\n(export test (tmp) (Pure (-> (Int) Int))\n    (with_tmp tmp))\n----\n\nBLispのマクロは、テンプレートが導入する局所 binder に対して衛生的です。\n`lambda` の引数、`let` の束縛、`match` のパターン変数は展開時に fresh な内部名へ自動的にリネームされるため、呼び出し側の同名変数を変数捕捉しません。\n一方で、`defun`、`export`、`data` のようなトップレベル名は自動では改名されません。\n\n== 文字列と文字\n\n_chars_ はStringから(List Char)へ変換します。\n\n[source, lisp]\n----\n; (Pure (-> (String) (List Char)))\n(chars \"Hello\") ; '(`H` `e` `l` `l` `o`)\n----\n\n_str_ は(List Char)からStringへ変換します。\n\n[source, lisp]\n----\n; (Pure (-> ((List Char)) String))\n(str '(`H` `e` `l` `l` `o`)) ; \"Hello\"\n----\n\n== 外部関数呼び出し\n\n_blisp::embedded_ は、外部関数呼び出し用のマクロです。\nこのマクロを利用すると、Rustの関数をBLispから容易に呼び出せるようになります。\n\nたとえば、はじめに、Rustの関数を以下のように定義します。\n\n[source, rust]\n----\nuse blisp::embedded;\nuse num_bigint::{BigInt, ToBigInt};\n\n#[embedded]\nfn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> Result<BigInt, String> {\n    let mut result = a + b.0 + b.1;\n    if let Some(n) = c {\n        result += n;\n    }\n\n    Ok(result)\n}\n----\n\n_blisp::embedded_ マクロは外部関数呼び出し用の型定義を生成します。\nこの関数は、以下のようにBLispから呼び出せます。\n\n[source, lisp]\n----\n(export call_add_four_ints (n)\n    (IO (-> ((Option Int)) (Result Int String)))\n    (add_four_ints 1 [2 3] n))\n----\n\n外部関数を登録するためには、以下のように、 _embedded_ によって生成される型定義のベクタを\n_blisp::init_ に渡します。\n\n[source, rust]\n----\n// add_for_ints\nlet code = \"(export call_add_four_ints (n)\n    (IO (-> ((Option Int)) (Result Int String)))\n    (add_four_ints 1 [2 3] n)\n)\";\nlet exprs = blisp::init(code, vec![Box::new(AddFourInts)]).unwrap();\nlet ctx = blisp::typing(exprs).unwrap();\nlet result = blisp::eval(\"(call_add_four_ints (Some 4))\", &ctx).unwrap();\n----\n\nここでは、関数名が _add_four_ints_ のため、そのキャメルケースの _AddFourInts_\nを _Box_ と _Vec_ に包んで _blisp::init_ に渡さなければなりません。\n\nRustの外部関数は以下に示される型のみ引数と返り値で利用可能です。\n_Vec<u64>_ のような他の型はサポート外ですが、\n_Vec<Option<bool>>_ のような型はOKです。\nBLispとRustの間の型変換は _embedded_ マクロが生成する関数によって自動的に行われます。\n\n.Type Conversion between BLisp and Rust\n|===\n|BLisp          | Rust\n\n|_Int_          | _BigInt_\n|_Bool_         | _bool_\n|_Char_         | _char_\n|_String_       | _String_\n|_'(T)_         | _Vec<T>_\n|_[T0, T1]_     | _(T0, T1)_\n|_(Option T)_   | _Option<T>_\n|_(Result T E)_ | _Result<T, E>_\n|===\n\n== Coqへのトランスパイラ (実験的)\n\nBLispは実験的にCoqへのトランスパイラを実装しています。\nトランスパイラは、以下のように _blisp::transpile_ を呼び出すことで実行されます。\n\n[source, coq]\n----\nlet expr = \"\n(defun snoc (l y)\n(Pure (-> (\n    '(t) t)\n'(t)))\n(match l\n    (nil (Cons y nil))\n    ((Cons h b) (Cons h (snoc b y)))))\n\n(defun rev (l)\n(Pure (-> (\n    '(t))\n'(t)))\n(match l\n    (nil nil)\n    ((Cons h t) (snoc (rev t) h))))\n    \";\nlet exprs = blisp::init(expr, vec![]).unwrap();\nlet ctx = blisp::typing(exprs).unwrap();\n\nprintln!(\"{}\", blisp::transpile(&ctx));\n----\n\nこれは以下のようなCoqのコードを出力します。\nこの出力には、BLispのプレリュードも含まれます。\n\n[source, coq]\n----\nRequire Import ZArith.\nRequire Import Coq.Lists.List.\n\nInductive Option (t: Type): Type :=\n| Some (x0: t)\n| None.\n\nArguments Some{t}.\nArguments None{t}.\n\nInductive Result (t e: Type): Type :=\n| Ok (x0: t)\n| Err (x0: e).\n\nArguments Ok{t e}.\nArguments Err{t e}.\n\nDefinition car {t: Type} (x: list t): Option t :=\nmatch x with\n  | (cons n _) => (Some n)\n  | _ => (None)\n  end.\n\nDefinition cdr {t: Type} (x: list t): list t :=\nmatch x with\n  | (cons _ l) => l\n  | _ => nil\n  end.\n\nDefinition filter {t: Type} (f: t -> bool) (x: list t): list t :=\n(reverse (filter' f x nil ) ).\n\nFixpoint filter' {t: Type} (f: t -> bool) (x l: list t): list t :=\nmatch x with\n  | (cons h a) => match (f h ) with\n    | true => (filter' f a (cons h l) )\n    | false => (filter' f a l )\n    end\n  | _ => l\n  end.\n\nFixpoint fold {a b: Type} (f: a -> b -> b) (init: b) (x: list a): b :=\nmatch x with\n  | (cons h l) => (fold f (f h init ) l )\n  | _ => init\n  end.\n\nFixpoint map {a b: Type} (f: a -> b) (x: list a): list b :=\nmatch x with\n  | (cons h l) => (cons (f h ) (map f l ))\n  | _ => nil\n  end.\n\nFixpoint rev {t: Type} (l: list t): list t :=\nmatch l with\n  | nil => nil\n  | (cons h t) => (snoc (rev t ) h )\n  end.\n\nDefinition reverse {t: Type} (x: list t): list t :=\n(reverse' x nil ).\n\nFixpoint reverse' {t: Type} (x l: list t): list t :=\nmatch x with\n  | (cons h a) => (reverse' a (cons h l) )\n  | _ => l\n  end.\n\nFixpoint snoc {t: Type} (l: list t) (y: t): list t :=\nmatch l with\n  | nil => (cons y nil)\n  | (cons h b) => (cons h (snoc b y ))\n  end.\n----\n\nこのトランスパイラは実験的なものであることに注意してください。\nよって、いくつかの出力はCoqが解釈できません。\nその場合は、手動でソースコードを修正してください。\n簡単にできるはずです。\n\n== 例\n\n=== リバース\n\n_reverse_ は内部で定義されている関数です。この関数はリストを反転します。\n\n[source, lisp]\n----\n(reverse '(1 2 3 4 5 6 7 8 9))\n----\n\nこのコードの出力は以下の通りです。\n\n '(9 8 7 6 5 4 3 2 1)\n\n=== Filter\n\n_filter_ は内部で定義されている関数です。この関数はリストの中身をフィルターします。\n\n[source, lisp]\n----\n(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9))\n----\n\nこのコードの出力は以下の通りです。\n\n '(2 4 6 8)\n\n_filter_' の型は以下の通りです。\n\n[source, lisp]\n----\n(Pure (->\n    ((Pure (-> (t) Bool)) ; 関数を引数にとる\n     '(t))                ; リストを引数にとる\n    '(t))) ; リストをリターン\n----\n\n=== 階乗\n\n末尾呼び出し版の階乗関数は、以下のように実装できます。\n\n[source, lisp]\n----\n(export factorial (n) (Pure (-> (Int) Int))\n    (fact n 1))\n\n(defun fact (n total) (Pure (-> (Int Int) Int))\n    (if (<= n 0)\n        total\n        (fact (- n 1) (* n total))))\n----\n\nこの関数は以下のように呼び出すことができます。\n\n >> (factorial 10)\n 3628800\n >>\n >> (factorial 1000)\n 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n >>\n >> (factorial 100)\n 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n >>\n >> (factorial 500)\n 1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
  },
  {
    "path": "docs/index.ja.html",
    "content": "<!DOCTYPE html>\n<html lang=\"ja\">\n<head>\n<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.20\">\n<meta name=\"author\" content=\"Yuuki Takano\">\n<title>BLisp: Lispっぽい静的型付け言語</title>\n<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\">\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @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\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{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}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.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}\ndiv,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}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,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}\nh1 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}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable 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}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n: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}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre>code{display:block}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{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}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#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}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#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}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\n#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}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#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}\n#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}\n#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}\n#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}\n#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}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>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%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.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}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.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)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.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}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.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}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.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}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.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}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.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}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.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)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.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}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.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}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.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}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.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}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.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}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n<style>\npre.pygments .hll { background-color: #ffffcc }\npre.pygments { background: #f8f8f8; }\npre.pygments .tok-c { color: #3D7B7B; font-style: italic } /* Comment */\npre.pygments .tok-err { border: 1px solid #FF0000 } /* Error */\npre.pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */\npre.pygments .tok-o { color: #666666 } /* Operator */\npre.pygments .tok-ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */\npre.pygments .tok-cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */\npre.pygments .tok-cp { color: #9C6500 } /* Comment.Preproc */\npre.pygments .tok-cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */\npre.pygments .tok-c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */\npre.pygments .tok-cs { color: #3D7B7B; font-style: italic } /* Comment.Special */\npre.pygments .tok-gd { color: #A00000 } /* Generic.Deleted */\npre.pygments .tok-ge { font-style: italic } /* Generic.Emph */\npre.pygments .tok-ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */\npre.pygments .tok-gr { color: #E40000 } /* Generic.Error */\npre.pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */\npre.pygments .tok-gi { color: #008400 } /* Generic.Inserted */\npre.pygments .tok-go { color: #717171 } /* Generic.Output */\npre.pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */\npre.pygments .tok-gs { font-weight: bold } /* Generic.Strong */\npre.pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */\npre.pygments .tok-gt { color: #0044DD } /* Generic.Traceback */\npre.pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */\npre.pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */\npre.pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */\npre.pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */\npre.pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */\npre.pygments .tok-kt { color: #B00040 } /* Keyword.Type */\npre.pygments .tok-m { color: #666666 } /* Literal.Number */\npre.pygments .tok-s { color: #BA2121 } /* Literal.String */\npre.pygments .tok-na { color: #687822 } /* Name.Attribute */\npre.pygments .tok-nb { color: #008000 } /* Name.Builtin */\npre.pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */\npre.pygments .tok-no { color: #880000 } /* Name.Constant */\npre.pygments .tok-nd { color: #AA22FF } /* Name.Decorator */\npre.pygments .tok-ni { color: #717171; font-weight: bold } /* Name.Entity */\npre.pygments .tok-ne { color: #CB3F38; font-weight: bold } /* Name.Exception */\npre.pygments .tok-nf { color: #0000FF } /* Name.Function */\npre.pygments .tok-nl { color: #767600 } /* Name.Label */\npre.pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */\npre.pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */\npre.pygments .tok-nv { color: #19177C } /* Name.Variable */\npre.pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */\npre.pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */\npre.pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */\npre.pygments .tok-mf { color: #666666 } /* Literal.Number.Float */\npre.pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */\npre.pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */\npre.pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */\npre.pygments .tok-sa { color: #BA2121 } /* Literal.String.Affix */\npre.pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */\npre.pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */\npre.pygments .tok-dl { color: #BA2121 } /* Literal.String.Delimiter */\npre.pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */\npre.pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */\npre.pygments .tok-se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */\npre.pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */\npre.pygments .tok-si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */\npre.pygments .tok-sx { color: #008000 } /* Literal.String.Other */\npre.pygments .tok-sr { color: #A45A77 } /* Literal.String.Regex */\npre.pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */\npre.pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */\npre.pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */\npre.pygments .tok-fm { color: #0000FF } /* Name.Function.Magic */\npre.pygments .tok-vc { color: #19177C } /* Name.Variable.Class */\npre.pygments .tok-vg { color: #19177C } /* Name.Variable.Global */\npre.pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */\npre.pygments .tok-vm { color: #19177C } /* Name.Variable.Magic */\npre.pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */\n</style>\n</head>\n<body class=\"article\">\n<div id=\"header\">\n<h1>BLisp: Lispっぽい静的型付け言語</h1>\n<div class=\"details\">\n<span id=\"author\" class=\"author\">Yuuki Takano</span><br>\n<span id=\"email\" class=\"email\"><a href=\"mailto:ytakano@wide.ad.jp\">ytakano@wide.ad.jp</a></span><br>\n<span id=\"revnumber\">version 0.4.0,</span>\n<span id=\"revdate\">2023-02</span>\n</div>\n<div id=\"toc\" class=\"toc\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_特徴\">1. 特徴</a></li>\n<li><a href=\"#_値\">2. 値</a></li>\n<li><a href=\"#_基本型\">3. 基本型</a></li>\n<li><a href=\"#_関数定義\">4. 関数定義</a></li>\n<li><a href=\"#_算術演算\">5. 算術演算</a></li>\n<li><a href=\"#_真偽値演算\">6. 真偽値演算</a></li>\n<li><a href=\"#_比較演算\">7. 比較演算</a></li>\n<li><a href=\"#_ビット演算\">8. ビット演算</a></li>\n<li><a href=\"#_数学的演算\">9. 数学的演算</a></li>\n<li><a href=\"#_代数的データ型\">10. 代数的データ型</a></li>\n<li><a href=\"#_ジェネリクス\">11. ジェネリクス</a></li>\n<li><a href=\"#_ジェネリック関数\">12. ジェネリック関数</a></li>\n<li><a href=\"#_if式\">13. If式</a></li>\n<li><a href=\"#_match式\">14. Match式</a></li>\n<li><a href=\"#_let式\">15. Let式</a></li>\n<li><a href=\"#_ラムダ式\">16. ラムダ式</a></li>\n<li><a href=\"#_マクロ\">17. マクロ</a></li>\n<li><a href=\"#_文字列と文字\">18. 文字列と文字</a></li>\n<li><a href=\"#_外部関数呼び出し\">19. 外部関数呼び出し</a></li>\n<li><a href=\"#_coqへのトランスパイラ_実験的\">20. Coqへのトランスパイラ (実験的)</a></li>\n<li><a href=\"#_例\">21. 例</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_リバース\">21.1. リバース</a></li>\n<li><a href=\"#_filter\">21.2. Filter</a></li>\n<li><a href=\"#_階乗\">21.3. 階乗</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>BLispは静的型付けされたLispライクなプログラミング言語で、no_std環境用のエフェクトシステムを採用しています。BLispは関数型プログラミング言語の高階関数のような高階のRPCをサポートしています。</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><a href=\"https://github.com/ytakano/blisp\">GitHubリポジトリ</a></p>\n</li>\n<li>\n<p><a href=\"https://crates.io/crates/blisp\">BLispのcrates.io</a></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>本リポジトリではライブラリクレートのみを提供しています。BLispを利用するには <a href=\"https://github.com/ytakano/blisp-repl\">blisp-repl</a> か、おもちゃのOSである <a href=\"https://github.com/ytakano/baremetalisp\">baremetalisp</a> を参照してください。</p>\n</div>\n<div class=\"paragraph\">\n<p><a href=\"https://ytakano.github.io/blisp/\">English version is here.</a></p>\n</div>\n<div class=\"paragraph\">\n<div class=\"title\">no_stdで動くBLisp</div>\n<p><span class=\"image\"><img src=\"https://cdn-ak.f.st-hatena.com/images/fotolife/y/ytakano/20210221/20210221155657.gif\" alt=\"no_stdで動くBLisp\"></span></p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_特徴\">1. 特徴</h2>\n<div class=\"sectionbody\">\n<div class=\"ulist\">\n<ul>\n<li>\n<p>代数的データ型</p>\n</li>\n<li>\n<p>ジェネリクス</p>\n</li>\n<li>\n<p>型推論</p>\n</li>\n<li>\n<p>IOと純粋な関数を分離するためのエフェクトシステム</p>\n</li>\n<li>\n<p>多倍長整数</p>\n</li>\n<li>\n<p>no_std環境のサポート</p>\n</li>\n</ul>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_値\">2. 値</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">values</div>\n<div class=\"content\">\n<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\">; 文字リテラル</span>\n<span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-w\">   </span><span class=\"tok-c1\">; 文字列リテラル</span>\n<span class=\"tok-mi\">144</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; 整数値</span>\n<span class=\"tok-nv\">0xabcDEF</span><span class=\"tok-w\">  </span><span class=\"tok-c1\">; 16進数</span>\n<span class=\"tok-nv\">0o777</span><span class=\"tok-w\">     </span><span class=\"tok-c1\">; 8進数</span>\n<span class=\"tok-nv\">0b1001</span><span class=\"tok-w\">    </span><span class=\"tok-c1\">; 2進数</span>\n<span class=\"tok-nv\">true</span><span class=\"tok-w\">      </span><span class=\"tok-c1\">; 真偽値</span>\n<span class=\"tok-nv\">false</span><span class=\"tok-w\">     </span><span class=\"tok-c1\">; 真偽値</span>\n<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\">; タプル</span>\n<span class=\"tok-nv\">[]</span><span class=\"tok-w\">        </span><span class=\"tok-c1\">; 空のタプル</span>\n<span class=\"tok-o\">&#39;</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\">; リスト</span>\n<span class=\"tok-o\">&#39;</span><span class=\"tok-p\">()</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; 空のリスト、Nil</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_基本型\">3. 基本型</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">types</div>\n<div class=\"content\">\n<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\">; 文字型</span>\n<span class=\"tok-nv\">String</span><span class=\"tok-w\">     </span><span class=\"tok-c1\">; 文字列型</span>\n<span class=\"tok-nv\">Int</span><span class=\"tok-w\">        </span><span class=\"tok-c1\">; 整数型</span>\n<span class=\"tok-nv\">Bool</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; 真偽値型</span>\n<span class=\"tok-o\">&#39;</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\">; Int型のリスト型</span>\n<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\">; Int型とBool型のタプル型</span>\n<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\">-&gt;</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\">; Int型の値を2つとり、Bool型の値をリターンする純粋な関数</span>\n<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\">-&gt;</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\">; Int型の値をとり[]をリターンするIOのある関数</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>PureとIOは関数の効果です。IO関数内では、Pure関数とIO関数の両方を呼び出すことができます。しかし、Pure関数内では、Pure関数の呼び出しのみ許可されています。</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_関数定義\">4. 関数定義</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>関数はdefunやexportで定義することができます。\"defun\"はRustのeval関数からは呼び出せないローカル関数を定義します。</p>\n</div>\n<div class=\"paragraph\">\n<p>以下の2つの関数があるとしましょう。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">defun</div>\n<div class=\"content\">\n<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\">; 関数名がdoubleでxは引数</span>\n<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\">-&gt;</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\">; 関数の型</span>\n<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\">; 関数の中身</span></code></pre>\n</div>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">export</div>\n<div class=\"content\">\n<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\">; 関数名がquadで引数はx</span>\n<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\">-&gt;</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\">; 関数の型</span>\n<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\">; 関数の中身</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>doubleはRustのevalからは呼び出せませんが、内部で定義された関数からは呼び出せます。quadはRustのevalから呼び出すことができ、内部的にdoubleを呼び出します。</p>\n</div>\n<div class=\"paragraph\">\n<p>これはRustで実際に行うコードです。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">Rust&#8217;s eval</div>\n<div class=\"content\">\n<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>\n\n<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\">&amp;</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\">&amp;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-c1\">// evaluate expressions</span>\n<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>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-n\">es</span><span class=\"tok-p\">,</span>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">            </span><span class=\"tok-fm\">println!</span><span class=\"tok-p\">(</span><span class=\"tok-s\">&quot;error:{}:{}: {}&quot;</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>\n<span class=\"tok-w\">            </span><span class=\"tok-k\">return</span><span class=\"tok-p\">;</span>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">}</span>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">};</span>\n\n<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>\n<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>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">                </span><span class=\"tok-fm\">println!</span><span class=\"tok-p\">(</span><span class=\"tok-s\">&quot;{}&quot;</span><span class=\"tok-p\">,</span><span class=\"tok-w\"> </span><span class=\"tok-n\">msg</span><span class=\"tok-p\">);</span>\n<span class=\"tok-w\">            </span><span class=\"tok-p\">}</span>\n<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\">=&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">                </span><span class=\"tok-fm\">println!</span><span class=\"tok-p\">(</span><span class=\"tok-s\">&quot;error: {}&quot;</span><span class=\"tok-p\">,</span><span class=\"tok-w\"> </span><span class=\"tok-n\">msg</span><span class=\"tok-p\">);</span>\n<span class=\"tok-w\">            </span><span class=\"tok-p\">}</span>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">}</span>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">}</span>\n<span class=\"tok-p\">}</span>\n\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-c1\">// internal code</span>\n<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\">&quot;</span>\n<span class=\"tok-s\">(defun double (x)         ; 関数名がdoubleでxは引数</span>\n<span class=\"tok-s\">    (Pure (-&gt; (Int) Int)) ; 関数の型</span>\n<span class=\"tok-s\">    (* 2 x))              ; 関数の中身</span>\n\n<span class=\"tok-s\">(export quad (x)          ; 関数名がquadで引数はx</span>\n<span class=\"tok-s\">    (Pure (-&gt; (Int) Int)) ; 関数の型</span>\n<span class=\"tok-s\">    (double (double x)))  ; 関数の中身</span>\n<span class=\"tok-s\">&quot;</span><span class=\"tok-p\">;</span>\n<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>\n<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-n\">exprs</span><span class=\"tok-p\">).</span><span class=\"tok-n\">unwrap</span><span class=\"tok-p\">();</span>\n\n<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\">&quot;(double 10) ; エラー&quot;</span><span class=\"tok-p\">;</span>\n<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\">&amp;</span><span class=\"tok-n\">ctx</span><span class=\"tok-p\">);</span>\n\n<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\">&quot;(quad 10) ; OK&quot;</span><span class=\"tok-p\">;</span>\n<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\">&amp;</span><span class=\"tok-n\">ctx</span><span class=\"tok-p\">);</span>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>このコードは以下のように出力します。</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>error:0:1: Typing Error: double is not defined\n40</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_算術演算\">5. 算術演算</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">基本</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Int Int) Int))</span>\n<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>\n<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>\n<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>\n<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>\n<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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_真偽値演算\">6. 真偽値演算</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"title\">logical</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Bool Bool) Bool))</span>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">negation</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Bool) Bool))</span>\n<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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_比較演算\">7. 比較演算</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>=, !=, &lt;, &gt;, &lt;=, &gt;= といった関数は、同じ型の2つの値に対して適用できます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">comparison between 2 values whose types are same</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (t t) Bool))</span>\n<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>\n<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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">=</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\">   </span><span class=\"tok-c1\">; true</span>\n<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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&gt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;=</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&gt;=</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;World&quot;</span><span class=\"tok-p\">)</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">&lt;=</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>eq</em>, <em>neq</em>, <em>lt</em>, <em>gt</em>, <em>leq</em>, <em>geq</em> といった関数は、異なる型同士の値でも比較可能です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">comparison between any 2 values</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (t1 t1) Bool))</span>\n<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\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\"> </span><span class=\"tok-c1\">; (Some 1)は&quot;Hello&quot;より大きい、もしくは等しいか？</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">eq</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</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\">; &quot;Hello&quot;と100は等しいか？</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">neq</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</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\">; &quot;Hello&quot;と100は等しくないか？</span>\n<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\">; 100は(Some 20)より小さいか？</span>\n<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\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; 200は&quot;Hello&quot;より大きいか？</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_ビット演算\">8. ビット演算</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">; ビット積</span>\n<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\">; ビット積</span>\n<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\">; ビット和</span>\n<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\">; ビット和</span>\n<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\">; ビット排他的論理和</span></code></pre>\n</div>\n</div>\n<div class=\"listingblock\">\n<div class=\"title\">ビットシフト</div>\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Int Int) (Option Int)))</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">&lt;&lt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">&gt;&gt;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">&gt;&gt;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>2番目の引数が2<sup>64</sup>以上の場合はNoneをリターンします。</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_数学的演算\">9. 数学的演算</h2>\n<div class=\"sectionbody\">\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (Int Int) (Option Int)))</span>\n<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) namely 10^20</span>\n\n<span class=\"tok-c1\">; (Pure (-&gt; (Int) (Option Int)))</span>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>powの指数部が2<sup>32</sup>以上の場合は、powはNoneをリターンします。</p>\n</div>\n<div class=\"paragraph\">\n<p>sqrtの引数が0以下の場合は、sqrtはNoneをリターンします。</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_代数的データ型\">10. 代数的データ型</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>代数的データ型は以下のように定義できます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; in BLisp</span>\n<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\">; 型名</span>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">East</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; 値</span>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">North</span><span class=\"tok-w\">      </span><span class=\"tok-c1\">; 値</span>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">West</span><span class=\"tok-w\">       </span><span class=\"tok-c1\">; 値</span>\n<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\">; 値</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>型名とその値の最初の文字は大文字でなければなりません。これはRustの以下のコードと同等です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// in Rust</span>\n<span class=\"tok-k\">enum</span> <span class=\"tok-nc\">Cardinal</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">East</span><span class=\"tok-p\">,</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">North</span><span class=\"tok-p\">,</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">West</span><span class=\"tok-p\">,</span>\n<span class=\"tok-w\">    </span><span class=\"tok-n\">South</span>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>各要素は以下のような値を持つことができます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; in BLisp</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">data</span><span class=\"tok-w\"> </span><span class=\"tok-nv\">Dim2</span>\n<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は2つのInt型の値を持つ</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Dim2は以下のようにインスタンス化することができます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>この型はRustの以下の型と同等です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// in Rust</span>\n<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>\n<span class=\"tok-k\">enum</span> <span class=\"tok-nc\">Dim2</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_ジェネリクス\">11. ジェネリクス</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Option型とResult型は内部で定義されています。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">None</span><span class=\"tok-p\">)</span>\n\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>t</em> と <em>e</em> は型変数です。このコードは、Rustの以下のコードと同等です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// in Rust</span>\n<span class=\"tok-k\">enum</span> <span class=\"tok-nb\">Option</span><span class=\"tok-o\">&lt;</span><span class=\"tok-n\">T</span><span class=\"tok-o\">&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nb\">None</span><span class=\"tok-p\">,</span>\n<span class=\"tok-p\">}</span>\n\n<span class=\"tok-k\">enum</span> <span class=\"tok-nb\">Result</span><span class=\"tok-o\">&lt;</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\">&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<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>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>リスト型は以下のような組み込み型です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-no\">Nil</span><span class=\"tok-p\">)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>したがって、以下の2つのリストは等価です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<span class=\"tok-o\">&#39;</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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_ジェネリック関数\">12. ジェネリック関数</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>car</em> と <em>cdr</em> は内部的に定義されたジェネリック関数です。これらの定義は以下の通りです。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</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>\n<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>\n<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>\n<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>\n\n<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\">-&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</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\">&#39;</span><span class=\"tok-p\">(</span><span class=\"tok-no\">t</span><span class=\"tok-p\">)))</span>\n<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>\n<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>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">(</span><span class=\"tok-nv\">_</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">())))</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>t_は型変数です。これらの関数は以下のように使うことができます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n<span class=\"tok-p\">(</span><span class=\"tok-nb\">cdr</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</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 &#39;(10 4)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>通常変数と型変数の最初の文字は小文字でなければなりません。</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_if式\">13. If式</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>単純です.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&lt;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-o\">&#39;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">())</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_match式\">14. Match式</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>リストは以下のようにマッチさせることができます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">()</span><span class=\"tok-w\"> </span><span class=\"tok-mi\">0</span><span class=\"tok-p\">))</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>この、</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>(Cons n _)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>という式はパターンです。\nパターンが '(1 2 3) にマッチした場合、1は可変変数 <em>n</em> に代入されます。そうすると、<em>n</em> つまり1が返されます。</p>\n</div>\n<div class=\"paragraph\">\n<p>タプルのパターンマッチングの例です。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>このコードはタプルの第1要素と第2要素を入れ替えます。</p>\n</div>\n<div class=\"paragraph\">\n<p>整数値はパターンマッチングにも使用できます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>より複雑な例としては、以下のようなものがあります。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>BLispはパターンを網羅的にチェックします。そのため、以下のコードは拒否されます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">(</span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">()</span><span class=\"tok-w\"> </span><span class=\"tok-mi\">0</span><span class=\"tok-p\">))</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_let式\">15. Let式</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>変数のバインドには、以下のようにLet式を使用します。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-nv\">x</span><span class=\"tok-p\">)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>また、以下のように分配束縛を行うこともできます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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>\n<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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_ラムダ式\">16. ラムダ式</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>ラムダ式は以下のように定義されます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>このラムダは2つの整数を受け取り、それらの乗算を返します。これに引数を適用するのは次のように簡単に行えます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>すべてのラムダ式は純粋です。よって、ラムダ式からIO関数を呼び出すことはできません。</p>\n</div>\n<div class=\"paragraph\">\n<p><em>map</em> と <em>fold</em> 関数は内部的に以下のように定義されています。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</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\">-&gt;</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\">&#39;</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\">&#39;</span><span class=\"tok-p\">(</span><span class=\"tok-nv\">b</span><span class=\"tok-p\">)))</span>\n<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>\n<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>\n<span class=\"tok-w\">        </span><span class=\"tok-p\">(</span><span class=\"tok-nv\">_</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</span><span class=\"tok-p\">())))</span>\n\n<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\">-&gt;</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\">-&gt;</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\">&#39;</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>\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>map</em> を使うと、以下のようにリストの要素に関数を適用することができます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; それぞれをの要素を2乗</span>\n<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\">&#39;</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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>fold</em> を使用して、リストの要素にまたがって計算することができます。例えば、合計は以下のように計算できます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; 合計</span>\n<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\">&#39;</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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>当然、これは以下のようにも記述できます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; summation</span>\n<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\">&#39;</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>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_マクロ\">17. マクロ</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>マクロは <code>macro</code> で定義できます。\n各ルールはパターンとテンプレートの組からなり、最初に一致したルールが展開されます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><code>$</code> で始まる識別子はパターン変数です。\nパターン変数には、マクロ呼び出し側で一致した式がそのまま代入されます。\n<code>&#8230;&#8203;</code> は、パターン変数やテンプレート断片の後ろに置くことで、残りの引数を可変長部分としてまとめて扱えます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>マクロは局所変数を導入する式も生成できます。\nたとえば、一時変数を含むラムダ式は以下のように書けます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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\">-&gt;</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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>BLispのマクロは、テンプレートが導入する局所 binder に対して衛生的です。\n<code>lambda</code> の引数、<code>let</code> の束縛、<code>match</code> のパターン変数は展開時に fresh な内部名へ自動的にリネームされるため、呼び出し側の同名変数を変数捕捉しません。\n一方で、<code>defun</code>、<code>export</code>、<code>data</code> のようなトップレベル名は自動では改名されません。</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_文字列と文字\">18. 文字列と文字</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>chars</em> はStringから(List Char)へ変換します。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; (String) (List Char)))</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">chars</span><span class=\"tok-w\"> </span><span class=\"tok-s\">&quot;Hello&quot;</span><span class=\"tok-p\">)</span><span class=\"tok-w\"> </span><span class=\"tok-c1\">; &#39;(`H` `e` `l` `l` `o`)</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>str</em> は(List Char)からStringへ変換します。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"lisp\"><span></span><span class=\"tok-c1\">; (Pure (-&gt; ((List Char)) String))</span>\n<span class=\"tok-p\">(</span><span class=\"tok-nv\">str</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&#39;</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\">; &quot;Hello&quot;</span></code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_外部関数呼び出し\">19. 外部関数呼び出し</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><em>blisp::embedded</em> は、外部関数呼び出し用のマクロです。\nこのマクロを利用すると、Rustの関数をBLispから容易に呼び出せるようになります。</p>\n</div>\n<div class=\"paragraph\">\n<p>たとえば、はじめに、Rustの関数を以下のように定義します。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<span class=\"tok-cp\">#[embedded]</span>\n<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\">&lt;</span><span class=\"tok-n\">BigInt</span><span class=\"tok-o\">&gt;</span><span class=\"tok-p\">)</span><span class=\"tok-w\"> </span>-&gt; <span class=\"tok-nb\">Result</span><span class=\"tok-o\">&lt;</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\">&gt;</span><span class=\"tok-w\"> </span><span class=\"tok-p\">{</span>\n<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>\n<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>\n<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>\n<span class=\"tok-w\">    </span><span class=\"tok-p\">}</span>\n\n<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>\n<span class=\"tok-p\">}</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>blisp::embedded</em> マクロは外部関数呼び出し用の型定義を生成します。\nこの関数は、以下のようにBLispから呼び出せます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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\">-&gt;</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>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>外部関数を登録するためには、以下のように、 <em>embedded</em> によって生成される型定義のベクタを\n<em>blisp::init</em> に渡します。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"pygments highlight\"><code data-lang=\"rust\"><span></span><span class=\"tok-c1\">// add_for_ints</span>\n<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\">&quot;(export call_add_four_ints (n)</span>\n<span class=\"tok-s\">    (IO (-&gt; ((Option Int)) (Result Int String)))</span>\n<span class=\"tok-s\">    (add_four_ints 1 [2 3] n)</span>\n<span class=\"tok-s\">)&quot;</span><span class=\"tok-p\">;</span>\n<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>\n<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>\n<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\">&quot;(call_add_four_ints (Some 4))&quot;</span><span class=\"tok-p\">,</span><span class=\"tok-w\"> </span><span class=\"tok-o\">&amp;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>ここでは、関数名が <em>add_four_ints</em> のため、そのキャメルケースの <em>AddFourInts</em>\nを <em>Box</em> と <em>Vec</em> に包んで <em>blisp::init</em> に渡さなければなりません。</p>\n</div>\n<div class=\"paragraph\">\n<p>Rustの外部関数は以下に示される型のみ引数と返り値で利用可能です。\n<em>Vec&lt;u64&gt;</em> のような他の型はサポート外ですが、\n<em>Vec&lt;Option&lt;bool&gt;&gt;</em> のような型はOKです。\nBLispとRustの間の型変換は <em>embedded</em> マクロが生成する関数によって自動的に行われます。</p>\n</div>\n<table class=\"tableblock frame-all grid-all stretch\">\n<caption class=\"title\">Table 1. Type Conversion between BLisp and Rust</caption>\n<colgroup>\n<col style=\"width: 50%;\">\n<col style=\"width: 50%;\">\n</colgroup>\n<thead>\n<tr>\n<th class=\"tableblock halign-left valign-top\">BLisp</th>\n<th class=\"tableblock halign-left valign-top\">Rust</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Int</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>BigInt</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Bool</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>bool</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Char</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>char</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>String</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>String</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>'(T)</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Vec&lt;T&gt;</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>[T0, T1]</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>(T0, T1)</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>(Option T)</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Option&lt;T&gt;</em></p></td>\n</tr>\n<tr>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>(Result T E)</em></p></td>\n<td class=\"tableblock halign-left valign-top\"><p class=\"tableblock\"><em>Result&lt;T, E&gt;</em></p></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_coqへのトランスパイラ_実験的\">20. Coqへのトランスパイラ (実験的)</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>BLispは実験的にCoqへのトランスパイラを実装しています。\nトランスパイラは、以下のように <em>blisp::transpile</em> を呼び出すことで実行されます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&quot;</span>\n<span class=\"tok-s2\">(defun snoc (l y)</span>\n<span class=\"tok-s2\">(Pure (-&gt; (</span>\n<span class=\"tok-s2\">    &#39;(t) t)</span>\n<span class=\"tok-s2\">&#39;(t)))</span>\n<span class=\"tok-s2\">(match l</span>\n<span class=\"tok-s2\">    (nil (Cons y nil))</span>\n<span class=\"tok-s2\">    ((Cons h b) (Cons h (snoc b y)))))</span>\n\n<span class=\"tok-s2\">(defun rev (l)</span>\n<span class=\"tok-s2\">(Pure (-&gt; (</span>\n<span class=\"tok-s2\">    &#39;(t))</span>\n<span class=\"tok-s2\">&#39;(t)))</span>\n<span class=\"tok-s2\">(match l</span>\n<span class=\"tok-s2\">    (nil nil)</span>\n<span class=\"tok-s2\">    ((Cons h t) (snoc (rev t) h))))</span>\n<span class=\"tok-s2\">    &quot;</span><span class=\"tok-o\">;</span>\n<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>\n<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>\n\n<span class=\"tok-n\">println</span><span class=\"tok-o\">!(</span><span class=\"tok-s2\">&quot;{}&quot;</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\">(&amp;</span><span class=\"tok-n\">ctx</span><span class=\"tok-o\">));</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>これは以下のようなCoqのコードを出力します。\nこの出力には、BLispのプレリュードも含まれます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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>\n<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>\n\n<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>\n<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>\n<span class=\"tok-o\">|</span> <span class=\"tok-n\">None</span><span class=\"tok-o\">.</span>\n\n<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>\n<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>\n\n<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>\n<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>\n<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>\n\n<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>\n<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>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">Some</span> <span class=\"tok-n\">n</span><span class=\"tok-o\">)</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">None</span><span class=\"tok-o\">)</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</span> <span class=\"tok-n\">l</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">nil</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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\">-&gt;</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>\n<span class=\"tok-o\">(</span><span class=\"tok-n\">reverse</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">filter&#39;</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>\n\n<span class=\"tok-kn\">Fixpoint</span> <span class=\"tok-n\">filter&#39;</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\">-&gt;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</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>\n    <span class=\"tok-o\">|</span> <span class=\"tok-bp\">true</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">filter&#39;</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>\n    <span class=\"tok-o\">|</span> <span class=\"tok-bp\">false</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">filter&#39;</span> <span class=\"tok-n\">f</span> <span class=\"tok-n\">a</span> <span class=\"tok-n\">l</span> <span class=\"tok-o\">)</span>\n    <span class=\"tok-k\">end</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">l</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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\">-&gt;</span> <span class=\"tok-n\">b</span> <span class=\"tok-o\">-&gt;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</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>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">init</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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\">-&gt;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</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>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">nil</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">l</span> <span class=\"tok-k\">with</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-n\">nil</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">nil</span>\n  <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\">=&gt;</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>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-o\">(</span><span class=\"tok-n\">reverse&#39;</span> <span class=\"tok-n\">x</span> <span class=\"tok-n\">nil</span> <span class=\"tok-o\">).</span>\n\n<span class=\"tok-kn\">Fixpoint</span> <span class=\"tok-n\">reverse&#39;</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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">x</span> <span class=\"tok-k\">with</span>\n  <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\">=&gt;</span> <span class=\"tok-o\">(</span><span class=\"tok-n\">reverse&#39;</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>\n  <span class=\"tok-o\">|</span> <span class=\"tok-o\">_</span> <span class=\"tok-o\">=&gt;</span> <span class=\"tok-n\">l</span>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span>\n\n<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>\n<span class=\"tok-k\">match</span> <span class=\"tok-n\">l</span> <span class=\"tok-k\">with</span>\n  <span class=\"tok-o\">|</span> <span class=\"tok-n\">nil</span> <span class=\"tok-o\">=&gt;</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>\n  <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\">=&gt;</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>\n  <span class=\"tok-k\">end</span><span class=\"tok-o\">.</span></code></pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>このトランスパイラは実験的なものであることに注意してください。\nよって、いくつかの出力はCoqが解釈できません。\nその場合は、手動でソースコードを修正してください。\n簡単にできるはずです。</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_例\">21. 例</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_リバース\">21.1. リバース</h3>\n<div class=\"paragraph\">\n<p><em>reverse</em> は内部で定義されている関数です。この関数はリストを反転します。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>このコードの出力は以下の通りです。</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>'(9 8 7 6 5 4 3 2 1)</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_filter\">21.2. Filter</h3>\n<div class=\"paragraph\">\n<p><em>filter</em> は内部で定義されている関数です。この関数はリストの中身をフィルターします。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">&#39;</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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>このコードの出力は以下の通りです。</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>'(2 4 6 8)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><em>filter</em>' の型は以下の通りです。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</span>\n<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\">-&gt;</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\">; 関数を引数にとる</span>\n<span class=\"tok-w\">     </span><span class=\"tok-o\">&#39;</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\">; リストを引数にとる</span>\n<span class=\"tok-w\">    </span><span class=\"tok-o\">&#39;</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\">; リストをリターン</span></code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_階乗\">21.3. 階乗</h3>\n<div class=\"paragraph\">\n<p>末尾呼び出し版の階乗関数は、以下のように実装できます。</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<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\">-&gt;</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>\n<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>\n\n<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\">-&gt;</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>\n<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\">&lt;=</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>\n<span class=\"tok-w\">        </span><span class=\"tok-nv\">total</span>\n<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>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>この関数は以下のように呼び出すことができます。</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&gt;&gt; (factorial 10)\n3628800\n&gt;&gt;\n&gt;&gt; (factorial 1000)\n402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n&gt;&gt;\n&gt;&gt; (factorial 100)\n93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000\n&gt;&gt;\n&gt;&gt; (factorial 500)\n1220136825991110068701238785423046926253574342803192842192413588385845373153881997605496447502203281863013616477148203584163378722078177200480785205159329285477907571939330603772960859086270429174547882424912726344305670173270769461062802310452644218878789465754777149863494367781037644274033827365397471386477878495438489595537537990423241061271326984327745715546309977202781014561081188373709531016356324432987029563896628911658974769572087926928871281780070265174507768410719624390394322536422605234945850129918571501248706961568141625359056693423813008856249246891564126775654481886506593847951775360894005745238940335798476363944905313062323749066445048824665075946735862074637925184200459369692981022263971952597190945217823331756934581508552332820762820023402626907898342451712006207714640979456116127629145951237229913340169552363850942885592018727433795173014586357570828355780158735432768888680120399882384702151467605445407663535984174430480128938313896881639487469658817504506926365338175055478128640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nVersion 0.4.0<br>\nLast updated 2026-04-28 09:28:41 +0900\n</div>\n</div>\n<script type=\"text/x-mathjax-config\">\nMathJax.Hub.Config({\n  messageStyle: \"none\",\n  tex2jax: {\n    inlineMath: [[\"\\\\(\", \"\\\\)\"]],\n    displayMath: [[\"\\\\[\", \"\\\\]\"]],\n    ignoreClass: \"nostem|nolatexmath\"\n  },\n  asciimath2jax: {\n    delimiters: [[\"\\\\$\", \"\\\\$\"]],\n    ignoreClass: \"nostem|noasciimath\"\n  },\n  TeX: { equationNumbers: { autoNumber: \"none\" } }\n})\nMathJax.Hub.Register.StartupHook(\"AsciiMath Jax Ready\", function () {\n  MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {\n    if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains(\"stemblock\")) {\n      data.math.root.display = \"block\"\n    }\n    return data\n  })\n})\n</script>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML\"></script>\n</body>\n</html>"
  },
  {
    "path": "embed_macro/Cargo.toml",
    "content": "[package]\nname = \"blisp_embedded\"\nversion = \"0.1.1\"\nauthors = [\"Yuuki Takano <ytakanoster@gmail.com>\", \"Fumiya Saito\"]\nedition = \"2021\"\ndescription = \"embedded macro for BLisp\"\nrepository = \"https://github.com/ytakano/blisp\"\nkeywords = [\n    \"no_std\",\n    \"scripting\",\n    \"scripting-engine\",\n    \"scripting-language\",\n    \"embedded\",\n]\ncategories = [\"no-std\", \"embedded\"]\nlicense-file = \"LICENSE\"\nreadme = \"README.md\"\nhomepage = \"https://ytakano.github.io/blisp/\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[lib]\nproc-macro = true\n\n[dependencies]\nsyn = { version = \"2.0\", features = [\"full\"] }\nquote = \"1.0\"\nproc-macro2 = \"1.0\"\nconvert_case = \"0.7\"\n"
  },
  {
    "path": "embed_macro/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Yuuki Takano <ytakano@wide.ad.jp>, Fumiya Saito\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "embed_macro/README.md",
    "content": "# `embedded` macro for BLisp\n\nPlease see [blisp-repl](https://github.com/ytakano/blisp-repl) to use BLisp,\nand [baremetalisp](https://github.com/ytakano/baremetalisp) which is a toy OS.\n\n**[Homepage](https://ytakano.github.io/blisp/) is here.**\n"
  },
  {
    "path": "embed_macro/src/lib.rs",
    "content": "extern crate proc_macro;\n\nuse convert_case::{Case, Casing};\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\nuse syn::{parse_macro_input, FnArg, GenericArgument, Item, PathArguments, Signature, Type};\n\n#[proc_macro_attribute]\npub fn embedded(\n    _args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    let mut out = input.clone();\n\n    let ty = parse_macro_input!(input as Item);\n    let item_fn = match ty {\n        Item::Fn(ref n) => n,\n        _ => panic!(\"only function is allowed\"),\n    };\n\n    let fn_name = &item_fn.sig.ident.clone();\n\n    let fn_name_camel = {\n        let mut temp = format!(\"{}\", fn_name);\n        temp = temp.to_case(Case::Pascal);\n        Ident::new(&temp, Ident::span(fn_name))\n    };\n\n    // Generate BLisp.\n    let fn_data = &item_fn.sig;\n    let inputs_parse = inputs_type(fn_data);\n    let output_ty = output_type(fn_data);\n\n    let fn_body = format!(\"(extern {} (-> ({}) {}))\", fn_name, inputs_parse, output_ty);\n\n    // Generate FFI\n    let fn_name_ffi = {\n        let temp = format!(\"{fn_name}_ffi\");\n        Ident::new(&temp, Ident::span(fn_name))\n    };\n\n    let fn_name_str = format!(\"{fn_name}\");\n\n    let ffi_body = generate_ffi_body(fn_data, &fn_name, &fn_name_ffi);\n\n    let expanded = quote! {\n        struct #fn_name_camel;\n\n        impl blisp::runtime::FFI for #fn_name_camel {\n            fn blisp_extern(&self) -> &'static str { #fn_body }\n\n            fn ffi(&self) -> fn(&mut blisp::runtime::Environment<'_>, &[blisp::runtime::RTData]) -> blisp::runtime::RTData {\n                use blisp::runtime::{Environment, RTData, RTDataToRust, RustToRTData};\n                fn ffi_inner(env: &mut Environment<'_>, args: &[RTData]) ->RTData {\n                    #ffi_body\n                }\n                ffi_inner\n            }\n\n            fn name(&self) -> &'static str {\n                #fn_name_str\n            }\n        }\n    };\n\n    out.extend(proc_macro::TokenStream::from(expanded));\n    out\n}\n\nfn generate_ffi_body(data: &Signature, fn_name: &Ident, fn_name_ffi: &Ident) -> TokenStream {\n    let mut body = quote! {};\n    for (i, arg) in data.inputs.iter().enumerate() {\n        let arg_type = match arg {\n            FnArg::Typed(pat) => &*pat.ty,\n            _ => panic!(\"Need an explicitly typed input pattern \"),\n        };\n\n        let arg_dst = {\n            let temp = format!(\"arg{i}\");\n            Ident::new(&temp, Ident::span(fn_name_ffi))\n        };\n\n        let arg_src = {\n            quote! {\n                &args[#i]\n            }\n        };\n\n        let casting = typecast(arg_type, arg_dst, arg_src);\n\n        body = quote! {\n            #body\n            #casting\n        };\n    }\n\n    let ffi_invoke = call_ffi(data.inputs.len(), fn_name);\n\n    quote! {\n        #body\n        let result = #ffi_invoke;\n        RustToRTData::from(env, result)\n    }\n}\n\nfn call_ffi(len: usize, fn_name: &Ident) -> TokenStream {\n    match len {\n        0 => quote! {\n            #fn_name()\n        },\n        1 => quote! {\n            #fn_name(arg0)\n        },\n        2 => quote! {\n            #fn_name(arg0, arg1)\n        },\n        3 => quote! {\n            #fn_name(arg0, arg1, arg2)\n        },\n        4 => quote! {\n            #fn_name(arg0, arg1, arg2, arg3)\n        },\n        5 => quote! {\n            #fn_name(arg0, arg1, arg2, arg3, arg4)\n        },\n        6 => quote! {\n            #fn_name(arg0, arg1, arg2, arg3, arg4, arg5)\n        },\n        7 => quote! {\n            #fn_name(arg0, arg1, arg2, arg3, arg4, arg5, arg6)\n        },\n        8 => quote! {\n            #fn_name(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\n        },\n        9 => quote! {\n            #fn_name(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)\n        },\n        _ => panic!(\"too many arguments\"),\n    }\n}\n\nfn typecast(ty: &Type, arg_dst: Ident, arg_src: TokenStream) -> TokenStream {\n    match ty {\n        Type::Tuple(_tup) => {\n            quote! {\n                let #arg_dst: #ty = RTDataToRust::into(#arg_src);\n            }\n        }\n        Type::Path(path) => match &path.path.segments.first().unwrap().arguments {\n            PathArguments::None => {\n                quote! {\n                    let #arg_dst: #ty = RTDataToRust::into(#arg_src);\n                }\n            }\n            PathArguments::AngleBracketed(_ang) => {\n                let type_name = &path.path.segments.first().unwrap().ident;\n                let type_name_str = format!(\"{}\", &type_name);\n\n                match type_name_str.as_str() {\n                    \"Vec\" | \"Option\" | \"Result\" => quote! {\n                        let #arg_dst: #ty = RTDataToRust::into(#arg_src);\n                    },\n                    _ => panic!(\"only Vec, Option, or Result generics types are allowed\"),\n                }\n            }\n            _ => panic!(\"no parentheses at PathArgument\"),\n        },\n        _ => panic!(\"parse type miss\"),\n    }\n}\n\nfn inputs_type(data: &Signature) -> String {\n    let ret = data.inputs.iter().map(|arg| match arg {\n        FnArg::Typed(pat) => parse_type(&*pat.ty),\n        _ => panic!(\"Need an explicitly typed input pattern \"),\n    });\n\n    let mut statements = String::from(\"\");\n    for (i, data) in ret.enumerate() {\n        if i == 0 {\n            statements = format!(\"{}{}\", statements, data);\n        } else {\n            statements = format!(\"{} {}\", statements, data);\n        }\n    }\n    statements\n}\n\nfn output_type(data: &Signature) -> String {\n    let ret = match &data.output {\n        syn::ReturnType::Default => \"[]\".to_string(),\n        syn::ReturnType::Type(_, ty) => parse_type(&*ty),\n    };\n\n    ret\n}\n\nfn parse_type(ty: &Type) -> String {\n    match ty {\n        Type::Tuple(tup) => {\n            let mut statements = String::from(\"[\");\n\n            for (i, data) in tup.elems.iter().enumerate() {\n                if i == 0 {\n                    statements = format!(\"{}{}\", statements, parse_type(data));\n                } else {\n                    statements = format!(\"{} {}\", statements, parse_type(data));\n                }\n            }\n            format!(\"{}]\", statements)\n        }\n        Type::Path(path) => {\n            let mut args_str = String::from(\"\");\n            match &path.path.segments.first().unwrap().arguments {\n                // not generic type (eg BigInt)\n                PathArguments::None => ex_type_check(&path.path.segments.first().unwrap().ident),\n\n                // generic type (vec, option, result)\n                PathArguments::AngleBracketed(ang) => {\n                    let args = ang.args.iter().map(|a| match a {\n                        GenericArgument::Type(gene_type) => parse_type(gene_type),\n                        _ => panic!(\"GenericArgument is only Type\"),\n                    });\n\n                    for (i, data) in args.enumerate() {\n                        if i == 0 {\n                            args_str = format!(\"{}{}\", args_str, data);\n                        } else {\n                            args_str = format!(\"{} {}\", args_str, data);\n                        }\n                    }\n\n                    let type_name = &path.path.segments.first().unwrap().ident;\n                    let type_name_str = format!(\"{}\", &type_name);\n\n                    match type_name_str.as_str() {\n                        \"Vec\" => format!(\"'({})\", args_str),\n                        \"Option\" => format!(\"(Option {})\", args_str),\n                        \"Result\" => format!(\"(Result {})\", args_str),\n                        _ => panic!(\"only Vec, Option, or Result generics types are allowed\"),\n                    }\n                }\n                _ => panic!(\"no parentheses at PathArgument\"),\n            }\n        }\n        _ => panic!(\"parse type miss\"),\n    }\n}\n\nfn ex_type_check(id: &Ident) -> String {\n    let id_str = format!(\"{}\", &id);\n    match &*id_str {\n        \"BigInt\" => String::from(\"Int\"),\n        \"char\" => String::from(\"Char\"),\n        \"String\" => String::from(\"String\"),\n        \"bool\" => String::from(\"Bool\"),\n        _ => panic!(\"arguments must be BigInt, char, bool, or String\"),\n    }\n}\n"
  },
  {
    "path": "history.md",
    "content": "# 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 to Coq\n\n## 0.3.9\n\n- fix a bug on the garbage collector\n\n## 0.3.8\n\n- fix a bug on typing\n  - check the number of arguments\n  - (+ 10) was passed typing rule\n- add != and neq\n  - (!= 10 10)\n  - (neq (Some \"Hello\") 10)\n\n## 0.3.7\n\n- add bit shift operators\n  - (<< 8 4)   ; shift left\n  - (>> 128 4) ; shift right\n- add Char type\n- add character literal\n  - \\`H\\`\n- add chars and str functions\n  - chars converts String to (List Char)\n    - (chars \"Hello, World!\")\n  - str converts (List Char) to String\n    - (str '(\\`H\\` \\`e\\` \\`l\\` \\`l\\` \\`o\\`))\n\n## 0.3.6\n\n- make <, >, <=, >= functions' type (Pure (-> (t t) Bool))\n  - perform comparison between 2 values whose types are same\n  - (< \"Hello\" \"World\")\n  - (>= (Some 5) (Some 19))\n- add lt, gt, leq, geq functions\n  - perform comparison between any 2 values\n  - function type is (Pure (-> (t1 t2) Bool))\n  - (eq \"Hello\" 10)\n  - (lt (Some 6) \"Hello\")\n\n## 0.3.5\n\n- add string type and literal\n  - String\n  - \"Hello World!\"\n- make equal function generics\n  - it can be used for non-integer types\n  - (= \"Hello\" \"Hello\")\n  - (= (Some 1) (Some 2))\n- fix a bug on typing\n  - (= (Some 1) (Some 2)) could not be typed properly\n\n## 0.3.4\n\n- fix bugs on typing\n  - bug 1: some locally defined functions are cannot be called\n  - bug 2: empty list cannot be typed properly\n- add filter and reverse functions to prelude\n\n## 0.3.3\n\n- add hexadecimal, octal, and binary\n  - 0xabcDEF\n  - 0o777\n  - 0b1010\n\n## 0.3.2\n\n- add pow to compute exponent\n  - example: (pow 10 20)\n  - type of pow: (Pure (-> (Int Int) (Option Int)))\n  - if the exponent portion is greater or equal to 2^32, then return None\n- add sqrt\n  - example: (sqrt 16)\n  - type of sqrt: (Pure (-> (Int) (Option Int)))\n  - if the value is less than 0, then return None\n- add bitwise operations\n  - band, bor, bxor\n\n## 0.3.1\n\n- garbage collection is ready (mark and sweep)\n"
  },
  {
    "path": "specification/Makefile",
    "content": "all: typing.pdf\n\ntyping.dvi: typing.tex\n\tplatex typing.tex\n\tplatex typing.tex\n\ntyping.pdf: typing.dvi\n\tdvipdfmx -p letter typing.dvi\n\nclean:\n\trm -f *.dvi *.log *.aux *.pdf"
  },
  {
    "path": "specification/language.md",
    "content": "# Syntax and Semantics of BLisp\n\n## Literal\n\n- $LITERAL := $HEX | $OCT | $BIN | $DECIMAL | $BOOL | $STRING | $CHAR\n- $DECIMAL\n  - decimal number\n  - examples: 0, 100, 224, -130, 4457, 0007\n- $HEX\n  - hexadecimal number\n  - examples: 0xabcd 0xABCD\n- $BIN\n  - binary number\n  - examples: 0b1100, 0b01011\n- $BOOL := true | false\n- $STRING\n  - string literal\n  - example: \"Hello, World!\"\n  - escape sequences\n    - \\r\n    - \\n\n    - \\t\n    - \\0\n    - \\\\\\\\\n    - \\\\\"\n- $CHAR\n  - character literal\n  - example: \\`H\\`\n  - escape sequences\n    - \\r\n    - \\n\n    - \\t\n    - \\0\n    - \\\\\\\\\n    - \\\\\\`\n\n## Identifier\n\n- $ID\n  - a string whose first character is not capital (not 'A' to 'Z')\n  - excludes \"true\" and \"false\"\n\n## Type Identifier\n\n- $TID\n  - a string whose first character is capital ('A' to 'Z')\n\n## Type\n\n- $TYPE := Int | Bool | String | Char | $TYPE_LIST | $TYPE_TUPLE | $TYPE_FUN | $TYPE_DATA | $ID\n- $TYPE_LIST := '( $TYPE )\n- $TYPE_TUPLE := \\[ $TYPE* \\]\n- $TYPE_DATA := $TID | ( $TID $TYPE* )\n- $TYPE_FUN := ( $EFFECT $TYPE_ARROW )\n- $TYPE_ARROW := ( -> $TYPES $TYPE )\n- $TYPES := ( $TYPE* )\n- $EFFECT := Pure | IO\n\nexamples:\n\n```common-lisp\n'(Int)\n[Int Bool]\n(Pure (-> (Int INT) Bool))\n'('(Int Bool))\n[Int Int '([Int Bool])]\n```\n\n## Data Type\n\n- $DATA := ( data $DATA_NAME $MEMBER* )\n- $DATA_NAME := $TID | ( $TID $ID* )\n- $MEMBER := $TID | ( $TID $TYPE* )\n\nexamples:\n\n```common-lisp\n(data Dim2\n  (Dim2 Int Int))\n\n(data (Maybe t)\n    (Just t)\n    Nothing)\n\n(data (Tree t)\n    (Node (Tree t) (Tree t))\n    Leaf)\n```\n\n## Function Definition\n\n- $DEFUN := ( $HEAD_DEFUN $ID ( $ID* ) $TYPE_FUN $EXPR )\n- $HEAD_DEFUN := export | defun\n\nexample:\n\n```common-lisp\n(defun add (x y) (Pure (-> (Int Int) Int))\n  (+ x y))\n```\n\n## External Function\n\n- $EXTERN := ( extern $ID $TYPE_ARROW )\n\n## Expression\n\n- $EXPR := $LITERAL | $ID | $TID | $LET | $IF | $LAMBDA | $MATCH | $LIST | $TUPLE | $GENDATA | $APPLY\n\n### Let Expression\n\n- $LET := ( let ( $DEFVAR+ ) $EXPR )\n- $DEFVAR := ( $LETPAT $EXPR )\n- $LETPAT := $ID | [ $LETPAT+ ] | ($TID $LETPAT+ )\n\n### If Expression\n\n- $IF := ( if $EXPR $EXPR $EXPR )\n\n### List Expression\n\n- $LIST := '( $EXPR* )\n\n### Tuple Expression\n\n- $TUPLE := [ $EXPR* ]\n\n### Match Expression\n\n- $MATCH := ( match $EXPR $CASE+ )\n- $CASE := ( $PATTERN $EXPR )\n- $PATTERN := $LITERAL | $ID | $TID | \\[ $PATTERN+ \\] | ( $TID $PATTERN* ) | '()\n\n### Function Application\n\n- $APPLY := ( $EXPR+ )\n\n### Data Creataion\n\n- $GENDATA := ( $TID $EXPR* )\n\n### Lambda\n\n- $LAMBDA := (lambda ($ID*) $EXPR)\n\n## Built-in Functions\n\n- +, -, *, /, %: (Pure (-> (Int Int) Int))\n- band, bor, bxor: (Pure (-> (Int Int) Int))\n- pow, <<, >>: (Pure (-> (Int Int) (Some Int)))\n- sqrt: (Pure (-> (Int) (Some Int)))\n- <, >, <=, >=, =: (Pure (-> (t t) Bool))\n- lt, gt, leq, geq, eq: (Pure (-> (t1 t2) Bool))\n- and, or, xor: (Pure (-> (Bool Bool) Bool))\n- not: (Pure (-> (Bool) Bool))\n- chars: (Pure (-> (String) (List Char)))\n- str: (Pure (-> ((List Char)) String))\n\n## Macro\n\n- $MACRO := ( macro $ID $MACRO_RULE+ )\n- $MACRO_RULE := ( ( $EXPR* ) ( $EXPR* ) )\n\n```common-lisp\n(macro add\n  ((add $e1 $e2) (+ $e1 $e2))\n  ((_ $e1 $e2 $e3 ...) (+ $e1 (add $e2 $e3 ...))))\n```\n"
  },
  {
    "path": "specification/typing.tex",
    "content": "\\documentclass{article}\n\n\\usepackage{amsmath,amssymb}\n\\usepackage[dvipdfmx]{hyperref,graphicx}\n\\usepackage{listings}\n\n\\lstset{%\n  language={lisp},\n  basicstyle={\\small\\ttfamily},%\n  identifierstyle={\\small},%\n  commentstyle={\\small\\itshape},%\n  keywordstyle={\\small\\bfseries},%\n  ndkeywordstyle={\\small},%\n  stringstyle={\\small\\ttfamily},\n  frame={tb},\n  keepspaces=true,\n  breaklines=true,\n  columns=[l]{fullflexible},%\n  numbers=left,%\n  xrightmargin=0zw,%\n  xleftmargin=3zw,%\n  numberstyle={\\scriptsize},%\n  stepnumber=1,\n  numbersep=1zw,%\n  lineskip=-0.5ex%\n}\n\n\\title{Typing Rule of Baremetalisp}\n\\author{Yuuki Takano\\\\ ytakano@wide.ad.jp}\n\n\\begin{document}\n\n\\maketitle\n\n\\section{Introduction}\n\nIn this paper, I will formally describe the typing rule of Baremetalisp,\nwhich is a well typed Lisp for trusted execution environment.\n\n\\begin{table}[tb]\n    \\centering\n    \\caption{Notation}\n    \\label{tab:notation}\n    \\begin{tabular}{rl}\n        $A \\Rightarrow B$ & logical implication (if A then B)\\\\\n        $e$ & expression \\\\\n        $z$ & integer literal such as 10, -34, 112 \\\\\n        $x$ & variable \\\\\n        $t$ & type variable \\\\\n        $D$ & type name of user defined data \\\\\n        $L$ & label of user defined data \\\\\n        $E$ & effect \\\\\n        $E_\\mathcal{T}: T \\rightarrow E$ & effect of type \\\\\n        $\\mathcal{T}$ & type \\\\\n        $C$ & type constraint \\\\\n        $io(C): C \\rightarrow \\mathtt{Bool}$ & does $C$ contain $\\mathtt{IO}$ functions? \\\\\n        $\\Gamma$ & context \\\\\n        $\\mathcal{P}$ & pattern \\\\\n        $\\mathcal{P}_{let}$ & pattern of let expression \\\\\n        $\\mathcal{T}_1 \\equiv_\\alpha \\mathcal{T}_2$ & $\\mathcal{T}_1$ and $\\mathcal{T}_2$ are $\\alpha$-equivalent \\\\\n        $\\mathcal{S} : t \\rightarrow \\mathcal{T}$ & substitution from type variable to type\\\\\n        $\\mathcal{T} \\cdot \\mathcal{S}$ & apply $\\mathcal{S}$ to $\\mathcal{T}$ \\\\\n        $\\mathcal{X}$ & set of $t$ \\\\\n        $FV_\\mathcal{T} : \\mathcal{T} \\rightarrow \\mathcal{X}$ & function from $\\mathcal{T}$ to its free variables\\\\\n        $FV_\\Gamma : \\Gamma \\rightarrow \\mathcal{X}$ & function from $\\Gamma$ to its free variables\\\\\n        $Size : L \\rightarrow \\mathtt{Int}$ & the number of labels $L$'s type has \\\\\n        $\\Gamma \\vdash e : \\mathcal{T}\\ |_\\mathcal{X}\\ C$ & $e$'s type is deduced as $\\mathcal{T}$ from $\\Gamma$ \\\\\n        & under constraint $C$ and type variables $\\mathcal{X}$\n    \\end{tabular}\n\\end{table}\n\n\\begin{figure}[tb]\n    \\centering\n    \\begin{tabular}{rrll}\n    $\\mathcal{C}$ & := & $\\mathcal{T} = \\mathcal{T}, \\mathcal{C}$ & \\bf{type constraint} \\\\\n        & $|$ & $\\varnothing$ \\\\ \\\\\n\n    $\\Gamma$ & := & & \\bf{context} \\\\\n        &     & $x: \\mathcal{T}, \\Gamma$ & type of variable \\\\\n        & $|$ & $L: \\mathcal{T}, \\Gamma$ & type of label \\\\\n        & $|$ & $L_{nth}: \\mathcal{T}, \\Gamma$ & n-th type of label's element \\\\\n        & $|$ & $\\varnothing$ \\\\ \\\\\n\n    $E$ & := & $\\mathtt{Pure}\\ |\\ \\mathtt{IO}$ & \\bf{effect} \\\\ \\\\\n\n    $\\mathcal{T}$ & := & & \\bf{type} \\\\\n        &     & $\\mathtt{Int}$ \\\\\n        & $|$ & $\\mathtt{Bool}$ \\\\\n        & $|$ & $'(\\mathcal{T})$ & list type \\\\\n        & $|$ & $[\\mathcal{T}+]$ & tuple type \\\\\n        & $|$ & $D$    & user defined type \\\\\n        & $|$ & $(D\\ \\mathcal{T}+)$ & user defined type with type arguments \\\\\n        & $|$ & $(E\\ (\\rightarrow\\ (\\mathcal{T}*)\\ \\mathcal{T}))$ & function type \\\\\n        & $|$ & $t$ & type variable \\\\ \\\\\n\n    $\\mathcal{P}$ & := & & \\bf{pattern} \\\\\n        &     & $x$ & variable \\\\\n        & $|$ & $L$ & label \\\\\n        & $|$ & $(L\\ \\mathcal{P}+)$ & label with patterns \\\\\n        & $|$ & $'()$ & empty list \\\\\n        & $|$ & $[\\mathcal{P}+]$ & tuple \\\\ \\\\\n\n    $\\mathcal{P}_{let}$ & := & & \\bf{patten for let} \\\\\n        &     & $x$ & variable \\\\\n        & $|$ & $(L\\ \\mathcal{P}_{let}+)$ & label with patterns \\\\\n        & $|$ & $[\\mathcal{P}_{let}+]$ & tuple \\\\\n    \\end{tabular}\n    \\caption{Syntax}\n    \\label{fig:syntax}\n\\end{figure}\n\n\\section{Notation and Syntax}\n\nTable~\\ref{tab:notation} and Fig.~\\ref{fig:syntax} shows notation used in this paper\nand syntax for the typing rule, respectively.\n\n\\begin{lstlisting}[caption=Example of variable and type,label=src:vars]\n(defun add (a b) (Pure (-> (Int Int) Int))\n    (+ a b))\n\\end{lstlisting}\n\n$x$ is a variable.\nFor example, $x \\in \\{a, b\\}$ in Listing~\\ref{src:vars}.\n$\\mathcal{T}$ is a type.\nFor example, $\\mathcal{T} \\in \\{\\mathtt{Int}, (\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int})\\}$\nin Listing~\\ref{src:vars}.\n$(\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int})$ is a function type which takes 2 integer values\nand return 1 integer value.\n$\\mathtt{Pure}$ in Listing~\\ref{src:vars} denotes the effect of the function but I just ignore it now.\nFunction effects will be described in Sec.~\\ref{sec:effect}.\n$\\mathcal{T}$ can be other forms as described in Fig.~\\ref{fig:syntax} such as\n$\\mathtt{Bool}$, $'(\\mathtt{Int})$, $[\\mathtt{Bool}\\ \\mathtt{Int}]$, $(\\mathrm{List}\\ a)$, $(\\mathrm{List}\\ \\mathtt{Int})$.\n$C$ is a type constraint, which is a set of pairs of types.\nFor example, $C = \\{(\\rightarrow\\ (t_1\\ t_2)\\ t) = (\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int})\\}$ deduced from\nListing~\\ref{src:vars} means $(\\rightarrow\\ (t_1\\ t_2)\\ t)$ and $(\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int})$ are\nsemantically equal and every type variable in $C$, $t_1, t_2, t$, is thus $\\mathtt{Int}$.\n$\\Gamma$ is a map from variable and label to type.\nFor example, $\\Gamma = \\{a : t_1, b : t_2, + : (\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int})\\}$\nin Listing~\\ref{src:vars}.\n$\\Gamma$ is called context generally, thus I call $\\Gamma$ context in this paper.\n\n\\begin{lstlisting}[caption=Example of user defined data type,label=src:cons]\n(data (List a)\n    (Cons a (List a))\n    Nil)\n\\end{lstlisting}\n\n$t$ is a type variable.\nFor example, $t \\in \\{a\\}$ in Listing~\\ref{src:cons}.\n$L$ is a label for user defined type.\nFor example, $L \\in \\{\\mathrm{Cons}, \\mathrm{Nil}\\}$ in Listing~\\ref{src:cons}.\n$D$ is user defined data.\nFor example, $D \\in \\{\\mathrm{List}\\}$ in Listing~\\ref{src:cons}.\n$\\Gamma$ will hold mapping from labels in addition to variables.\nFor example,\n$\\Gamma = \\{\\mathrm{Cons} : (\\mathrm{List}\\ a), \\mathrm{Nil} : (\\mathrm{List}\\ a), \\mathrm{Cons}_{1st} : a, \\mathrm{Cons}_{2nd} : (\\mathrm{List}\\ a)\\}$\nin Listing~\\ref{src:cons}.\n\n$FV_\\mathcal{T}$ and $FV_\\Gamma$ are functions, which take $\\mathcal{T}$ and $\\Gamma$ and return free variables.\nFor example, $FV_\\mathcal{T}((\\rightarrow\\ (t_1\\ t_2)\\ t)) = \\{t_1, t_2, t\\}$ and\n\\begin{equation*}\n    \\begin{aligned}\n        &FV_\\Gamma(\\{a : t_1, b : t_1, + : (\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int})\\}) \\\\\n        &=\\{FV_\\mathcal{T}(t_1), FV_\\mathcal{T}(t_1), FV_\\mathcal{T}((\\rightarrow\\ (\\mathtt{Int}\\ \\mathtt{Int})\\ \\mathtt{Int}))\\} \\\\\n        &=\\{t_1, t_2\\}.\n    \\end{aligned}\n\\end{equation*}\n$\\mathcal{T}_1 \\equiv_\\alpha \\mathcal{T}_2$ denotes that $\\mathcal{T}_1$ and $\\mathcal{T}_2$ are $\\alpha$-equivalent,\nwhich means $\\mathcal{T}_1$ and $\\mathcal{T}_2$ are semantically equal.\nFor example, $(\\rightarrow\\ (t_1\\ t_2)\\ t) \\equiv_\\alpha (\\rightarrow\\ (t_{10}\\ t_{11})\\ t_{12})$.\n$\\mathcal{S}$ is a substitution, which is a map from type variable to type,\nand it can be applied to $\\mathcal{T}$ as $\\mathcal{T} \\cdot \\mathcal{S}$.\nFor example, if $\\mathcal{S}(t_1) = [\\mathtt{Bool}\\ \\mathtt{Int}], \\mathcal{S}(t_2) = (\\mathrm{List}\\ t_3)$ then\n$(\\rightarrow\\ (t_1\\ t_2)\\ t) \\cdot \\mathcal{S} = (\\rightarrow\\ ([\\mathtt{Bool}\\ \\mathtt{Int}]\\ (\\mathrm{List}\\ t_3))\\ t)$.\n\n\\begin{lstlisting}[caption=Example of pattern matching,label=src:match]\n(data Dim2 (Dim2 Int Int))\n\n(data (Maybe t)\n    (Just t)\n    Nothing)\n\n(defun match-let (a) (Pure (-> ((Maybe Dim2)) Int))\n    (match a\n        ((Just val)\n            (let (((Dim2 x y) val))\n                (+ x y)))\n        (Nothing\n            0)))\n\\end{lstlisting}\n$\\mathcal{P}$ and $\\mathcal{P}_{let}$ are pattern in match and let expressions.\nFor example, in listings~\\ref{src:match}, $(\\mathrm{Just}\\ val)$ and Nothing at line 9 and 12 are from $\\mathcal{P}$\nand $(\\mathrm{Dim2}\\ x\\ y)$ at line 10 is from $\\mathcal{P}_{let}$.\n$Size$ is a function which takes a label and return the number of labels the label's type has.\nFor example, $Size(\\mathrm{Just}) = Size(\\mathrm{Nothing}) = 2$ because Maybe type has 2 labels\nand $Size(\\mathrm{Dim2}) = 1$ because Dim2 type has 1 label in listings~\\ref{src:match}.\n\n\\begin{figure}[tb]\n    \\centering\n    \\begin{tabular}{rlrl}\n        $\\Gamma \\vdash \\mathtt{true} : \\mathtt{Bool}\\ |_\\varnothing\\ \\varnothing$ & (T-True) &\n        $\\Gamma \\vdash \\mathtt{false} : \\mathtt{Bool}\\ |_\\varnothing\\ \\varnothing$ & (T-False) \\vspace{5mm} \\\\\n\n        $\\dfrac{x : T \\in \\Gamma}{\\Gamma \\vdash x : T\\ |_\\varnothing\\ \\varnothing}$ & (T-Var) &\n        $\\Gamma \\vdash z : \\mathtt{Int}\\ |_\\varnothing\\ \\varnothing$ & (T-Num) \\vspace{5mm} \\\\\n\n        $\\dfrac{x : T' \\in \\Gamma \\hspace{5mm} T' \\cdot S \\equiv_\\alpha T}{\\Gamma \\vdash x : T\\ |_{FV_\\mathcal{T}(T)}\\ \\varnothing}$ & (T-VarPoly) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma_0 \\vdash \\mathcal{P}_{let} : \\mathcal{T}_0\\ |_{\\mathcal{X}_0}\\ C_0 \\hspace{5mm}\n                    \\Gamma \\vdash e_1 : \\mathcal{T}_1\\ |_{\\mathcal{X}_1}\\ C_1 \\hspace{5mm}\n                    \\Gamma, \\Gamma_0 \\vdash e_2 : \\mathcal{T}_2\\ |_{\\mathcal{X}_2}\\ C_2\\\\\n                &\\mathcal{X}_0 \\cap \\mathcal{X}_1 \\cap \\mathcal{X}_2 = \\varnothing \\hspace{5mm}\n                    C = C_0 \\cup C_1 \\cup C_2 \\cup \\{ \\mathcal{T}_0 = \\mathcal{T}_1 \\}\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash (\\mathtt{let1}\\ \\mathcal{P}_{let}\\ e_1\\ e_2) : \\mathcal{T}_2\\ |_{\\mathcal{X}_0 \\cup \\mathcal{X}_1 \\cup \\mathcal{X}_2}\\ C\n        }$} & (T-Let1) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma \\vdash e_1 : \\mathcal{T}_1\\ |_{\\mathcal{X}_1}\\ C_1 \\hspace{5mm} \\Gamma \\vdash e_2 : \\mathcal{T}_2\\ |_{\\mathcal{X}_2}\\ C_2 \\hspace{5mm} \\Gamma \\vdash e_3 : \\mathcal{T}_3\\ |_{\\mathcal{X}_3}\\ C_3 \\\\\n                &\\mathcal{X}_1 \\cap \\mathcal{X}_2 \\cap \\mathcal{X}_3 = \\varnothing \\hspace{5mm} C = C_1 \\cup C_2 \\cup C_3 \\cup \\{ \\mathcal{T}_1 = \\mathtt{Bool}, \\mathcal{T}_2 = T_3 \\}\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash (\\mathtt{if}\\ e_1\\ e_2\\ e_3) : \\mathcal{T}_2\\ |_{\\mathcal{X}_1 \\cup \\mathcal{X}_2 \\cup \\mathcal{X}_3}\\ C\n        }$} & (T-If) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma \\vdash e_1 : \\mathcal{T}_1\\ |_{\\mathcal{X}_1}\\ C_1 \\hspace{5mm}\n                    \\Gamma \\vdash e_2 : \\mathcal{T}_2\\ |_{\\mathcal{X}_2}\\ C_2 \\land \\cdots \\land \\Gamma \\vdash e_n : \\mathcal{T}_n\\ |_{\\mathcal{X}_n}\\ C_n \\\\\n                &\\{t\\} \\cap FV_\\Gamma(\\Gamma) = \\varnothing \\hspace{5mm} \\{t\\} \\cap \\mathcal{X}_1 \\cap \\cdots \\cap \\mathcal{X}_n = \\varnothing\\\\\n                &\\mathcal{X} = \\{t\\} \\cup \\mathcal{X}_1 \\cup \\cdots \\cup \\mathcal{X}_n \\hspace{5mm} E = E_\\mathcal{T}(\\mathcal{T}_1) \\\\\n                &C = C_1 \\cup \\cdots \\cup C_n \\cup \\{ \\mathcal{T}_1 = (E\\ (\\rightarrow\\ (\\mathcal{T}_2\\ \\cdots\\ \\mathcal{T}_n)\\ t)) \\}\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash (e_1\\ e_2\\ \\cdots\\ e_n) : t\\ |_\\mathcal{X}\\ C\n        }$} & (T-App) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma \\vdash e_0 : \\mathcal{T}_0\\ |_{\\mathcal{X}_0}\\ C_0 \\\\\n                &\\Gamma, \\Gamma_1 \\vdash e_1 : \\mathcal{T}_{e1}\\ |_{\\mathcal{X}_{e1}}\\ C_{e1} \\land \\cdots \\land \\Gamma, \\Gamma_n \\vdash e_n : \\mathcal{T}_{en}\\ |_{\\mathcal{X}_{en}}\\ C_{en} \\\\\n                &\\Gamma_1 \\vdash \\mathcal{P}_1 : \\mathcal{T}_{p1}\\ |_{\\mathcal{X}_{p1}}\\ C_{p1} \\land \\cdots \\land \\Gamma_n \\vdash \\mathcal{P}_{pn} : \\mathcal{T}_{pn}\\ |_{\\mathcal{X}_{pn}}\\ C_{pn} \\\\\n                &\\mathcal{X}_0 \\cap \\mathcal{X}_{e1} \\cap \\cdots \\cap \\mathcal{X}_{en} \\cap \\mathcal{X}_{p1} \\cap \\cdots \\cap \\mathcal{X}_{pn} = \\varnothing \\\\\n                &\\mathcal{X} = \\mathcal{X}_0 \\cup \\mathcal{X}_{e1} \\cup \\cdots \\cup \\mathcal{X}_{en} \\cup \\mathcal{X}_{p1} \\cup \\cdots \\cup \\mathcal{X}_{pn} \\\\\n                &\\begin{aligned}\n                    C =\\ &C_0 \\cup C_{e1} \\cup \\cdots \\cup C_{en} \\cup C_{p1} \\cup \\cdots \\cup C_{pn} \\cup \\\\\n                         &\\{\\mathcal{T}_0 = \\mathcal{T}_{p1}, \\cdots, \\mathcal{T}_0 = \\mathcal{T}_{pn}\\} \\cup\n                         \\{\\mathcal{T}_{e1} = \\mathcal{T}_{e2}, \\cdots, \\mathcal{T}_{e1} = \\mathcal{T}_{en}\\}\n                \\end{aligned}\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash (\\mathtt{match}\\ e_0\\ (\\mathcal{P}_1\\ e_1)\\ \\cdots\\ (\\mathcal{P}_n\\ e_n)) : T_{e1}\\ |_\\mathcal{X}\\ C\n        }$} & (T-Match)\n    \\end{tabular}\n    \\caption{Typing rule (1/2)}\n    \\label{fig:typing1}\n\\end{figure}\n\n\\begin{figure}[tb]\n    \\centering\n    \\begin{tabular}{rlrl}\n        $\\Gamma \\vdash\\ '() :\\ '(T)\\ |_{\\{T\\}}\\ \\varnothing$ & (T-Nil) &\n        $\\dfrac{L : \\mathcal{T}' \\in \\Gamma \\hspace{5mm} \\mathcal{T}' \\cdot \\mathcal{S} \\equiv_\\alpha \\mathcal{T}}{\\Gamma \\vdash L : \\mathcal{T}\\ |_{FV_\\mathcal{T}(\\mathcal{T})}\\ \\varnothing}$ & (T-Label0) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n            $\\dfrac{\n                \\begin{aligned}\n                    &\\Gamma \\vdash e_1 : T_1\\ |_{\\mathcal{X}_1}\\ C_1 \\land \\cdots \\land \\Gamma \\vdash e_n : T_n\\ |_{\\mathcal{X}_n}\\ C_n \\\\\n                    &\\mathcal{X}_1 \\cap \\cdots \\cap \\mathcal{X}_n = \\varnothing \\hspace{5mm}\n                    \\mathcal{X} = \\mathcal{X}_1 \\cup \\cdots \\cup \\mathcal{X}_n \\hspace{5mm}\n                    C = C_1 \\cup \\cdots \\cup C_n\n                \\end{aligned}\n            }{\\Gamma \\vdash [e_1\\ \\cdots\\ e_n] : [T_1\\ \\cdots\\ T_n]\\ |_\\mathcal{X}\\ C}$\n        } & (T-Tuple) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n            $\\dfrac{\n                \\begin{aligned}\n                    &\\Gamma \\vdash e_1 : T_1\\ |_{\\mathcal{X}_1}\\ C_1 \\land \\cdots \\land \\Gamma \\vdash e_n : T_n\\ |_{\\mathcal{X}_n}\\ C_n \\\\\n                    &\\mathcal{X}_1 \\cap \\cdots \\cap \\mathcal{X}_n = \\varnothing \\hspace{5mm}\n                    \\mathcal{X} = \\mathcal{X}_1 \\cup \\cdots \\cup \\mathcal{X}_n \\\\\n                    &C = C_1 \\cup \\cdots \\cup C_n \\cup \\{T_1 = T_2, \\cdots, T_1 = T_n \\}\n                \\end{aligned}\n            }{\\Gamma \\vdash\\ '(e_1\\ \\cdots\\ e_n) :\\ '(T_1)\\ |_\\mathcal{X}\\ C}$\n        } & (T-List) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma \\vdash e_1 : \\mathcal{T}_1\\ |_{\\mathcal{X}_1}\\ C_1 \\land \\cdots \\land\n                    \\Gamma \\vdash e_n : \\mathcal{T}_n\\ |_{\\mathcal{X}_n}\\ C_n \\\\\n                &L : \\mathcal{T}_0' \\in \\Gamma \\hspace{5mm} \\mathcal{T}_0' \\cdot \\mathcal{S}\\equiv_\\alpha \\mathcal{T}_0 \\hspace{5mm} FV(\\mathcal{T}_0) \\cap \\mathcal{X}_1 \\cap \\cdots \\cap \\mathcal{X}_n = \\varnothing \\\\\n                &FV_\\mathcal{T}(\\mathcal{T}_0) \\cap FV_\\Gamma(\\Gamma) = \\varnothing \\hspace{5mm}\n                    \\mathcal{X} = FV(\\mathcal{T}_0) \\cup \\mathcal{X}_1 \\cup \\cdots \\cup \\mathcal{X}_n \\\\\n                &L_{1st} : T_1' \\in \\Gamma \\land \\cdots \\land L_{nth} : T_n' \\in \\Gamma \\\\\n                &C = C_1 \\cup \\cdots \\cup C_n \\cup \\{T_1' \\cdot \\mathcal{S} = \\mathcal{T}_1, \\cdots, T_n' \\cdot \\mathcal{S} = \\mathcal{T}_n\\} \\\\\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash (L\\ e_1\\ \\cdots\\ e_n) : \\mathcal{T}_0\\ |_{\\mathcal{X}}\\ C\n        }$} & (T-Label) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n            $\\dfrac{\n                \\begin{aligned}\n                    &\\Gamma, x_1 : t_1, \\cdots, x_n : t_n \\vdash e : \\mathcal{T}_0\\ |_{\\mathcal{X}}\\ C_0 \\hspace{5mm} \\neg io(C)\\\\\n                    &C = \\{\\mathcal{T} = (\\mathtt{Pure}\\ (\\rightarrow\\ (t_1\\ \\cdots\\ t_n)\\ \\mathcal{T}_0))\\} \\cup C_0\n                \\end{aligned}\n            }\n            {\n                \\Gamma \\vdash (\\mathtt{lambda}\\ (x_1\\ \\cdots\\ x_n)\\ e) : \\mathcal{T}\\ |_\\mathcal{X}\\ C\n            }$\n        } & (T-Lambda) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n            $\\dfrac{\n                \\begin{aligned}\n                    &\\Gamma, x_1 : t_1, \\cdots, x_n : t_n \\vdash e : \\mathcal{T}_0\\ |_{\\mathcal{X}}\\ C_0 \\hspace{5mm}\\\\\n                    &E = E_\\mathcal{T}(\\mathcal{T}) \\hspace{5mm} (E = \\mathtt{Pure}) \\Rightarrow \\neg io(C)\\\\\n                    &C = C_0 \\cup \\{\\mathcal{T} = (E\\ (\\rightarrow (\\mathcal{T}_1\\ \\cdots\\ \\mathcal{T}_n)\\ \\mathcal{T}_0)) \\}\n                \\end{aligned}\n            }{\n                \\Gamma \\vdash (\\mathtt{defun}\\ \\mathrm{name}\\ (x_1\\ \\cdots\\ x_n)\\ \\mathcal{T}\\ e) : \\mathcal{T}\\ |_\\mathcal{X}\\ C\n            }$\n        } & (T-Defun)\n    \\end{tabular}\n    \\caption{Typing rule (2/2)}\n    \\label{fig:typing2}\n\\end{figure}\n\n\n\\begin{figure}[tb]\n    \\centering\n    \\begin{tabular}{rlrl}\n        $\\Gamma \\vdash \\mathtt{true} : \\mathtt{Bool}\\ |_\\varnothing\\ \\varnothing$ & (P-True) &\n        $\\Gamma \\vdash \\mathtt{false} : \\mathtt{Bool}\\ |_\\varnothing\\ \\varnothing$ & (P-False) \\vspace{5mm} \\\\\n\n        $\\dfrac{x : T \\in \\Gamma}{\\Gamma \\vdash x : T\\ |_\\varnothing\\ \\varnothing}$ & (P-Var) &\n        $\\Gamma \\vdash z : \\mathtt{Int}\\ |_\\varnothing\\ \\varnothing$ & (P-Num) \\vspace{5mm} \\\\\n\n        $\\Gamma \\vdash\\ '() :\\ '(T)\\ |_{\\{T\\}}\\ \\varnothing$ & (P-Nil) &\n        $\\dfrac{L : \\mathcal{T}' \\in \\Gamma \\hspace{5mm} \\mathcal{T}' \\cdot \\mathcal{S} \\equiv_\\alpha \\mathcal{T}}{\\Gamma \\vdash L : \\mathcal{T}\\ |_{FV_\\mathcal{T}(\\mathcal{T})}\\ \\varnothing}$ & (P-Label0) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma \\vdash \\mathcal{P}_1 : \\mathcal{T}_1\\ |_{\\mathcal{X}_1}\\ C_1 \\land \\cdots \\land\n                    \\Gamma \\vdash \\mathcal{P}_n : \\mathcal{T}_n\\ |_{\\mathcal{X}_n}\\ C_n \\\\\n                &L : \\mathcal{T}_0' \\in \\Gamma \\hspace{5mm} \\mathcal{T}_0' \\cdot \\mathcal{S}\\equiv_\\alpha \\mathcal{T}_0 \\hspace{5mm} FV(\\mathcal{T}_0) \\cap \\mathcal{X}_1 \\cap \\cdots \\cap \\mathcal{X}_n = \\varnothing \\\\\n                &FV_\\mathcal{T}(\\mathcal{T}_0) \\cap FV_\\Gamma(\\Gamma) = \\varnothing \\hspace{5mm}\n                    \\mathcal{X} = FV(\\mathcal{T}_0) \\cup \\mathcal{X}_1 \\cup \\cdots \\cup \\mathcal{X}_n \\\\\n                &L_{1st} : T_1' \\in \\Gamma \\land \\cdots \\land L_{nth} : T_n' \\in \\Gamma \\\\\n                &C = C_1 \\cup \\cdots \\cup C_n \\cup \\{T_1' \\cdot \\mathcal{S} = \\mathcal{T}_1, \\cdots, T_n' \\cdot \\mathcal{S} = \\mathcal{T}_n\\} \\\\\n                &Size(L) = 1\\ \\mbox{for only}\\ P_{let}\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash (L\\ \\mathcal{P}_1\\ \\cdots\\ \\mathcal{P}_n) : \\mathcal{T}_0\\ |_{\\mathcal{X}}\\ C\n        }$} & (P-Label) \\vspace{5mm} \\\\\n\n        \\multicolumn{3}{r}{\n        $\\dfrac{\n            \\begin{aligned}\n                &\\Gamma \\vdash \\mathcal{P}_1 : \\mathcal{T}_1\\ |_{\\mathcal{X}_1}\\ C_1 \\land \\cdots \\land\n                    \\Gamma \\vdash \\mathcal{P}_n : \\mathcal{T}_n\\ |_{\\mathcal{X}_n}\\ C_n \\\\\n                &\\mathcal{X}_1 \\cap \\cdots \\cap \\mathcal{X}_n = \\varnothing \\hspace{5mm}\n                    \\mathcal{X} = \\mathcal{X}_1 \\cup \\cdots \\cup \\mathcal{X}_n \\hspace{5mm}\n                    C = C_1 \\cup \\cdots \\cup C_n\n            \\end{aligned}\n        }{\n            \\Gamma \\vdash [\\mathcal{P}_1\\ \\cdots\\ \\mathcal{P}_n] : [\\mathcal{T}_1 \\cdots \\mathcal{T}_n]\\ |_{\\mathcal{X}}\\ C\n        }$} & (P-Tuple) \\\\\n    \\end{tabular}\n    \\caption{Typing rule of pattern}\n\\end{figure}\n\n\\section{Typing Rule}\n\nIn this section, I will introduce the typing rule of Baremetalisp.\nBefore describing the rule, I introduce an assumption\nthat there is no variable shadowing to make it simple.\nThis means that every variable should be properly $\\alpha$-converted\nby using the De Bruijn index technique or variable shadowing should be handled\nwhen implementing the type inference algorithm.\n\nFig.~\\ref{fig:typing1} and \\ref{fig:typing2} are the typing rule of\nexpressions and function definitions.\n\n\\section{Effect}\n\\label{sec:effect}\n\n\\end{document}"
  },
  {
    "path": "src/coq.rs",
    "content": "use super::semantics as S;\nuse alloc::{\n    collections::LinkedList,\n    format,\n    string::{String, ToString},\n    vec::Vec,\n};\n\npub(crate) fn to_coq_type(\n    expr: &S::TypeExpr,\n    depth: usize,\n    targs: &mut LinkedList<String>,\n) -> String {\n    match expr {\n        S::TypeExpr::Bool(_) => \"bool\".to_string(),\n        S::TypeExpr::Int(_) => \"Z\".to_string(),\n        S::TypeExpr::String(_) => \"string\".to_string(),\n        S::TypeExpr::Char(_) => \"ascii\".to_string(),\n        S::TypeExpr::Id(e) => {\n            if let Some(c) = e.id.chars().next() {\n                if c.is_ascii_lowercase() {\n                    let mut flag = false;\n                    for s in targs.iter() {\n                        if *s == e.id {\n                            flag = true;\n                        }\n                    }\n\n                    if !flag {\n                        targs.push_back(e.id.clone());\n                    }\n                }\n            }\n            e.id.clone()\n        }\n        S::TypeExpr::Tuple(e) => {\n            if e.ty.is_empty() {\n                return \"unit\".to_string();\n            }\n\n            let mut i = 0;\n            let mut s = \"\".to_string();\n\n            for t in e.ty.iter() {\n                i += 1;\n                if i == e.ty.len() {\n                    s = format!(\"{}{}\", s, to_coq_type(t, depth + 1, targs));\n                } else {\n                    s = format!(\"{}{} * \", s, to_coq_type(t, depth + 1, targs));\n                }\n            }\n\n            if depth > 0 {\n                format!(\"({})\", s)\n            } else {\n                s\n            }\n        }\n        S::TypeExpr::List(e) => {\n            if depth == 0 {\n                format!(\"list {}\", to_coq_type(&e.ty, depth + 1, targs))\n            } else {\n                format!(\"(list {})\", to_coq_type(&e.ty, depth + 1, targs))\n            }\n        }\n        S::TypeExpr::Data(e) => {\n            if e.type_args.is_empty() {\n                e.id.id.clone()\n            } else {\n                let mut args = \"\".to_string();\n                for arg in e.type_args.iter() {\n                    args = format!(\"{}{}\", args, to_coq_type(arg, depth + 1, targs));\n                }\n\n                if depth == 0 {\n                    format!(\"{} {}\", e.id.id, args)\n                } else {\n                    format!(\"({} {})\", e.id.id, args)\n                }\n            }\n        }\n        S::TypeExpr::Fun(e) => {\n            let mut s = \"\".to_string();\n\n            // ここがおかしいかも\n            for (i, arg) in e.args.iter().enumerate() {\n                if i == 0 {\n                    s = to_coq_type(arg, depth + 1, targs);\n                } else {\n                    //s = format!(\"{} -> {}\", s, to_coq_type(arg, depth + 1, targs));\n                    s = format!(\"{} -> {}\", s, to_coq_type(arg, depth + 1, targs));\n                }\n            }\n            s = format!(\"{} -> {}\", s, to_coq_type(&e.ret, depth + 1, targs));\n\n            if depth > 0 {\n                format!(\"({})\", s)\n            } else {\n                s\n            }\n        }\n    }\n}\n\npub(crate) fn import() -> &'static str {\n    \"Require Import ZArith.\nRequire Import Coq.Lists.List.\"\n    /*\\n\n    Inductive tuple5 (A, B, C, D, E:Type): Type :=\n        | tup5 (x0: A, x1: B, x2: C, x3: D, x4: E).\n    Inductive tuple4 (A, B, C, D:Type): Type :=\n        | tup4 (x0: A, x1: B, x2: C, x3: D).\n    Inductive tuple3 (A, B, C:Type): Type :=\n        | tup3 (x0: A, x1: B, x2: C).\n    Inductive tuple2 (A, B:Type): Type :=\n        | tup2 (x0: A, x1: B).\n    Inductive tuple1 (A:Type): Type :=\n        | tup1 (x0: A).\n    Inductive tuple0 : Type :=\n        | tup0.\"*/\n}\n\npub(crate) fn to_coq_data(expr: &S::DataType) -> String {\n    let mut mem = \"\".to_string();\n    let mut i = 0;\n    for d in expr.members.iter() {\n        i += 1;\n        if i == expr.members.len() {\n            mem = format!(\"{}{}.\\n\", mem, to_coq_data_mem(d));\n        } else {\n            mem = format!(\"{}{}\\n\", mem, to_coq_data_mem(d));\n        }\n    }\n\n    if expr.members.is_empty() {\n        format!(\"Inductive {}\\n{}\", to_coq_data_def(&expr.name), mem)\n    } else {\n        let extend = inductive_arguments(expr);\n        format!(\n            \"Inductive {}\\n{}{}\\n\",\n            to_coq_data_def(&expr.name),\n            mem,\n            extend\n        )\n    }\n}\n\nfn to_coq_data_def(expr: &S::DataTypeName) -> String {\n    let mut args = \"(\".to_string();\n    let mut i = 0;\n    for t in expr.type_args.iter() {\n        i += 1;\n        if expr.type_args.len() == i {\n            args = format!(\"{}{}: Type)\", args, t.id);\n        } else {\n            args = format!(\"{}{} \", args, t.id);\n        }\n    }\n\n    if !expr.type_args.is_empty() {\n        format!(\"{} {}: Type :=\", expr.id.id, args)\n    } else {\n        format!(\"{}: Type :=\", expr.id.id)\n    }\n}\n\nfn to_coq_data_mem(expr: &S::DataTypeMem) -> String {\n    let mut mem = \"\".to_string();\n    for (i, t) in expr.types.iter().enumerate() {\n        let mut targs = LinkedList::new();\n        if expr.types.len() == i + 1 {\n            mem = format!(\"{}(x{}: {})\", mem, i, to_coq_type(t, 0, &mut targs));\n        } else {\n            mem = format!(\"{}(x{}: {}) \", mem, i, to_coq_type(t, 0, &mut targs));\n        }\n    }\n\n    if !expr.types.is_empty() {\n        format!(\"| {} {}\", expr.id.id, mem)\n    } else {\n        format!(\"| {}\", expr.id.id)\n    }\n}\n\nfn to_args_type(args: &LinkedList<String>, ty: &str) -> String {\n    let mut s = \"(\".to_string();\n    let mut i = 0;\n    for a in args {\n        i += 1;\n        if i == args.len() {\n            s = format!(\"{}{}: {})\", s, a, ty);\n        } else {\n            s = format!(\"{}{} \", s, a);\n        }\n    }\n\n    s\n}\n\nfn inductive_arguments(expr: &S::DataType) -> String {\n    let mut add_expr = \"\".to_string();\n    for t in &expr.members {\n        let mut temp = \"\".to_string();\n        for (i, _id) in expr.name.type_args.iter().enumerate() {\n            match i {\n                0 => temp = format!(\"{}{}\", temp, _id.id),\n                _ => temp = format!(\"{} {}\", temp, _id.id),\n            }\n        }\n        add_expr = format!(\"{}\\nArguments {}{{{}}}.\", add_expr, t.id.id, temp);\n    }\n    add_expr\n}\n\npub(crate) fn to_coq_func(expr: &S::Defun) -> String {\n    let head = if is_recursive(expr) {\n        format!(\"Fixpoint {}\", expr.id.id)\n    } else {\n        format!(\"Definition {}\", expr.id.id)\n    };\n\n    let fun_type = if let S::TypeExpr::Fun(e) = &expr.fun_type {\n        e\n    } else {\n        return \"\".to_string();\n    };\n\n    // transpile arguments\n    // arguments whose types are same are aggregated\n    let mut args = \"\".to_string();\n    let mut targs = LinkedList::new();\n    let mut args_list = LinkedList::new();\n    let mut prev = \"\".to_string();\n    for (arg, t) in expr.args.iter().zip(fun_type.args.iter()) {\n        let ta = to_coq_type(t, 0, &mut targs);\n        if prev.is_empty() {\n            prev = ta.clone();\n        }\n\n        if prev != ta {\n            let s = to_args_type(&args_list, &prev);\n            args = format!(\"{} {}\", args, s);\n            args_list.clear();\n            args_list.push_back(arg.id.clone());\n            prev = ta;\n        } else {\n            args_list.push_back(arg.id.clone());\n        }\n    }\n\n    let s = to_args_type(&args_list, &prev);\n    args = format!(\"{} {}\", args, s);\n\n    // transpile return type\n    let ret = to_coq_type(&fun_type.ret, 0, &mut targs);\n\n    //indent count\n    let mut tab_count = 0;\n    let tl_expr = func_analyze(&expr.expr, &mut tab_count);\n\n    // if there is no type argument, then return\n    if targs.is_empty() {\n        return format!(\"{}{}: {} :=\\n{}.\\n\", head, args, ret, tl_expr);\n    }\n\n    // transpile type arguments\n    let mut s_targs = \"{\".to_string();\n    let mut i = 0;\n    for targ in &targs {\n        i += 1;\n        if i == targs.len() {\n            s_targs = format!(\"{}{}\", s_targs, targ);\n        } else {\n            s_targs = format!(\"{}{} \", s_targs, targ);\n        }\n    }\n\n    s_targs = format!(\"{}: Type}}\", s_targs);\n\n    format!(\"{} {}{}: {} :=\\n{}.\\n\", head, s_targs, args, ret, tl_expr)\n}\n\nfn func_analyze(expr: &S::LangExpr, count: &mut i32) -> String {\n    match expr {\n        S::LangExpr::IfExpr(ex) => {\n            let mut if_expr = \"\".to_string();\n            if_expr = format!(\n                \"{}match {} with\\n\",\n                if_expr,\n                func_analyze(&ex.cond_expr, count)\n            );\n            *count += 2;\n            let tab_expr = tabb(*count);\n\n            if_expr = format!(\n                \"{}{}| true => {}\\n\",\n                if_expr,\n                tab_expr,\n                func_analyze(&ex.then_expr, count)\n            );\n            if_expr = format!(\n                \"{}{}| false => {}\\n\",\n                if_expr,\n                tab_expr,\n                func_analyze(&ex.else_expr, count)\n            );\n\n            *count -= 2;\n            format!(\"{}{}end\", if_expr, tabb(*count + 2))\n        }\n        S::LangExpr::LetExpr(ex) => {\n            let mut let_expr = \"\".to_string();\n            if ex.def_vars.is_empty() {\n                return let_expr;\n            }\n            for t in &ex.def_vars {\n                let_expr = format!(\n                    \"{}let {} = {} in\\n\",\n                    let_expr,\n                    pattern_analyze(&t.pattern),\n                    func_analyze(&t.expr, count)\n                );\n            }\n            let_expr\n        }\n        S::LangExpr::LitStr(ex) => ex.str.to_string(),\n        S::LangExpr::LitChar(ex) => ex.c.to_string(),\n        S::LangExpr::LitNum(ex) => ex.num.to_string(),\n        S::LangExpr::LitBool(ex) => ex.val.to_string(),\n        S::LangExpr::IDExpr(ex) => ex.id.to_string(),\n        S::LangExpr::DataExpr(ex) => {\n            let mut data_expr = \"\".to_string();\n            let temp: &str = &ex.label.id;\n            let temp1 = match temp {\n                \"Cons\" => \"cons\".to_string(),\n                _ => temp.to_string(),\n            };\n            data_expr = format!(\"{}({}\", data_expr, temp1);\n            if !&ex.exprs.is_empty() {\n                for t in &ex.exprs {\n                    data_expr = format!(\"{} {}\", data_expr, func_analyze(t, count));\n                }\n            }\n            format!(\"{})\", data_expr)\n        }\n        S::LangExpr::MatchExpr(ex) => {\n            let mut match_expr = \"match\".to_string();\n            match_expr = format!(\"{} {} with\", match_expr, func_analyze(&ex.expr, count));\n\n            *count += 2;\n            let tab_expr = tabb(*count);\n\n            let mut case_expr = \"\".to_string();\n            for t in &ex.cases {\n                case_expr = format!(\n                    \"{}\\n{}| {} => {}\",\n                    case_expr,\n                    tab_expr,\n                    pattern_analyze(&t.pattern),\n                    func_analyze(&t.expr, count)\n                );\n            }\n            *count -= 2;\n            format!(\"{}{}\\n{}end\", match_expr, case_expr, tabb(*count + 2))\n        }\n        S::LangExpr::ApplyExpr(ex) => {\n            let mut apply_expr = \"(\".to_string();\n            let mut store: Option<String> = None;\n            for t in &ex.exprs {\n                let temp = func_analyze(t, count);\n                match apply_arith(temp.clone()) {\n                    Some(_) => {\n                        store = apply_arith(temp);\n                    }\n                    None => {\n                        match store {\n                            Some(y) => apply_expr = format!(\"{} {} {}\", apply_expr, temp, y),\n                            None => apply_expr = format!(\"{}{} \", apply_expr, temp),\n                        }\n                        store = None;\n                    }\n                }\n            }\n            format!(\"{})\", apply_expr)\n        }\n        S::LangExpr::ListExpr(ex) => {\n            if ex.exprs.is_empty() {\n                return \"nil\".to_string();\n            }\n            let mut list_expr = \"\".to_string();\n            let mut temp = \"\".to_string();\n            for (_i, t) in ex.exprs.iter().enumerate() {\n                list_expr = format!(\"{}(cons {} \", list_expr, func_analyze(t, count));\n                temp = format!(\"{})\", temp);\n            }\n            format!(\"{}nil{}\", list_expr, temp)\n        }\n        S::LangExpr::TupleExpr(ex) => {\n            let length = &ex.exprs.len();\n            let mut tupple_expr = format!(\"tup{}\", &length);\n            match length {\n                0 => tupple_expr,\n                _ => {\n                    tupple_expr = format!(\"{} (\", tupple_expr);\n                    for t in &ex.exprs {\n                        tupple_expr = format!(\"{} {}\", tupple_expr, func_analyze(t, count));\n                    }\n                    format!(\"{})\", tupple_expr)\n                }\n            }\n        }\n        S::LangExpr::LambdaExpr(ex) => {\n            let mut lambda_expr = \"fun\".to_string();\n            if ex.args.is_empty() {\n                lambda_expr = format!(\"{} _\", lambda_expr);\n            } else {\n                for t in &ex.args {\n                    lambda_expr = format!(\"{} {}\", lambda_expr, t.id);\n                }\n            }\n            format!(\"{} => {}\", lambda_expr, func_analyze(&ex.expr, count))\n        }\n    }\n}\n\nfn pattern_analyze(pattern: &S::Pattern) -> String {\n    match pattern {\n        S::Pattern::PatStr(ex) => ex.str.to_string(),\n        S::Pattern::PatChar(ex) => ex.c.to_string(),\n        S::Pattern::PatNum(ex) => ex.num.to_string(),\n        S::Pattern::PatBool(ex) => ex.val.to_string(),\n        S::Pattern::PatID(ex) => ex.id.to_string(),\n        S::Pattern::PatTuple(ex) => {\n            let mut pattern_expr = \"\".to_string();\n            let length = &ex.pattern.len();\n            if ex.pattern.is_empty() {\n                return format!(\"{}tup{}\", pattern_expr, length);\n            }\n            pattern_expr = format!(\"{}tup{} (\", pattern_expr, length);\n            for t in &ex.pattern {\n                pattern_expr = format!(\"{} {}\", pattern_expr, pattern_analyze(t));\n            }\n            format!(\"{})\", pattern_expr)\n        }\n        S::Pattern::PatData(ex) => {\n            let mut pattern_expr = \"\".to_string();\n            let temp: &str = &ex.label.id;\n            let temp = match temp {\n                \"Cons\" => \"cons\".to_string(),\n                _ => temp.to_string(),\n            };\n            pattern_expr = format!(\"{}({}\", pattern_expr, temp);\n            for t in &ex.pattern {\n                pattern_expr = format!(\"{} {}\", pattern_expr, pattern_analyze(t));\n            }\n            format!(\"{})\", pattern_expr)\n        }\n        S::Pattern::PatNil(_) => \"_\".to_string(),\n    }\n}\n\nfn apply_arith(expr: String) -> Option<String> {\n    let temp: Vec<char> = expr.chars().collect();\n    match temp[0] {\n        '+' => Some(String::from(\"+\")),\n        '-' => Some(String::from(\"-\")),\n        '*' => Some(String::from(\"*\")),\n        '/' => Some(String::from(\"/\")),\n        '%' => Some(String::from(\"%\")),\n        _ => None,\n    }\n}\n\nfn tabb(count: i32) -> String {\n    let mut tab_expr = \"\".to_string();\n    for _ in 1..=count {\n        tab_expr = format!(\"{} \", tab_expr);\n    }\n    tab_expr\n}\n\nfn is_recursive(expr: &S::Defun) -> bool {\n    is_recursive_expr(&expr.expr, &expr.id.id)\n}\n\nfn is_recursive_expr(expr: &S::LangExpr, id: &str) -> bool {\n    match expr {\n        S::LangExpr::IfExpr(e) => {\n            is_recursive_expr(&e.cond_expr, id)\n                || is_recursive_expr(&e.then_expr, id)\n                || is_recursive_expr(&e.else_expr, id)\n        }\n        S::LangExpr::LetExpr(e) => is_recursive_expr(&e.expr, id),\n        S::LangExpr::LitStr(_) => false,\n        S::LangExpr::LitChar(_) => false,\n        S::LangExpr::LitNum(_) => false,\n        S::LangExpr::LitBool(_) => false,\n        S::LangExpr::IDExpr(e) => e.id == *id,\n        S::LangExpr::DataExpr(e) => is_recursive_exprs(&e.exprs, id),\n        S::LangExpr::MatchExpr(e) => {\n            if is_recursive_expr(&e.expr, id) {\n                return true;\n            }\n\n            for c in e.cases.iter() {\n                if is_recursive_expr(&c.expr, id) {\n                    return true;\n                }\n            }\n\n            false\n        }\n        S::LangExpr::ApplyExpr(e) => is_recursive_exprs(&e.exprs, id),\n        S::LangExpr::ListExpr(e) => is_recursive_exprs(&e.exprs, id),\n        S::LangExpr::TupleExpr(e) => is_recursive_exprs(&e.exprs, id),\n        S::LangExpr::LambdaExpr(e) => is_recursive_expr(&e.expr, id),\n    }\n}\n\nfn is_recursive_exprs(exprs: &[S::LangExpr], id: &str) -> bool {\n    for e in exprs.iter() {\n        if is_recursive_expr(e, id) {\n            return true;\n        }\n    }\n    false\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "//! # BLisp\n//!\n//! BLisp is a well typed Lisp like programming language which adopts effect\n//! system for no_std environments.\n//! BLisp supports higher order RPCs like higher order functions\n//! of functional programing languages.\n//!\n//! This repository provides only a library crate.\n//! Please see [blisp-repl](https://github.com/ytakano/blisp-repl) to use BLisp,\n//! or [baremetalisp](https://github.com/ytakano/baremetalisp) which is a toy OS.\n//!\n//! [Homepage](https://ytakano.github.io/blisp/) is here.\n//!\n//! ## Features\n//!\n//! - Algebraic data type\n//! - Generics\n//! - Hindley–Milner based type inference\n//! - Effect system to separate side effects from pure functions\n//! - Big integer\n//! - Supporting no_std environments\n//!\n//! ## Examples\n//!\n//! ### Simple Eval\n//!\n//! ```\n//! let code = \"\n//! (export factorial (n) (Pure (-> (Int) Int))\n//!     (factorial' n 1))\n//!\n//! (defun factorial' (n total) (Pure (-> (Int Int) Int))\n//!     (if (<= n 0)\n//!         total\n//!         (factorial' (- n 1) (* n total))))\";\n//!\n//! let exprs = blisp::init(code, vec![]).unwrap();\n//! let ctx = blisp::typing(exprs).unwrap();\n//! let expr = \"(factorial 10)\";\n//! for result in blisp::eval(expr, &ctx).unwrap() {\n//!    println!(\"{}\", result.unwrap());\n//! }\n//! ```\n//!\n//! ### Foreign Function Interface\n//!\n//! ```\n//! use blisp::{self, embedded};\n//! use num_bigint::BigInt;\n//!\n//! #[embedded]\n//! fn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> Result<BigInt, String> {\n//!     let mut result = a + b.0 + b.1;\n//!     if let Some(n) = c {\n//!         result += n;\n//!     }\n//!\n//!     Ok(result)\n//! }\n//!\n//! let code = \"\n//! (export call_add_four_ints (n)\n//!     (IO (-> ((Option Int)) (Result Int String)))\n//!     (add_four_ints 1 [2 3] n))\"; // call `add_four_ints` in Rust here.\n//!\n//! let exprs = blisp::init(code, vec![Box::new(AddFourInts)]).unwrap(); // extern `add_four_ints`\n//! let ctx = blisp::typing(exprs).unwrap();\n//! let result = blisp::eval(\"(call_add_four_ints (Some 4))\", &ctx).unwrap();\n//!\n//! let front = result.front().unwrap().as_ref().unwrap();\n//! assert_eq!(front, \"(Ok 10)\");\n//! ```\n//!\n//! ### Expressions\n//!\n//! ```lisp\n//! \"Hello, World!\" ; string\n//! (+ 0x10 0x20)   ; 48\n//! (+ 0b111 0b101) ; 12\n//! (+ 0o777 0o444) ; 803\n//! (car '(1 2 3))  ; (Some 1)\n//! (cdr '(1 2 3))  ; '(2 3)\n//! (map (lambda (x) (* x 2)) '(8 9 10)) ; '(16 18 20)\n//! (fold + 0 '(1 2 3 4 5 6 7 8 9))      ; 45\n//! (reverse '(1 2 3 4 5 6 7 8 9))       ; '(9 8 7 6 5 4 3 2 1)\n//! (filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9)) ; '(2 4 6 8)\n//! ```\n\n#![cfg_attr(not(test), no_std)]\n\nextern crate alloc;\n\nuse core::fmt::Display;\n\nuse alloc::{\n    boxed::Box,\n    collections::linked_list::LinkedList,\n    format,\n    string::{String, ToString},\n    vec::Vec,\n};\n\npub mod coq;\npub mod r#macro;\npub mod parser;\npub mod runtime;\npub mod semantics;\n\npub use blisp_embedded::embedded;\nuse r#macro::{process_macros, Macros};\nuse runtime::FFI;\n\n#[derive(Debug, Clone, Copy)]\npub enum FileType {\n    Prelude,\n    User,\n    Eval,\n    Extern(u64),\n}\n\n/// indicate a position of file\n#[derive(Debug, Clone, Copy)]\npub struct Pos {\n    pub file_id: FileType,\n    pub line: usize,   // line number, 0 origin\n    pub column: usize, // column number, 0 origin\n}\n\nimpl Display for Pos {\n    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n        write!(f, \"{:?}:{}:{}\", self.file_id, self.line, self.column)\n    }\n}\n\n/// error message\n#[derive(Debug)]\npub struct LispErr {\n    pub msg: String,\n    pub pos: Pos,\n}\n\nimpl LispErr {\n    fn new(msg: String, pos: Pos) -> LispErr {\n        LispErr { msg, pos }\n    }\n}\n\npub struct TypingContext {\n    exprs: LinkedList<parser::Expr>,\n    ext_funs: Vec<Box<dyn FFI + Send>>,\n    macros: Macros,\n}\n\n/// initialize BLisp with code\n///\n/// # Example\n///\n/// ```\n/// let code = \"(export factorial (n) (Pure (-> (Int) Int))\n///    (if (<= n 0)\n///        1\n///        (* n (factorial (- n 1)))))\";\n///\n/// blisp::init(code, vec![]).unwrap();\n/// ```\npub fn init(code: &str, ext_funs: Vec<Box<dyn FFI + Send>>) -> Result<TypingContext, LispErr> {\n    let prelude = include_str!(\"prelude.lisp\");\n    // let prelude = \"\";\n    let mut ps = parser::Parser::new(prelude, FileType::Prelude);\n    let mut exprs = match ps.parse() {\n        Ok(e) => e,\n        Err(e) => {\n            let msg = format!(\"Syntax Error: {}\", e.msg);\n            return Err(LispErr::new(msg, e.pos));\n        }\n    };\n\n    for (i, fun) in ext_funs.iter().enumerate() {\n        let mut ps = parser::Parser::new(fun.blisp_extern(), FileType::Extern(i as u64));\n        match ps.parse() {\n            Ok(mut e) => {\n                exprs.append(&mut e);\n            }\n            Err(e) => {\n                let msg = format!(\"Syntax Error: {}\", e.msg);\n                return Err(LispErr::new(msg, e.pos));\n            }\n        }\n    }\n\n    let mut ps = parser::Parser::new(code, FileType::User);\n    match ps.parse() {\n        Ok(mut e) => {\n            exprs.append(&mut e);\n\n            let macros = match process_macros(&mut exprs) {\n                Ok(macros) => macros,\n                Err(e) => {\n                    let msg = format!(\"Macro Error: {}\", e.msg);\n                    return Err(LispErr::new(msg, e.pos));\n                }\n            };\n\n            Ok(TypingContext {\n                exprs,\n                ext_funs,\n                macros,\n            })\n        }\n        Err(e) => {\n            let msg = format!(\"Syntax Error: {}\", e.msg);\n            Err(LispErr::new(msg, e.pos))\n        }\n    }\n}\n\n/// perform type checking and inference\n///\n/// # Example\n///\n/// ```\n/// let code = \"(export factorial (n) (Pure (-> (Int) Int))\n///    (if (<= n 0)\n///        1\n///        (* n (factorial (- n 1)))))\";\n///\n/// let exprs = blisp::init(code, vec![]).unwrap();\n/// blisp::typing(exprs).unwrap();\n/// ```\npub fn typing(exprs: TypingContext) -> Result<semantics::Context, LispErr> {\n    match semantics::exprs2context(exprs) {\n        Ok(c) => Ok(c),\n        Err(e) => {\n            let msg = format!(\"Typing Error: {}\", e.msg);\n            Err(LispErr::new(msg, e.pos))\n        }\n    }\n}\n\n/// evaluate an expression\n///\n/// # Example\n///\n/// ```\n/// let code = \"(export factorial (n) (Pure (-> (Int) Int))\n///    (if (<= n 0)\n///        1\n///        (* n (factorial (- n 1)))))\";\n///\n/// let exprs = blisp::init(code, vec![]).unwrap();\n/// let ctx = blisp::typing(exprs).unwrap();\n/// let expr = \"(factorial 30)\";\n/// for result in blisp::eval(expr, &ctx).unwrap() {\n///    println!(\"{}\", result.unwrap());\n/// }\n/// ```\npub fn eval(\n    code: &str,\n    ctx: &semantics::Context,\n) -> Result<LinkedList<Result<String, String>>, LispErr> {\n    runtime::eval(code, ctx)\n}\n\npub fn transpile(ctx: &semantics::Context) -> String {\n    let mut s = \"\".to_string();\n    for (_, d) in ctx.data.iter() {\n        s = format!(\"{}{}\\n\", s, coq::to_coq_data(d));\n    }\n\n    for (_, f) in ctx.funs.iter() {\n        s = format!(\"{}{}\\n\", s, coq::to_coq_func(f));\n    }\n\n    format!(\"{}\\n\\n{}\", coq::import(), s)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    fn eval_first(code: &str, ctx: &semantics::Context) -> String {\n        eval(code, ctx)\n            .unwrap()\n            .front()\n            .unwrap()\n            .as_ref()\n            .unwrap()\n            .clone()\n    }\n\n    #[test]\n    fn test_macro() {\n        let expr = \"\n(macro add\n    ((add $e1 $e2) (+ $e1 $e2))\n    ((add $e1 $e2 $e3 ...) (+ $e1 (add $e2 $e3 ...))))\n\n(macro minus\n    ((_ $e1 $e2) (- $e1 $e2))\n    ((_ $e1 $e2 $e3 ...) (- $e1 (minus $e2 $e3 ...))))\n\n(macro tuple_to_list\n    ((_ []) ((lambda (x) x) '()))\n    ((_ [$e ...]) ((lambda (x) x) '($e ...))))\n\n(macro none ((_ _) ([])))\n\n(tuple_to_list [])\n(tuple_to_list [1 2 3])\n\n(add 1 2 3 4 5)\n\n(defun test_add () (Pure (-> () Int))\n    (add 1 2 3 4 (minus 5 6 7) 8))\n\n(add 1)\n\n(none 123)\n\";\n\n        let typing_context = init(expr, vec![]).unwrap();\n\n        for expr in typing_context.exprs.iter() {\n            println!(\"{expr}\");\n        }\n    }\n\n    #[test]\n    fn test_macro_hygiene_lambda() {\n        let expr = \"\n(macro with_tmp\n    ((_ $x) ((lambda (tmp) (+ tmp $x)) 1)))\n\n(export test (tmp) (Pure (-> (Int) Int))\n    (with_tmp tmp))\n\";\n\n        let ctx = typing(init(expr, vec![]).unwrap()).unwrap();\n        assert_eq!(eval_first(\"(test 10)\", &ctx), \"11\");\n    }\n\n    #[test]\n    fn test_macro_hygiene_let() {\n        let expr = \"\n(macro with_tmp\n    ((_ $x) (let ((tmp 1)) (+ tmp $x))))\n\n(export test (tmp) (Pure (-> (Int) Int))\n    (with_tmp tmp))\n\";\n\n        let ctx = typing(init(expr, vec![]).unwrap()).unwrap();\n        assert_eq!(eval_first(\"(test 10)\", &ctx), \"11\");\n    }\n\n    #[test]\n    fn test_macro_hygiene_match() {\n        let expr = \"\n(macro match_some\n    ((_ $x)\n        (match (Some 1)\n            ((Some v) (+ v $x))\n            (None 0))))\n\n(export test (v) (Pure (-> (Int) Int))\n    (match_some v))\n\";\n\n        let ctx = typing(init(expr, vec![]).unwrap()).unwrap();\n        assert_eq!(eval_first(\"(test 10)\", &ctx), \"11\");\n    }\n\n    fn eval_result(code: &str, ctx: &semantics::Context) {\n        for r in eval(code, ctx).unwrap() {\n            println!(\"{} -> {}\", code, r.unwrap());\n        }\n    }\n\n    #[test]\n    fn ops() {\n        let exprs = init(\"\", vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n        eval_result(\"(neq (Some \\\"Hello\\\") 10)\", &ctx);\n        eval_result(\"(chars \\\"Hello, World!\\\")\", &ctx);\n        eval_result(\"(str '(`H` `e` `l` `l` `o`))\", &ctx);\n        eval_result(\"`\\\\``\", &ctx);\n        eval_result(\"(= `h` `h`)\", &ctx);\n        eval_result(\"(<< 8 4)\", &ctx);\n        eval_result(\"(>> 128 4)\", &ctx);\n        eval_result(\"\\\"Hello, World!\\\"\", &ctx);\n        eval_result(\"(= \\\"Hello, World!\\\" \\\"Hello, World!\\\")\", &ctx);\n        eval_result(\"(= (Some 1) (Some 2))\", &ctx);\n        eval_result(\"(< (Some 1) (Some 2))\", &ctx);\n        eval_result(\"(> (Some 1) (Some 2))\", &ctx);\n        eval_result(\"(= \\\"Hello\\\" \\\"Hel\\\")\", &ctx);\n        eval_result(\"(eq \\\"Hello\\\" 10)\", &ctx);\n        eval_result(\"(lt \\\"Hello\\\" 10)\", &ctx);\n        eval_result(\"(lt 5 10)\", &ctx);\n        eval_result(\"(+ 0x10 0x20)\", &ctx);\n        eval_result(\"(+ 0b111 0b101)\", &ctx);\n        eval_result(\"(+ 0o777 0o444)\", &ctx);\n        eval_result(\"(+ 10 20)\", &ctx);\n        eval_result(\"(pow 10 20)\", &ctx);\n        eval_result(\"(band 1 0)\", &ctx);\n        eval_result(\"(band 1 1)\", &ctx);\n        eval_result(\"(bor 1 0)\", &ctx);\n        eval_result(\"(bor 1 1)\", &ctx);\n        eval_result(\"(bxor 1 0)\", &ctx);\n        eval_result(\"(bxor 1 1)\", &ctx);\n        eval_result(\"(sqrt 16)\", &ctx);\n        eval_result(\"(sqrt -1)\", &ctx);\n    }\n\n    #[test]\n    fn lambda() {\n        let expr = \"(export lambda-test (f)\n    (Pure (-> ((Pure (-> (Int Int) Int))) Int))\n    (f 10 20))\n\";\n        let exprs = init(expr, vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n        let e = \"(lambda-test (lambda (x y) (* x y)))\";\n        eval_result(e, &ctx);\n\n        let e = \"(lambda-test +)\";\n        eval_result(e, &ctx);\n    }\n\n    #[test]\n    fn list() {\n        let expr = \"\n(export head (x) (Pure (-> ('(Int)) (Option Int)))\n    (match x\n        ((Cons n _) (Some n))\n        (_ None)))\n(export tail (x) (Pure (-> ('(Int)) (Option Int)))\n    ; match expression\n    (match x\n        (Nil None)\n        ((Cons n Nil) (Some n))\n        ((Cons _ l) (tail l))))\n\";\n        let exprs = init(expr, vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n\n        let e = \"(head '(30 40 50))\";\n        eval_result(e, &ctx);\n\n        let e = \"(tail '(30 40 50))\";\n        eval_result(e, &ctx);\n    }\n\n    #[test]\n    fn tuple() {\n        let expr = \"(export first (x) (Pure (-> ([Int Bool]) Int))\n    (match x\n        ([n _] n)))\n\";\n        let exprs = init(expr, vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n        let e = \"(first [10 false])\";\n        eval_result(e, &ctx);\n    }\n\n    #[test]\n    fn prelude() {\n        let expr = \"\n(export factorial (n) (Pure (-> (Int) Int))\n    (factorial' n 1))\n(defun factorial' (n total) (Pure (-> (Int Int) Int))\n    (if (<= n 0)\n        total\n        (factorial' (- n 1) (* n total))))\n\";\n        let exprs = init(expr, vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n\n        let e = \"(Some 10)\";\n        eval_result(e, &ctx);\n\n        let e = \"(car '(1 2 3))\";\n        eval_result(e, &ctx);\n\n        let e = \"(cdr '(1 2 3))\";\n        eval_result(e, &ctx);\n\n        let e = \"(map (lambda (x) (* x 2)) '(8 9 10))\";\n        eval_result(e, &ctx);\n\n        let e = \"(fold + 0 '(1 2 3 4 5 6 7 8 9))\";\n        eval_result(e, &ctx);\n\n        let e = \"(reverse '(1 2 3 4 5 6 7 8 9))\";\n        eval_result(e, &ctx);\n\n        let e = \"(filter (lambda (x) (= (% x 2) 0)) '(1 2 3 4 5 6 7 8 9))\";\n        eval_result(e, &ctx);\n\n        let e = \"(factorial 2000)\";\n        eval_result(e, &ctx);\n    }\n\n    #[test]\n    fn callback() {\n        let expr = \"\n(export callback (x y z) (IO (-> (Int Int Int) (Option Int)))\n    (call-rust x y z))\";\n        let exprs = init(expr, vec![]).unwrap();\n        let mut ctx = typing(exprs).unwrap();\n\n        use num_bigint::BigInt;\n        use std::boxed::Box;\n        let fun = |x: &BigInt, y: &BigInt, z: &BigInt| {\n            let n = x * y * z;\n            println!(\"n = {}\", n);\n            Some(n)\n        };\n        ctx.set_callback(Box::new(fun));\n\n        let e = \"(callback 100 2000 30000)\";\n        eval_result(e, &ctx);\n    }\n\n    #[test]\n    fn do_transpile() {\n        let expr = \"\n        (defun snoc (l y)\n        (Pure (-> (\n            '(t) t)\n        '(t)))\n        (match l\n            (nil (Cons y nil))\n            ((Cons h b) (Cons h (snoc b y)))))\n\n        (defun rev (l)\n        (Pure (-> (\n            '(t))\n        '(t)))\n        (match l\n            (nil nil)\n            ((Cons h t) (snoc (rev t) h))))\n            \";\n        let exprs = init(expr, vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n\n        println!(\"{}\", transpile(&ctx));\n    }\n\n    #[test]\n    fn test_multibyte() {\n        let expr = \"あ\";\n        let _exprs = init(expr, vec![]).unwrap();\n\n        let expr = \"\";\n        let exprs = init(expr, vec![]).unwrap();\n        let ctx = typing(exprs).unwrap();\n\n        let e = \"\\\"あ\\\"\";\n        let r = eval(e, &ctx).unwrap();\n        println!(\"{r:?}\");\n\n        let e = \"`あ`\";\n        let r = eval(e, &ctx).unwrap();\n        println!(\"{r:?}\");\n    }\n}\n"
  },
  {
    "path": "src/macro.rs",
    "content": "use crate::{parser::Expr, Pos};\nuse alloc::{\n    collections::{btree_map::Entry, BTreeMap, LinkedList},\n    format,\n    string::String,\n};\n\n#[derive(Debug)]\npub struct MacroErr {\n    pub pos: Pos,\n    pub msg: &'static str,\n}\n\n/// `e1` is a pattern and `e2` is an expression to be matched.\npub fn match_pattern(e1: &Expr, e2: &Expr, ctx: &mut BTreeMap<String, LinkedList<Expr>>) -> bool {\n    match (e1, e2) {\n        (Expr::ID(left, _), _) => {\n            if let Some('$') = left.chars().next() {\n                // If `e1` is `$id`, then a map from `$id` to `e1` is added to `ctx`.\n                let entry = ctx.entry(left.clone());\n                match entry {\n                    Entry::Vacant(ent) => {\n                        let mut list = LinkedList::new();\n                        list.push_back(e2.clone());\n                        ent.insert(list);\n\n                        true\n                    }\n                    Entry::Occupied(ent) => {\n                        let exprs = ent.get();\n                        if exprs.len() != 1 {\n                            false\n                        } else {\n                            eq_expr(exprs.front().unwrap(), e2)\n                        }\n                    }\n                }\n            } else if left == \"_\" {\n                true\n            } else {\n                matches!(e2, Expr::ID(right, _) if left == right)\n            }\n        }\n        (Expr::Bool(left, _), Expr::Bool(right, _)) => left == right,\n        (Expr::Char(left, _), Expr::Char(right, _)) => left == right,\n        (Expr::Num(left, _), Expr::Num(right, _)) => left == right,\n        (Expr::Str(left, _), Expr::Str(right, _)) => left == right,\n        (Expr::Tuple(left, _), Expr::Tuple(right, _)) => match_list(left, right, ctx),\n        (Expr::Apply(left, _), Expr::Apply(right, _)) => match_list(left, right, ctx),\n        (Expr::List(left, _), Expr::List(right, _)) => match_list(left, right, ctx),\n        _ => false,\n    }\n}\n\npub fn match_list(\n    left: &LinkedList<Expr>,\n    right: &LinkedList<Expr>,\n    ctx: &mut BTreeMap<String, LinkedList<Expr>>,\n) -> bool {\n    let mut prev = None;\n    let mut it_left = left.iter();\n    let mut it_right = right.iter();\n\n    loop {\n        match (it_left.next(), it_right.next()) {\n            (Some(e1), Some(e2)) => {\n                if let Expr::ID(id, _) = e1 {\n                    if id == \"...\" {\n                        if let Some(key) = &prev {\n                            let Some(exprs) = ctx.get_mut(key) else {\n                                return false;\n                            };\n                            exprs.push_back(e2.clone());\n                            break;\n                        }\n                    } else {\n                        prev = Some(id.clone());\n                    }\n                }\n\n                if !match_pattern(e1, e2, ctx) {\n                    return false;\n                }\n            }\n            (Some(e1), None) => {\n                if let Expr::ID(id, _) = e1 {\n                    return id == \"...\";\n                } else {\n                    return false;\n                }\n            }\n            (None, Some(_)) => return false,\n            _ => return true,\n        }\n    }\n\n    let key = prev.unwrap();\n    let exprs = ctx.get_mut(&key).unwrap();\n    for expr in it_right {\n        exprs.push_back(expr.clone());\n    }\n\n    true\n}\n\nfn eq_expr(e1: &Expr, e2: &Expr) -> bool {\n    match (e1, e2) {\n        (Expr::ID(left, _), Expr::ID(right, _)) => left == right,\n        (Expr::Bool(left, _), Expr::Bool(right, _)) => left == right,\n        (Expr::Char(left, _), Expr::Char(right, _)) => left == right,\n        (Expr::Num(left, _), Expr::Num(right, _)) => left == right,\n        (Expr::Str(left, _), Expr::Str(right, _)) => left == right,\n        (Expr::Tuple(left, _), Expr::Tuple(right, _)) => eq_exprs(left, right),\n        (Expr::Apply(left, _), Expr::Apply(right, _)) => eq_exprs(left, right),\n        (Expr::List(left, _), Expr::List(right, _)) => eq_exprs(left, right),\n        _ => false,\n    }\n}\n\nfn eq_exprs(es1: &LinkedList<Expr>, es2: &LinkedList<Expr>) -> bool {\n    if es1.len() != es2.len() {\n        return false;\n    }\n\n    es1.iter().zip(es2.iter()).all(|(e1, e2)| eq_expr(e1, e2))\n}\n\npub(crate) fn process_macros(exprs: &mut LinkedList<Expr>) -> Result<Macros, MacroErr> {\n    let macros = parse_macros(exprs)?;\n    let mut expander = MacroExpander::new(&macros);\n\n    for expr in exprs.iter_mut() {\n        expander.apply_macros(expr)?;\n    }\n\n    Ok(macros)\n}\n\npub(crate) fn apply(expr: &mut Expr, macros: &Macros) -> Result<(), MacroErr> {\n    MacroExpander::new(macros).apply_macros(expr)\n}\n\nstruct MacroExpander<'a> {\n    macros: &'a Macros,\n    fresh_counter: u64,\n}\n\nimpl<'a> MacroExpander<'a> {\n    fn new(macros: &'a Macros) -> MacroExpander<'a> {\n        MacroExpander {\n            macros,\n            fresh_counter: 0,\n        }\n    }\n\n    fn apply_macros(&mut self, expr: &mut Expr) -> Result<(), MacroErr> {\n        if let Expr::Apply(exprs, _) = expr {\n            if let Some(Expr::ID(id, _)) = exprs.front() {\n                if id == \"macro\" {\n                    return Ok(());\n                }\n            }\n        }\n\n        self.apply_macros_recursively(expr, 0)\n    }\n\n    fn apply_macros_expr(\n        &mut self,\n        pos: Pos,\n        expr: &Expr,\n        count: u8,\n    ) -> Result<Option<Expr>, MacroErr> {\n        if count == 0xff {\n            return Err(MacroErr {\n                pos,\n                msg: \"too deep macro\",\n            });\n        }\n\n        for (_, rules) in self.macros.iter() {\n            for rule in rules.iter() {\n                let mut ctx = BTreeMap::new();\n                if match_pattern(&rule.pattern, expr, &mut ctx) {\n                    let expr = self.expand(pos, &rule.template, &ctx).pop_front().unwrap();\n\n                    if let Some(e) = self.apply_macros_expr(pos, &expr, count + 1)? {\n                        return Ok(Some(e));\n                    } else {\n                        return Ok(Some(expr));\n                    }\n                }\n            }\n        }\n\n        Ok(None)\n    }\n\n    fn apply_macros_recursively(&mut self, expr: &mut Expr, count: u8) -> Result<(), MacroErr> {\n        if count == 0xff {\n            panic!(\"{}: too deep macro\", expr.get_pos());\n        }\n\n        if let Some(e) = self.apply_macros_expr(expr.get_pos(), expr, count)? {\n            *expr = e;\n        }\n\n        match expr {\n            Expr::Apply(exprs, _) | Expr::List(exprs, _) | Expr::Tuple(exprs, _) => {\n                for expr in exprs {\n                    self.apply_macros_recursively(expr, count + 1)?;\n                }\n            }\n            _ => (),\n        }\n\n        Ok(())\n    }\n\n    fn expand(\n        &mut self,\n        pos: Pos,\n        template: &Expr,\n        ctx: &BTreeMap<String, LinkedList<Expr>>,\n    ) -> LinkedList<Expr> {\n        let template = self.freshen_template(template);\n        expand_expr(pos, &template, ctx)\n    }\n\n    fn freshen_template(&mut self, template: &Expr) -> Expr {\n        let mut env = BTreeMap::new();\n        self.rename_expr(template, &mut env)\n    }\n\n    fn rename_expr(&mut self, expr: &Expr, env: &mut BTreeMap<String, String>) -> Expr {\n        match expr {\n            Expr::ID(id, pos) => {\n                if let Some(renamed) = env.get(id) {\n                    Expr::ID(renamed.clone(), *pos)\n                } else {\n                    expr.clone()\n                }\n            }\n            Expr::Bool(_, _) | Expr::Char(_, _) | Expr::Num(_, _) | Expr::Str(_, _) => expr.clone(),\n            Expr::List(exprs, pos) => Expr::List(self.rename_exprs(exprs, env), *pos),\n            Expr::Tuple(exprs, pos) => Expr::Tuple(self.rename_exprs(exprs, env), *pos),\n            Expr::Apply(exprs, pos) => {\n                let Some(head) = exprs.front() else {\n                    return expr.clone();\n                };\n\n                match head {\n                    Expr::ID(id, _) if id == \"lambda\" => self.rename_lambda(exprs, *pos, env),\n                    Expr::ID(id, _) if id == \"let\" => self.rename_let(exprs, *pos, env),\n                    Expr::ID(id, _) if id == \"match\" => self.rename_match(exprs, *pos, env),\n                    _ => Expr::Apply(self.rename_exprs(exprs, env), *pos),\n                }\n            }\n        }\n    }\n\n    fn rename_exprs(\n        &mut self,\n        exprs: &LinkedList<Expr>,\n        env: &mut BTreeMap<String, String>,\n    ) -> LinkedList<Expr> {\n        let mut result = LinkedList::new();\n\n        for expr in exprs {\n            result.push_back(self.rename_expr(expr, env));\n        }\n\n        result\n    }\n\n    fn rename_lambda(\n        &mut self,\n        exprs: &LinkedList<Expr>,\n        pos: Pos,\n        env: &mut BTreeMap<String, String>,\n    ) -> Expr {\n        let mut result = LinkedList::new();\n        let mut iter = exprs.iter();\n\n        result.push_back(iter.next().unwrap().clone());\n\n        if let Some(args) = iter.next() {\n            let mut local_env = env.clone();\n            result.push_back(self.rename_lambda_args(args, &mut local_env));\n\n            for expr in iter {\n                result.push_back(self.rename_expr(expr, &mut local_env));\n            }\n        }\n\n        Expr::Apply(result, pos)\n    }\n\n    fn rename_lambda_args(\n        &mut self,\n        args: &Expr,\n        env: &mut BTreeMap<String, String>,\n    ) -> Expr {\n        match args {\n            Expr::Apply(exprs, pos) => {\n                let mut renamed = LinkedList::new();\n                for expr in exprs {\n                    renamed.push_back(self.rename_binder(expr, env));\n                }\n                Expr::Apply(renamed, *pos)\n            }\n            _ => self.rename_expr(args, env),\n        }\n    }\n\n    fn rename_let(\n        &mut self,\n        exprs: &LinkedList<Expr>,\n        pos: Pos,\n        env: &mut BTreeMap<String, String>,\n    ) -> Expr {\n        let mut result = LinkedList::new();\n        let mut iter = exprs.iter();\n\n        result.push_back(iter.next().unwrap().clone());\n\n        let mut body_env = env.clone();\n        if let Some(bindings) = iter.next() {\n            result.push_back(self.rename_let_bindings(bindings, env, &mut body_env));\n        }\n\n        for expr in iter {\n            result.push_back(self.rename_expr(expr, &mut body_env));\n        }\n\n        Expr::Apply(result, pos)\n    }\n\n    fn rename_let_bindings(\n        &mut self,\n        bindings: &Expr,\n        env: &mut BTreeMap<String, String>,\n        body_env: &mut BTreeMap<String, String>,\n    ) -> Expr {\n        match bindings {\n            Expr::Apply(defs, pos) => {\n                let mut renamed_defs = LinkedList::new();\n\n                for def in defs {\n                    match def {\n                        Expr::Apply(def_exprs, def_pos) if def_exprs.len() == 2 => {\n                            let mut def_iter = def_exprs.iter();\n                            let pattern = def_iter.next().unwrap();\n                            let value = def_iter.next().unwrap();\n\n                            let value = self.rename_expr(value, env);\n                            let pattern = self.rename_pattern(pattern, body_env);\n\n                            let mut renamed_def = LinkedList::new();\n                            renamed_def.push_back(pattern);\n                            renamed_def.push_back(value);\n                            renamed_defs.push_back(Expr::Apply(renamed_def, *def_pos));\n                        }\n                        _ => renamed_defs.push_back(self.rename_expr(def, env)),\n                    }\n                }\n\n                Expr::Apply(renamed_defs, *pos)\n            }\n            _ => self.rename_expr(bindings, env),\n        }\n    }\n\n    fn rename_match(\n        &mut self,\n        exprs: &LinkedList<Expr>,\n        pos: Pos,\n        env: &mut BTreeMap<String, String>,\n    ) -> Expr {\n        let mut result = LinkedList::new();\n        let mut iter = exprs.iter();\n\n        result.push_back(iter.next().unwrap().clone());\n\n        if let Some(cond) = iter.next() {\n            result.push_back(self.rename_expr(cond, env));\n        }\n\n        for case in iter {\n            result.push_back(self.rename_match_case(case, env));\n        }\n\n        Expr::Apply(result, pos)\n    }\n\n    fn rename_match_case(&mut self, case: &Expr, env: &mut BTreeMap<String, String>) -> Expr {\n        match case {\n            Expr::Apply(case_exprs, pos) if case_exprs.len() == 2 => {\n                let mut iter = case_exprs.iter();\n                let pattern = iter.next().unwrap();\n                let body = iter.next().unwrap();\n\n                let mut case_env = env.clone();\n                let pattern = self.rename_pattern(pattern, &mut case_env);\n                let body = self.rename_expr(body, &mut case_env);\n\n                let mut renamed_case = LinkedList::new();\n                renamed_case.push_back(pattern);\n                renamed_case.push_back(body);\n                Expr::Apply(renamed_case, *pos)\n            }\n            _ => self.rename_expr(case, env),\n        }\n    }\n\n    fn rename_pattern(&mut self, pattern: &Expr, env: &mut BTreeMap<String, String>) -> Expr {\n        match pattern {\n            Expr::ID(_, _) => self.rename_binder(pattern, env),\n            Expr::Tuple(exprs, pos) => {\n                let mut renamed = LinkedList::new();\n                for expr in exprs {\n                    renamed.push_back(self.rename_pattern(expr, env));\n                }\n                Expr::Tuple(renamed, *pos)\n            }\n            Expr::Apply(exprs, pos) => {\n                let mut renamed = LinkedList::new();\n                let mut iter = exprs.iter();\n\n                if let Some(head) = iter.next() {\n                    renamed.push_back(self.rename_expr(head, env));\n                }\n\n                for expr in iter {\n                    renamed.push_back(self.rename_pattern(expr, env));\n                }\n\n                Expr::Apply(renamed, *pos)\n            }\n            _ => pattern.clone(),\n        }\n    }\n\n    fn rename_binder(&mut self, expr: &Expr, env: &mut BTreeMap<String, String>) -> Expr {\n        match expr {\n            Expr::ID(id, pos) => {\n                if id == \"_\" || is_pattern_var(id) {\n                    expr.clone()\n                } else {\n                    let fresh = self.fresh_name(id);\n                    env.insert(id.clone(), fresh.clone());\n                    Expr::ID(fresh, *pos)\n                }\n            }\n            _ => self.rename_expr(expr, env),\n        }\n    }\n\n    fn fresh_name(&mut self, id: &str) -> String {\n        let fresh = format!(\"__blisp_macro_{}_{}\", self.fresh_counter, id);\n        self.fresh_counter += 1;\n        fresh\n    }\n}\n\npub(crate) type Macros = BTreeMap<String, LinkedList<MacroRule>>;\n\n#[derive(Debug)]\npub(crate) struct MacroRule {\n    pattern: Expr,\n    template: Expr,\n}\n\nfn parse_macros(exprs: &LinkedList<Expr>) -> Result<Macros, MacroErr> {\n    let mut result = BTreeMap::new();\n\n    for e in exprs.iter() {\n        if let Expr::Apply(es, _) = e {\n            let mut it = es.iter();\n\n            let Some(front) = it.next() else {\n                continue;\n            };\n\n            if let Expr::ID(id_macro, _) = front {\n                if id_macro == \"macro\" {\n                    let id = it.next();\n                    let Some(Expr::ID(id, _)) = id else {\n                        return Err(MacroErr {\n                            pos: e.get_pos(),\n                            msg: \"invalid macro\",\n                        });\n                    };\n\n                    let mut rules = LinkedList::new();\n                    for rule in it {\n                        let Expr::Apply(rule_exprs, _) = rule else {\n                            return Err(MacroErr {\n                                pos: rule.get_pos(),\n                                msg: \"invalid macro rule\",\n                            });\n                        };\n\n                        if rule_exprs.len() != 2 {\n                            return Err(MacroErr {\n                                pos: rule.get_pos(),\n                                msg: \"the number of arguments of a macro rule is not 2\",\n                            });\n                        }\n\n                        let mut rule_it = rule_exprs.iter();\n\n                        let mut pattern = rule_it.next().unwrap().clone();\n                        if let Expr::Apply(arguments, _) = &mut pattern {\n                            if let Some(Expr::ID(front, _)) = arguments.front_mut() {\n                                if front == \"_\" {\n                                    *front = id.clone();\n                                } else if front != id {\n                                    return Err(MacroErr {\n                                        pos: pattern.get_pos(),\n                                        msg: \"invalid macro pattern\",\n                                    });\n                                }\n                            }\n\n                            let template = rule_it.next().unwrap().clone();\n\n                            rules.push_back(MacroRule { pattern, template });\n                        } else {\n                            return Err(MacroErr {\n                                pos: pattern.get_pos(),\n                                msg: \"invalid macro pattern\",\n                            });\n                        };\n                    }\n\n                    if let Entry::Vacant(entry) = result.entry(id.clone()) {\n                        entry.insert(rules);\n                    } else {\n                        return Err(MacroErr {\n                            pos: e.get_pos(),\n                            msg: \"multiply defined\",\n                        });\n                    }\n                }\n            }\n        }\n    }\n\n    Ok(result)\n}\n\nfn is_pattern_var(id: &str) -> bool {\n    matches!(id.chars().next(), Some('$'))\n}\n\nfn expand_expr(pos: Pos, template: &Expr, ctx: &BTreeMap<String, LinkedList<Expr>>) -> LinkedList<Expr> {\n    match template {\n        Expr::ID(id, _) => {\n            if let Some(exprs) = ctx.get(id) {\n                let expr = exprs.front().unwrap();\n                let mut result = LinkedList::new();\n                result.push_back(expr.clone());\n                result\n            } else {\n                let mut result: LinkedList<Expr> = LinkedList::new();\n                result.push_back(template.clone());\n                result\n            }\n        }\n        Expr::Apply(templates, _) => {\n            let exprs = expand_list(pos, templates, ctx);\n            let mut result = LinkedList::new();\n\n            result.push_back(Expr::Apply(exprs, pos));\n            result\n        }\n        Expr::List(templates, _) => {\n            let exprs = expand_list(pos, templates, ctx);\n            let mut result = LinkedList::new();\n            result.push_back(Expr::List(exprs, pos));\n            result\n        }\n        Expr::Tuple(templates, _) => {\n            let exprs = expand_list(pos, templates, ctx);\n            let mut result = LinkedList::new();\n            result.push_back(Expr::Tuple(exprs, pos));\n            result\n        }\n        expr => {\n            let mut result = LinkedList::new();\n            result.push_back(expr.clone());\n            result\n        }\n    }\n}\n\nfn expand_list(\n    pos: Pos,\n    templates: &LinkedList<Expr>,\n    ctx: &BTreeMap<String, LinkedList<Expr>>,\n) -> LinkedList<Expr> {\n    let mut result = LinkedList::new();\n\n    let mut prev = None;\n\n    for template in templates {\n        if let Expr::ID(id, _) = template {\n            if id == \"...\" {\n                if let Some(p) = &prev {\n                    if let Some(exprs) = ctx.get(p) {\n                        let mut it = exprs.iter();\n                        let _ = it.next();\n\n                        for expr in it {\n                            result.push_back(expr.clone());\n                        }\n                    } else {\n                        prev = None;\n                    }\n                } else {\n                    prev = None;\n                }\n\n                continue;\n            } else {\n                prev = Some(id.clone());\n            }\n        } else {\n            prev = None;\n        }\n\n        let mut exprs = expand_expr(pos, template, ctx);\n        result.append(&mut exprs);\n    }\n\n    result\n}\n"
  },
  {
    "path": "src/parser.rs",
    "content": "/*\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 | false\n * $STR   := \" string literal \"\n * $CHAR  := ' character literal '\n * $ESCC  := character * $ID    := string\n * $LIST  := '( $EXPRS )\n * $TUPLE := [ $EXPRS ]\n * $APPLY := ( $EXPRS )\n * $EXP   := $HEX | $OCT | $BIN | $NUM | $BOOL | $ID | $LIST | $TUPLE | $APPLY\n * $EXPRS := $EXP $EXPRS | ∅\n */\n\nuse super::Pos;\nuse crate::FileType;\nuse alloc::{\n    collections::linked_list::LinkedList,\n    string::{String, ToString},\n};\nuse core::{fmt::Display, usize};\nuse num_bigint::BigInt;\nuse num_traits::Zero;\n\n#[derive(Debug)]\npub struct SyntaxErr {\n    pub pos: Pos,\n    pub msg: &'static str,\n}\n\npub struct Parser<'a> {\n    pos: Pos,\n    remain: &'a str,\n}\n\n#[derive(Debug, Clone)]\npub enum Expr {\n    Str(String, Pos),\n    Char(char, Pos),\n    Num(BigInt, Pos),\n    ID(String, Pos),\n    Bool(bool, Pos),\n    List(LinkedList<Expr>, Pos),\n    Tuple(LinkedList<Expr>, Pos),\n    Apply(LinkedList<Expr>, Pos),\n}\n\nimpl Display for Expr {\n    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n        fn fmt_exprs(\n            f: &mut core::fmt::Formatter<'_>,\n            exprs: &LinkedList<Expr>,\n        ) -> core::fmt::Result {\n            for (n, expr) in exprs.iter().enumerate() {\n                if n == 0 {\n                    write!(f, \"{expr}\")?;\n                } else {\n                    write!(f, \" {expr}\")?;\n                }\n            }\n\n            Ok(())\n        }\n\n        match self {\n            Expr::Bool(val, _) => {\n                write!(f, \"{val}\")\n            }\n            Expr::Char(val, _) => {\n                write!(f, \"'{val}'\")\n            }\n            Expr::Str(val, _) => {\n                write!(f, \"\\\"{val}\\\"\")\n            }\n            Expr::Num(val, _) => {\n                write!(f, \"{val}\")\n            }\n            Expr::ID(val, _) => {\n                write!(f, \"{val}\")\n            }\n            Expr::Apply(exprs, _) => {\n                write!(f, \"(\")?;\n                fmt_exprs(f, exprs)?;\n                write!(f, \")\")\n            }\n            Expr::List(exprs, _) => {\n                write!(f, \"'(\")?;\n                fmt_exprs(f, exprs)?;\n                write!(f, \")\")\n            }\n            Expr::Tuple(exprs, _) => {\n                write!(f, \"[\")?;\n                fmt_exprs(f, exprs)?;\n                write!(f, \"]\")\n            }\n        }\n    }\n}\n\nimpl Expr {\n    pub fn get_pos(&self) -> Pos {\n        match self {\n            Expr::Char(_, pos) => *pos,\n            Expr::Num(_, pos) => *pos,\n            Expr::ID(_, pos) => *pos,\n            Expr::Bool(_, pos) => *pos,\n            Expr::List(_, pos) => *pos,\n            Expr::Tuple(_, pos) => *pos,\n            Expr::Apply(_, pos) => *pos,\n            Expr::Str(_, pos) => *pos,\n        }\n    }\n}\n\nimpl<'a> Parser<'a> {\n    pub fn new(code: &'a str, file_id: FileType) -> Parser<'a> {\n        Parser {\n            pos: Pos {\n                file_id,\n                line: 0,\n                column: 0,\n            },\n            remain: code,\n        }\n    }\n\n    pub fn parse(&mut self) -> Result<LinkedList<Expr>, SyntaxErr> {\n        let mut exprs = LinkedList::new();\n\n        loop {\n            self.skip_spaces();\n            if self.remain.is_empty() {\n                return Ok(exprs);\n            }\n\n            exprs.push_back(self.parse_expr()?);\n        }\n    }\n\n    fn parse_id_bool(&mut self) -> Result<Expr, SyntaxErr> {\n        let mut i = 0;\n\n        for s in self.remain.chars() {\n            if is_paren(s) || is_space(s) || s == ';' {\n                break;\n            }\n            i += s.to_string().len();\n        }\n\n        if i == 0 {\n            Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"unexpected EOF\",\n            })\n        } else {\n            let c = self.remain[..i].to_string();\n            self.remain = &self.remain[i..];\n            let pos = self.pos;\n            self.pos.column += i;\n\n            if c == \"true\" {\n                Ok(Expr::Bool(true, pos))\n            } else if c == \"false\" {\n                Ok(Expr::Bool(false, pos))\n            } else {\n                Ok(Expr::ID(c.to_string(), pos))\n            }\n        }\n    }\n\n    fn parse_oct(&mut self) -> Result<Expr, SyntaxErr> {\n        let mut n = Zero::zero();\n        let mut i = 0;\n\n        for c in self.remain.chars() {\n            let m = if ('0'..='7').contains(&c) {\n                c as u32 - '0' as u32\n            } else {\n                break;\n            };\n            n *= 8;\n            n += m;\n            i += 1;\n        }\n\n        if i == 0 {\n            return Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expect hexadecimal number\",\n            });\n        }\n\n        let expr = Expr::Num(n, self.pos);\n\n        self.pos.column += i;\n        self.remain = &self.remain[i..];\n\n        self.check_eof(expr)\n    }\n\n    fn parse_hex(&mut self) -> Result<Expr, SyntaxErr> {\n        let mut n = Zero::zero();\n        let mut i = 0;\n\n        for c in self.remain.chars() {\n            let m = if c.is_ascii_digit() {\n                c as u32 - '0' as u32\n            } else if ('a'..='f').contains(&c) {\n                c as u32 - 'a' as u32 + 10\n            } else if ('A'..='F').contains(&c) {\n                c as u32 - 'A' as u32 + 10\n            } else {\n                break;\n            };\n            n *= 16;\n            n += m;\n            i += 1;\n        }\n\n        if i == 0 {\n            return Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expect hexadecimal number\",\n            });\n        }\n\n        let expr = Expr::Num(n, self.pos);\n\n        self.pos.column += i;\n        self.remain = &self.remain[i..];\n\n        self.check_eof(expr)\n    }\n\n    fn check_eof(&self, expr: Expr) -> Result<Expr, SyntaxErr> {\n        if self.remain.is_empty() {\n            return Ok(expr);\n        }\n\n        match self.remain.chars().next() {\n            Some(c0) => {\n                if is_paren(c0) || is_space(c0) {\n                    Ok(expr)\n                } else {\n                    Err(SyntaxErr {\n                        pos: self.pos,\n                        msg: \"expected '(', ')', '[', ']' or space\",\n                    })\n                }\n            }\n            None => Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"unexpected EOF\",\n            }),\n        }\n    }\n\n    fn parse_binary(&mut self) -> Result<Expr, SyntaxErr> {\n        let mut n = Zero::zero();\n        let mut i = 0;\n\n        for c in self.remain.chars() {\n            let m = if c == '0' {\n                0\n            } else if c == '1' {\n                1\n            } else {\n                break;\n            };\n            n *= 2;\n            n += m;\n            i += 1;\n        }\n\n        if i == 0 {\n            return Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expect binary number\",\n            });\n        }\n\n        let expr = Expr::Num(n, self.pos);\n\n        self.pos.column += i;\n        self.remain = &self.remain[i..];\n\n        self.check_eof(expr)\n    }\n\n    fn parse_num(&mut self) -> Result<Expr, SyntaxErr> {\n        let mut i = 0;\n        let is_minus;\n\n        let mut cs = self.remain.chars();\n        let c0 = cs.next();\n        let c1 = cs.next();\n        let c = match (c0, c1) {\n            (Some('-'), _) => {\n                is_minus = true;\n                i += 1;\n                &self.remain[1..]\n            }\n            (Some('0'), Some('x')) => {\n                self.pos.column += 2;\n                self.remain = &self.remain[2..];\n                return self.parse_hex();\n            }\n            (Some('0'), Some('b')) => {\n                self.pos.column += 2;\n                self.remain = &self.remain[2..];\n                return self.parse_binary();\n            }\n            (Some('0'), Some('o')) => {\n                self.pos.column += 2;\n                self.remain = &self.remain[2..];\n                return self.parse_oct();\n            }\n            _ => {\n                is_minus = false;\n                self.remain\n            }\n        };\n\n        // parse decimal number\n        let mut n = Zero::zero();\n\n        for a in c.chars() {\n            if a.is_ascii_digit() {\n                n *= 10;\n                n += a as usize - '0' as usize;\n                i += 1;\n            } else {\n                break;\n            }\n        }\n\n        if is_minus {\n            n *= -1;\n        }\n\n        let expr = Expr::Num(n, self.pos);\n\n        self.pos.column += i;\n        self.remain = &self.remain[i..];\n\n        self.check_eof(expr)\n    }\n\n    fn skip_spaces(&mut self) {\n        let mut i = 0;\n        let mut prev = ' ';\n        let mut is_comment = false;\n        for s in self.remain.chars() {\n            if is_comment {\n                if s == '\\r' || s == '\\n' {\n                    is_comment = false;\n                } else {\n                    self.pos.column += 1;\n                    i += 1;\n                    prev = s;\n                    continue;\n                }\n            }\n\n            if s == ';' {\n                is_comment = true;\n                self.pos.column += 1;\n            } else if is_space(s) {\n                if s == '\\r' || (s == '\\n' && prev != '\\r') {\n                    self.pos.line += 1;\n                    self.pos.column = 0;\n                } else {\n                    self.pos.column += 1;\n                }\n            } else {\n                break;\n            }\n            i += 1;\n            prev = s;\n        }\n        self.remain = &self.remain[i..]\n    }\n\n    fn parse_exprs(&mut self) -> Result<LinkedList<Expr>, SyntaxErr> {\n        let mut exprs = LinkedList::<Expr>::new();\n        self.skip_spaces();\n\n        loop {\n            self.skip_spaces();\n            let c0 = self.remain.chars().next();\n            if self.remain.is_empty() || c0 == Some(')') || c0 == Some(']') {\n                break;\n            }\n            exprs.push_back(self.parse_expr()?);\n        }\n\n        Ok(exprs)\n    }\n\n    fn parse_expr(&mut self) -> Result<Expr, SyntaxErr> {\n        self.skip_spaces();\n        match self.remain.chars().next() {\n            Some('(') => self.parse_apply(),\n            Some('\\'') => self.parse_list(),\n            Some('[') => self.parse_tuple(),\n            Some('\"') => self.parse_string(),\n            Some('`') => self.parse_char(),\n            Some(a) => {\n                if a == ')' {\n                    Err(SyntaxErr {\n                        pos: self.pos,\n                        msg: \"invalid )\",\n                    })\n                } else if a.is_ascii_digit() {\n                    self.parse_num()\n                } else if a == '-' {\n                    match self.remain.chars().nth(1) {\n                        Some(b) => {\n                            if b.is_ascii_digit() {\n                                self.parse_num()\n                            } else {\n                                self.parse_id_bool()\n                            }\n                        }\n                        _ => self.parse_id_bool(),\n                    }\n                } else {\n                    self.parse_id_bool()\n                }\n            }\n            _ => Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"unexpected character\",\n            }),\n        }\n    }\n\n    fn parse_char(&mut self) -> Result<Expr, SyntaxErr> {\n        self.remain = &self.remain[1..]; // skip '`'\n        let pos = self.pos;\n        self.pos.column += 1;\n\n        if let Some(c) = self.remain.chars().next() {\n            match c {\n                '\\\\' => {\n                    if let Some(c1) = self.remain.chars().nth(1) {\n                        // TODO:\n                        //  \\x41     | 7-bit character code (exactly 2 digits, up to 0x7F)\n                        //  \\u{7FFF} | 24-bit Unicode character code (up to 6 digits)\n\n                        let esc = match c1 {\n                            'r' => '\\r',\n                            'n' => '\\n',\n                            't' => '\\t',\n                            '0' => '\\0',\n                            '\\\\' => '\\\\',\n                            '`' => '`',\n                            _ => {\n                                return Err(SyntaxErr {\n                                    pos: self.pos,\n                                    msg: \"invalid escape character\",\n                                });\n                            }\n                        };\n\n                        if let Some('`') = self.remain.chars().nth(2) {\n                            self.remain = &self.remain[3..];\n                            self.pos.column += 3;\n                            Ok(Expr::Char(esc, pos))\n                        } else {\n                            self.pos.column += 1;\n                            Err(SyntaxErr {\n                                pos: self.pos,\n                                msg: \"expected `\",\n                            })\n                        }\n                    } else {\n                        Err(SyntaxErr {\n                            pos: self.pos,\n                            msg: \"expected escape character\",\n                        })\n                    }\n                }\n                '\\r' | '\\n' => Err(SyntaxErr {\n                    pos: self.pos,\n                    msg: \"use \\\\r or \\\\n\",\n                }),\n                c => {\n                    if let Some('`') = self.remain.chars().nth(1) {\n                        self.remain = &self.remain[c.to_string().len() + 1..];\n                        self.pos.column += 2;\n                        Ok(Expr::Char(c, pos))\n                    } else {\n                        self.pos.column += 1;\n                        Err(SyntaxErr {\n                            pos: self.pos,\n                            msg: \"expected `\",\n                        })\n                    }\n                }\n            }\n        } else {\n            Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expected character literal\",\n            })\n        }\n    }\n\n    fn parse_string(&mut self) -> Result<Expr, SyntaxErr> {\n        self.remain = &self.remain[1..]; // skip '\"'\n        let pos = self.pos;\n        self.pos.column += 1;\n\n        let mut prev = ' ';\n        let mut str = \"\".to_string();\n        loop {\n            if let Some(c) = self.remain.chars().next() {\n                match c {\n                    '\"' => {\n                        self.pos.column += 1;\n                        self.remain = &self.remain[1..];\n                        break;\n                    }\n                    '\\\\' => {\n                        if let Some(c1) = self.remain.chars().nth(1) {\n                            // TODO:\n                            //  \\x41     | 7-bit character code (exactly 2 digits, up to 0x7F)\n                            //  \\u{7FFF} | 24-bit Unicode character code (up to 6 digits)\n\n                            let esc = match c1 {\n                                'r' => '\\r',\n                                'n' => '\\n',\n                                't' => '\\t',\n                                '0' => '\\0',\n                                '\\\\' => '\\\\',\n                                '\"' => '\"',\n                                _ => {\n                                    return Err(SyntaxErr {\n                                        pos: self.pos,\n                                        msg: \"invalid escape character\",\n                                    });\n                                }\n                            };\n\n                            str.push(esc);\n                            self.remain = &self.remain[2..];\n                            self.pos.column += 2;\n                            continue;\n                        } else {\n                            return Err(SyntaxErr {\n                                pos: self.pos,\n                                msg: \"expected escape character\",\n                            });\n                        }\n                    }\n                    _ => {\n                        if c == '\\r' || (c == '\\n' && prev != '\\r') {\n                            self.pos.line += 1;\n                            self.pos.column = 0;\n                        } else {\n                            self.pos.column += 1;\n                        }\n\n                        prev = c;\n                        str.push(c);\n                        self.remain = &self.remain[c.to_string().len()..];\n                    }\n                }\n            } else {\n                return Err(SyntaxErr {\n                    pos: self.pos,\n                    msg: \"string is not ended\",\n                });\n            }\n        }\n\n        Ok(Expr::Str(str, pos))\n    }\n\n    fn parse_apply(&mut self) -> Result<Expr, SyntaxErr> {\n        self.remain = &self.remain[1..]; // skip '('\n        let pos = self.pos;\n        self.pos.column += 1;\n\n        let exprs = self.parse_exprs()?;\n        if self.remain.starts_with(')') {\n            self.remain = &self.remain[1..];\n            self.pos.column += 1;\n            Ok(Expr::Apply(exprs, pos))\n        } else {\n            Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expected ')'\",\n            })\n        }\n    }\n\n    fn parse_list(&mut self) -> Result<Expr, SyntaxErr> {\n        let c = &self.remain[1..]; // skip '\\''\n        let pos = self.pos;\n        self.pos.column += 1;\n\n        match c.chars().next() {\n            Some('(') => {\n                self.remain = &c[1..];\n                let exprs = self.parse_exprs()?;\n                if self.remain.starts_with(')') {\n                    self.remain = &self.remain[1..];\n                    self.pos.column += 1;\n                    Ok(Expr::List(exprs, pos))\n                } else {\n                    Err(SyntaxErr {\n                        pos: self.pos,\n                        msg: \"expected ')'\",\n                    })\n                }\n            }\n            _ => Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expected '('\",\n            }),\n        }\n    }\n\n    fn parse_tuple(&mut self) -> Result<Expr, SyntaxErr> {\n        self.remain = &self.remain[1..]; // skip '['\n        let pos = self.pos;\n        self.pos.column += 1;\n\n        let exprs = self.parse_exprs()?;\n        if self.remain.starts_with(']') {\n            self.remain = &self.remain[1..];\n            self.pos.column += 1;\n            Ok(Expr::Tuple(exprs, pos))\n        } else {\n            Err(SyntaxErr {\n                pos: self.pos,\n                msg: \"expected ']'\",\n            })\n        }\n    }\n}\n\nfn is_space(c: char) -> bool {\n    c == ' ' || c == '\\r' || c == '\\n' || c == '\\t'\n}\n\nfn is_paren(c: char) -> bool {\n    c == '(' || c == ')' || c == '[' || c == ']'\n}\n"
  },
  {
    "path": "src/prelude.lisp",
    "content": "(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)) (Option t)))\n    (match x\n        ((Cons n _) (Some n))\n        (_ None)))\n\n(export cdr (x) (Pure (-> ('(t)) '(t)))\n    (match x\n        ((Cons _ l) l)\n        (_ '())))\n\n(export map (f x) (Pure (-> ((Pure (-> (a) b)) '(a)) '(b)))\n    (match x\n        ((Cons h l) (Cons (f h) (map f l)))\n        (_ '())))\n\n(export fold (f init x) (Pure (-> ((Pure (-> (a b) b)) b '(a)) b))\n    (match x\n        ((Cons h l) (fold f (f h init) l))\n        (_ init)))\n\n(export filter (f x)\n    (Pure (->\n        ((Pure (-> (t) Bool)) '(t))\n        '(t)))\n    (reverse (filter' f x '())))\n\n(defun filter' (f x l)\n    (Pure (-> (\n        (Pure (-> (t) Bool)) '(t) '(t))\n        '(t)))\n    (match x\n        ((Cons h a) (if (f h) (filter' f a (Cons h l)) (filter' f a l) ))\n        (_ l)))\n\n(export reverse (x) (Pure (-> ('(t)) '(t)))\n    (reverse' x '()))\n\n(defun reverse' (x l) (Pure (-> ('(t) '(t)) '(t)))\n    (match x\n        ((Cons h a) (reverse' a (Cons h l)))\n        (_ l)))\n"
  },
  {
    "path": "src/runtime.rs",
    "content": "use crate::r#macro;\n\nuse super::{parser, semantics, LispErr, Pos};\nuse alloc::{\n    boxed::Box,\n    collections::{btree_map::BTreeMap, linked_list::LinkedList, vec_deque::VecDeque},\n    format,\n    string::{String, ToString},\n    vec,\n    vec::Vec,\n};\nuse core::{\n    cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},\n    ops::{Shl, Shr},\n    pin::Pin,\n    ptr::{read_volatile, write_volatile},\n};\nuse num_bigint::BigInt;\nuse num_traits::{ToPrimitive, Zero};\n\ntype Expr = semantics::LangExpr;\ntype Pattern = semantics::Pattern;\n\nstruct RuntimeErr {\n    msg: String,\n    pos: Pos,\n}\n\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]\npub struct Variables {\n    vars: VecDeque<BTreeMap<String, RTData>>,\n}\n\nimpl Variables {\n    fn new() -> Variables {\n        let mut list = VecDeque::new();\n        list.push_back(BTreeMap::new());\n        Variables { vars: list }\n    }\n\n    fn push(&mut self) {\n        self.vars.push_back(BTreeMap::new());\n    }\n\n    fn pop(&mut self) {\n        self.vars.pop_back();\n    }\n\n    fn insert(&mut self, id: String, data: RTData) {\n        let m = self.vars.back_mut().unwrap();\n        m.insert(id, data);\n    }\n\n    fn get(&mut self, id: &str) -> Option<&RTData> {\n        for m in self.vars.iter().rev() {\n            if let Some(val) = m.get(id) {\n                return Some(val);\n            }\n        }\n        None\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]\npub enum TCall {\n    Defun(String),\n    Lambda(u64),\n}\n\n#[derive(Eq, Debug, Clone)]\npub struct IntType(*mut (BigInt, bool));\n\nimpl IntType {\n    fn get_int(&self) -> &BigInt {\n        unsafe { &(*self.0).0 }\n    }\n\n    fn get_ref(&mut self) -> &mut bool {\n        unsafe { &mut (*self.0).1 }\n    }\n}\n\nimpl Ord for IntType {\n    fn cmp(&self, other: &Self) -> Ordering {\n        let s1 = self.get_int();\n        let s2 = other.get_int();\n        s1.cmp(s2)\n    }\n}\n\nimpl PartialOrd for IntType {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        let s1 = self.get_int();\n        let s2 = other.get_int();\n        Some(s1.cmp(s2))\n    }\n}\n\nimpl PartialEq for IntType {\n    fn eq(&self, other: &Self) -> bool {\n        let s1 = self.get_int();\n        let s2 = other.get_int();\n        s1 == s2\n    }\n}\n\n#[derive(Eq, Debug, Clone)]\npub struct StrType(*mut (String, bool));\n\nimpl StrType {\n    fn get_string(&self) -> &String {\n        unsafe { &(*self.0).0 }\n    }\n\n    fn get_ref(&mut self) -> &mut bool {\n        unsafe { &mut (*self.0).1 }\n    }\n}\n\nimpl Ord for StrType {\n    fn cmp(&self, other: &Self) -> Ordering {\n        let s1 = self.get_string();\n        let s2 = other.get_string();\n        s1.cmp(s2)\n    }\n}\n\nimpl PartialOrd for StrType {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        let s1 = self.get_string();\n        let s2 = other.get_string();\n        Some(s1.cmp(s2))\n    }\n}\n\nimpl PartialEq for StrType {\n    fn eq(&self, other: &Self) -> bool {\n        let s1 = self.get_string();\n        let s2 = other.get_string();\n        s1 == s2\n    }\n}\n\n#[derive(Eq, Debug, Clone)]\npub struct ClojureType(*mut (Clojure, bool));\n\nimpl ClojureType {\n    fn get_clojure(&self) -> &Clojure {\n        unsafe { &(*self.0).0 }\n    }\n\n    fn get_clojure_mut(&mut self) -> &mut Clojure {\n        unsafe { &mut (*self.0).0 }\n    }\n\n    fn get_ref(&mut self) -> &mut bool {\n        unsafe { &mut (*self.0).1 }\n    }\n}\n\nimpl Ord for ClojureType {\n    fn cmp(&self, other: &Self) -> Ordering {\n        let s1 = self.get_clojure();\n        let s2 = other.get_clojure();\n        s1.cmp(s2)\n    }\n}\n\nimpl PartialOrd for ClojureType {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        let s1 = self.get_clojure();\n        let s2 = other.get_clojure();\n        Some(s1.cmp(s2))\n    }\n}\n\nimpl PartialEq for ClojureType {\n    fn eq(&self, other: &Self) -> bool {\n        let s1 = self.get_clojure();\n        let s2 = other.get_clojure();\n        s1 == s2\n    }\n}\n\n#[derive(Eq, Debug, Clone)]\npub struct LDataType(*mut (LabeledData, bool));\n\nimpl LDataType {\n    fn get_ldata(&self) -> &LabeledData {\n        unsafe { &(*self.0).0 }\n    }\n\n    fn get_ldata_mut(&mut self) -> &mut LabeledData {\n        unsafe { &mut (*self.0).0 }\n    }\n\n    fn get_ref(&mut self) -> &mut bool {\n        unsafe { &mut (*self.0).1 }\n    }\n}\n\nimpl Ord for LDataType {\n    fn cmp(&self, other: &Self) -> Ordering {\n        let s1 = self.get_ldata();\n        let s2 = other.get_ldata();\n        s1.cmp(s2)\n    }\n}\n\nimpl PartialOrd for LDataType {\n    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {\n        let s1 = self.get_ldata();\n        let s2 = other.get_ldata();\n        Some(s1.cmp(s2))\n    }\n}\n\nimpl PartialEq for LDataType {\n    fn eq(&self, other: &Self) -> bool {\n        let s1 = self.get_ldata();\n        let s2 = other.get_ldata();\n        s1 == s2\n    }\n}\n\n#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]\npub enum RTData {\n    Str(StrType),\n    Char(char),\n    Int(IntType),\n    Bool(bool),\n    Defun(String),\n    Lambda(ClojureType),\n    LData(LDataType),\n    TailCall(TCall, Variables),\n}\n\nfn escape_char(c: char) -> String {\n    match c {\n        '\\n' => \"\\\\n\".to_string(),\n        '\\r' => \"\\\\r\".to_string(),\n        '\\t' => \"\\\\t\".to_string(),\n        '\\0' => \"\\\\0\".to_string(),\n        _ => c.to_string(),\n    }\n}\n\nimpl RTData {\n    fn get_in_lisp(&self, list_head: bool) -> String {\n        match self {\n            RTData::Str(n) => {\n                let mut str = \"\\\"\".to_string();\n                for s in n.get_string().chars() {\n                    if s == '\"' {\n                        str.push_str(\"\\\\\\\"\");\n                    } else {\n                        str.push_str(&escape_char(s));\n                    }\n                }\n                str.push('\"');\n                str\n            }\n            RTData::Char(c) => {\n                if *c == '`' {\n                    \"`\\\\``\".to_string()\n                } else {\n                    let s = escape_char(*c);\n                    format!(\"`{}`\", s)\n                }\n            }\n            RTData::Int(n) => {\n                format!(\"{}\", n.get_int())\n            }\n            RTData::Bool(n) => n.to_string(),\n            RTData::Defun(n) => n.to_string(),\n            RTData::Lambda(n) => format!(\"(Lambda {})\", n.get_clojure().ident),\n            RTData::LData(n) => {\n                let label = &n.get_ldata().label;\n                if label == \"Cons\" {\n                    let e1;\n                    let e2;\n                    match n.get_ldata().data.as_ref() {\n                        Some(ld) => {\n                            e1 = ld[0].get_in_lisp(true);\n                            e2 = ld[1].get_in_lisp(false);\n                        }\n                        None => panic!(\"invalid list\"),\n                    }\n                    if list_head {\n                        if e2.is_empty() {\n                            format!(\"'({})\", e1)\n                        } else {\n                            format!(\"'({} {})\", e1, e2)\n                        }\n                    } else if e2.is_empty() {\n                        e1\n                    } else {\n                        format!(\"{} {}\", e1, e2)\n                    }\n                } else if label == \"Nil\" {\n                    if list_head {\n                        \"'()\".to_string()\n                    } else {\n                        \"\".to_string()\n                    }\n                } else if label == \"Tuple\" {\n                    match n.get_ldata().data.as_ref() {\n                        Some(ld) => {\n                            let mut msg = \"\".to_string();\n                            let len = (*ld).len();\n                            let mut i = 1;\n                            for d in ld.iter() {\n                                if i == len {\n                                    msg = format!(\"{}{}\", msg, d.get_in_lisp(true));\n                                } else {\n                                    msg = format!(\"{}{} \", msg, d.get_in_lisp(true));\n                                }\n                                i += 1;\n                            }\n                            format!(\"[{}]\", msg)\n                        }\n                        None => \"[]\".to_string(),\n                    }\n                } else {\n                    match n.get_ldata().data.as_ref() {\n                        Some(ld) => {\n                            let mut msg = format!(\"({}\", label);\n                            for d in ld.iter() {\n                                msg = format!(\"{} {}\", msg, d.get_in_lisp(true));\n                            }\n                            format!(\"{})\", msg)\n                        }\n                        None => label.to_string(),\n                    }\n                }\n            }\n            RTData::TailCall(TCall::Defun(f), _) => format!(\"(TailCall (Defun {}))\", f),\n            RTData::TailCall(TCall::Lambda(f), _) => format!(\"(TailCall (Lambda {}))\", f),\n        }\n    }\n}\n\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]\nstruct LabeledData {\n    label: String,\n    data: Option<Vec<RTData>>,\n}\n\n#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]\nstruct Clojure {\n    ident: u64,\n    data: Option<BTreeMap<String, RTData>>,\n}\n\nconst MIN_GC_NUM: usize = 1024;\n\n#[derive(Debug)]\npub(crate) struct RootObject {\n    objects: LinkedList<Pin<Box<(LabeledData, bool)>>>,\n    clojure: LinkedList<Pin<Box<(Clojure, bool)>>>,\n    integers: LinkedList<Pin<Box<(BigInt, bool)>>>,\n    strings: LinkedList<Pin<Box<(String, bool)>>>,\n    threshold: usize,\n}\n\nimpl RootObject {\n    fn new() -> RootObject {\n        RootObject {\n            objects: LinkedList::new(),\n            clojure: LinkedList::new(),\n            integers: LinkedList::new(),\n            strings: LinkedList::new(),\n            threshold: MIN_GC_NUM,\n        }\n    }\n\n    fn len(&self) -> usize {\n        self.objects.len() + self.clojure.len() + self.integers.len() + self.strings.len()\n    }\n\n    fn make_int(&mut self, n: BigInt) -> IntType {\n        self.integers.push_back(Box::pin((n, false)));\n        let ptr = self.integers.back_mut().unwrap();\n        IntType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (BigInt, bool) })\n    }\n\n    fn make_str(&mut self, str: String) -> StrType {\n        self.strings.push_back(Box::pin((str, false)));\n        let ptr = self.strings.back_mut().unwrap();\n        StrType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (String, bool) })\n    }\n\n    fn make_obj(&mut self, label: String, data: Option<Vec<RTData>>) -> LDataType {\n        let obj = LabeledData { label, data };\n        self.objects.push_back(Box::pin((obj, false)));\n        let ptr = self.objects.back_mut().unwrap();\n        LDataType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (LabeledData, bool) })\n    }\n\n    fn make_clojure(&mut self, ident: u64, data: Option<BTreeMap<String, RTData>>) -> ClojureType {\n        let obj = Clojure { ident, data };\n        self.clojure.push_back(Box::pin((obj, false)));\n        let ptr = self.clojure.back_mut().unwrap();\n        ClojureType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (Clojure, bool) })\n    }\n}\n\npub struct Environment<'a> {\n    pub(crate) ctx: &'a semantics::Context,\n    pub(crate) lambda: &'a BTreeMap<u64, semantics::Lambda>,\n    pub(crate) root: &'a mut RootObject,\n    pub(crate) vars: &'a mut VecDeque<Variables>,\n}\n\npub(crate) fn eval(\n    code: &str,\n    ctx: &semantics::Context,\n) -> Result<LinkedList<Result<String, String>>, LispErr> {\n    let mut ps = parser::Parser::new(code, crate::FileType::Eval);\n    let mut exprs: LinkedList<parser::Expr> = match ps.parse() {\n        Ok(e) => e,\n        Err(e) => {\n            let msg = format!(\"Syntax Error: {}\", e.msg);\n            return Err(LispErr { msg, pos: e.pos });\n        }\n    };\n\n    if let Err(e) = r#macro::process_macros(&mut exprs) {\n        let msg = format!(\"Macro Error: {}\", e.msg);\n        return Err(LispErr::new(msg, e.pos));\n    }\n\n    for expr in exprs.iter_mut() {\n        if let Err(e) = r#macro::apply(expr, &ctx.macros) {\n            let msg: String = format!(\"Macro Error: {}\", e.msg);\n            return Err(LispErr { msg, pos: e.pos });\n        }\n    }\n\n    let mut typed_exprs = LinkedList::new();\n    for expr in &exprs {\n        match semantics::typing_expr(expr, ctx) {\n            Ok(e) => {\n                typed_exprs.push_back(e);\n            }\n            Err(e) => {\n                let msg = format!(\"Typing Error: {}\", e.msg);\n                return Err(LispErr { msg, pos: e.pos });\n            }\n        }\n    }\n\n    let mut root = RootObject::new();\n    let mut result = LinkedList::new();\n    for (expr, lambda) in &typed_exprs {\n        let mut vars = VecDeque::new();\n        vars.push_back(Variables::new());\n\n        let mut env = Environment {\n            ctx,\n            lambda,\n            root: &mut root,\n            vars: &mut vars,\n        };\n\n        match eval_expr(expr, &mut env) {\n            Ok(val) => {\n                result.push_back(Ok(val.get_in_lisp(true)));\n            }\n            Err(e) => {\n                let msg = format!(\n                    \"(RuntimeErr [{} (Pos {} {})])\",\n                    e.msg, e.pos.line, e.pos.column\n                );\n                result.push_back(Err(msg));\n                return Ok(result);\n            }\n        }\n    }\n\n    Ok(result)\n}\n\nfn get_data_of_id(id: &str, vars: &mut VecDeque<Variables>) -> RTData {\n    match vars.back_mut().unwrap().get(id) {\n        Some(data) => data.clone(),\n        None => RTData::Defun(id.to_string()),\n    }\n}\n\nfn eval_expr(expr: &Expr, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    match expr {\n        Expr::LitStr(e) => Ok(RTData::Str(env.root.make_str(e.str.clone()))),\n        Expr::LitNum(e) => Ok(RTData::Int(env.root.make_int(e.num.clone()))),\n        Expr::LitChar(e) => Ok(RTData::Char(e.c)),\n        Expr::LitBool(e) => Ok(RTData::Bool(e.val)),\n        Expr::IfExpr(e) => eval_if(e, env),\n        Expr::DataExpr(e) => eval_data(e, env),\n        Expr::ListExpr(e) => eval_list(e, env),\n        Expr::LetExpr(e) => eval_let(e, env),\n        Expr::MatchExpr(e) => eval_match(e, env),\n        Expr::IDExpr(e) => Ok(eval_id(e, env.vars)),\n        Expr::ApplyExpr(e) => eval_apply(e, env),\n        Expr::TupleExpr(e) => eval_tuple(e, env),\n        Expr::LambdaExpr(e) => Ok(eval_lambda(e, env)),\n    }\n}\n\nfn eval_lambda(expr: &semantics::Lambda, env: &mut Environment<'_>) -> RTData {\n    let data = if !expr.vars.is_empty() {\n        let mut m = BTreeMap::new();\n        for v in &expr.vars {\n            m.insert(v.to_string(), get_data_of_id(v, env.vars));\n        }\n        Some(m)\n    } else {\n        None\n    };\n\n    let ptr = env.root.make_clojure(expr.ident, data);\n    RTData::Lambda(ptr)\n}\n\nfn eval_tuple(expr: &semantics::Exprs, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    let mut v = Vec::new();\n    for e in expr.exprs.iter() {\n        v.push(eval_expr(e, env)?);\n    }\n\n    let ptr = env.root.make_obj(\"Tuple\".to_string(), Some(v));\n\n    Ok(RTData::LData(ptr))\n}\n\nfn get_fun<'a>(\n    ctx: &'a semantics::Context,\n    fun_name: &str,\n    expr: &Expr,\n) -> Result<&'a semantics::Defun, RuntimeErr> {\n    let fun = match ctx.funs.get(fun_name) {\n        Some(f) => f,\n        None => {\n            let pos = expr.get_pos();\n            let msg = format!(\"{} is not defined\", fun_name);\n            return Err(RuntimeErr { msg, pos });\n        }\n    };\n\n    Ok(fun)\n}\n\nfn get_lambda<'a>(\n    ctx: &'a semantics::Context,\n    lambda: &'a BTreeMap<u64, semantics::Lambda>,\n    id: u64,\n    expr: &Expr,\n) -> Result<&'a semantics::Lambda, RuntimeErr> {\n    let fun;\n    match ctx.lambda.get(&id) {\n        Some(f) => {\n            fun = f;\n        }\n        None => match lambda.get(&id) {\n            Some(f) => {\n                fun = f;\n            }\n            None => {\n                let pos = expr.get_pos();\n                let msg = format!(\"could not find (Lambda {})\", id);\n                return Err(RuntimeErr { msg, pos });\n            }\n        },\n    }\n\n    Ok(fun)\n}\n\nfn call_lambda(\n    expr: &semantics::Apply,\n    env: &mut Environment<'_>,\n    cloj: &Clojure,\n    iter: core::slice::Iter<semantics::LangExpr>,\n    fun_expr: &semantics::LangExpr,\n) -> Result<RTData, RuntimeErr> {\n    // look up lambda\n    let ident = cloj.ident;\n    let fun = get_lambda(env.ctx, env.lambda, ident, fun_expr)?;\n\n    // set up arguments\n    let mut vars_fun = Variables::new();\n    for (e, arg) in iter.zip(fun.args.iter()) {\n        let data = eval_expr(e, env)?;\n        vars_fun.insert(arg.id.to_string(), data);\n    }\n\n    // set up free variables\n    match &cloj.data {\n        Some(d) => {\n            for (key, val) in d {\n                vars_fun.insert(key.to_string(), val.clone());\n            }\n        }\n        None => (),\n    }\n\n    // tail call optimization\n    if expr.is_tail {\n        Ok(RTData::TailCall(TCall::Lambda(ident), vars_fun))\n    } else {\n        env.vars.push_back(vars_fun);\n        let result = eval_tail_call(&fun.expr, env);\n        env.vars.pop_back();\n        result\n    }\n}\n\nfn eval_apply(expr: &semantics::Apply, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    let mut iter = expr.exprs.iter();\n    let fun_expr = match iter.next() {\n        Some(e) => e,\n        None => {\n            let pos = expr.pos;\n            return Err(RuntimeErr {\n                msg: \"empty application\".to_string(),\n                pos,\n            });\n        }\n    };\n\n    match eval_expr(fun_expr, env)? {\n        RTData::Defun(fun_name) => {\n            // call built-in function\n            if env.ctx.built_in.contains(&fun_name) {\n                let mut v = Vec::new();\n                for e in iter {\n                    let data = eval_expr(e, env)?;\n                    v.push(data);\n                }\n                return eval_built_in(fun_name, &v, expr.pos, env);\n            }\n\n            if let Some(ffi) = env.ctx.ext_ffi.get(fun_name.as_str()) {\n                let mut v = Vec::new();\n                for e in iter {\n                    let data = eval_expr(e, env)?;\n                    v.push(data);\n                }\n                return Ok(ffi(env, &v));\n            }\n\n            // look up defun\n            if let Ok(fun) = get_fun(env.ctx, &fun_name, fun_expr) {\n                // set up arguments\n                let mut vars_fun = Variables::new();\n                for (e, arg) in iter.zip(fun.args.iter()) {\n                    let data = eval_expr(e, env)?;\n                    vars_fun.insert(arg.id.to_string(), data);\n                }\n\n                // tail call optimization\n                if expr.is_tail {\n                    Ok(RTData::TailCall(TCall::Defun(fun_name), vars_fun))\n                } else {\n                    env.vars.push_back(vars_fun);\n                    let result = eval_tail_call(&fun.expr, env)?;\n                    env.vars.pop_back();\n                    Ok(result)\n                }\n            } else {\n                // call clojure\n                if let Some(RTData::Lambda(cloj)) = env.vars.back_mut().unwrap().get(&fun_name) {\n                    let c = cloj.clone();\n                    return call_lambda(expr, env, c.get_clojure(), iter, fun_expr);\n                }\n\n                // could not find such function\n                let pos = fun_expr.get_pos();\n                let msg = format!(\"{} is not defined\", fun_name);\n                Err(RuntimeErr { msg, pos })\n            }\n        }\n        RTData::Lambda(f) => {\n            let f = f.get_clojure();\n            call_lambda(expr, env, f, iter, fun_expr)\n        }\n        _ => {\n            let pos = fun_expr.get_pos();\n            Err(RuntimeErr {\n                msg: \"not function\".to_string(),\n                pos,\n            })\n        }\n    }\n}\n\nfn eval_tail_call<'a>(\n    mut expr: &'a Expr,\n    env: &'a mut Environment<'_>,\n) -> Result<RTData, RuntimeErr> {\n    loop {\n        match eval_expr(expr, env)? {\n            RTData::TailCall(TCall::Defun(fun_name), vars_fun) => {\n                let fun = get_fun(env.ctx, &fun_name, expr)?;\n                expr = &fun.expr;\n                env.vars.pop_back();\n                env.vars.push_back(vars_fun);\n                collect_garbage(env.vars, env.root); // mark and sweep\n            }\n            RTData::TailCall(TCall::Lambda(id), vars_fun) => {\n                let fun = get_lambda(env.ctx, env.lambda, id, expr)?;\n                expr = &fun.expr;\n                env.vars.pop_back();\n                env.vars.push_back(vars_fun);\n                collect_garbage(env.vars, env.root); // mark and sweep\n            }\n            x => {\n                return Ok(x);\n            }\n        }\n    }\n}\n\nfn get_int(args: &[RTData], pos: Pos) -> Result<*const BigInt, RuntimeErr> {\n    match &args[0] {\n        RTData::Int(n) => Ok(n.get_int()),\n        _ => Err(RuntimeErr {\n            msg: \"there must be exactly 2 integers\".to_string(),\n            pos,\n        }),\n    }\n}\n\nfn get_int_int(args: &[RTData], pos: Pos) -> Result<(*const BigInt, *const BigInt), RuntimeErr> {\n    match (&args[0], &args[1]) {\n        (RTData::Int(n1), RTData::Int(n2)) => Ok((n1.get_int(), n2.get_int())),\n        _ => Err(RuntimeErr {\n            msg: \"there must be exactly 2 integers\".to_string(),\n            pos,\n        }),\n    }\n}\n\nfn get_int_int_int(\n    args: &[RTData],\n    pos: Pos,\n) -> Result<(*const BigInt, *const BigInt, *const BigInt), RuntimeErr> {\n    match (&args[0], &args[1], &args[2]) {\n        (RTData::Int(n1), RTData::Int(n2), RTData::Int(n3)) => {\n            Ok((n1.get_int(), n2.get_int(), n3.get_int()))\n        }\n        _ => Err(RuntimeErr {\n            msg: \"there must be exactly 3 integers\".to_string(),\n            pos,\n        }),\n    }\n}\n\nfn get_bool_bool(args: &[RTData], pos: Pos) -> Result<(bool, bool), RuntimeErr> {\n    match (args[0].clone(), args[1].clone()) {\n        (RTData::Bool(n1), RTData::Bool(n2)) => Ok((n1, n2)),\n        _ => Err(RuntimeErr {\n            msg: \"there must be exactly 2 boolean values\".to_string(),\n            pos,\n        }),\n    }\n}\n\nfn get_bool(args: &[RTData], pos: Pos) -> Result<bool, RuntimeErr> {\n    match args[0].clone() {\n        RTData::Bool(n) => Ok(n),\n        _ => Err(RuntimeErr {\n            msg: \"there must be exactly 1 boolean value\".to_string(),\n            pos,\n        }),\n    }\n}\n\nfn eval_built_in(\n    fun_name: String,\n    args: &[RTData],\n    pos: Pos,\n    env: &mut Environment<'_>,\n) -> Result<RTData, RuntimeErr> {\n    match fun_name.as_str() {\n        \"+\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 + &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"-\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 - &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"*\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 * &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"/\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 / &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"%\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 % &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"=\" | \"eq\" => Ok(RTData::Bool(args[0] == args[1])),\n        \"!=\" | \"neq\" => Ok(RTData::Bool(args[0] != args[1])),\n        \"<=\" | \"leq\" => Ok(RTData::Bool(args[0] <= args[1])),\n        \">=\" | \"geq\" => Ok(RTData::Bool(args[0] >= args[1])),\n        \">\" | \"gt\" => Ok(RTData::Bool(args[0] > args[1])),\n        \"<\" | \"lt\" => Ok(RTData::Bool(args[0] < args[1])),\n        \"and\" => {\n            let (n1, n2) = get_bool_bool(args, pos)?;\n            Ok(RTData::Bool(n1 && n2))\n        }\n        \"or\" => {\n            let (n1, n2) = get_bool_bool(args, pos)?;\n            Ok(RTData::Bool(n1 || n2))\n        }\n        \"xor\" => {\n            let (n1, n2) = get_bool_bool(args, pos)?;\n            Ok(RTData::Bool(n1 ^ n2))\n        }\n        \"not\" => {\n            let n = get_bool(args, pos)?;\n            Ok(RTData::Bool(!n))\n        }\n        \"band\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 & &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"bor\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 | &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"bxor\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            let n = unsafe { &*n1 ^ &*n2 };\n            Ok(RTData::Int(env.root.make_int(n)))\n        }\n        \"sqrt\" => {\n            let n = get_int(args, pos)?;\n            if unsafe { (*n) >= Zero::zero() } {\n                let n = unsafe { (*n).sqrt() };\n                let n = RTData::Int(env.root.make_int(n));\n                let ptr = env.root.make_obj(\"Some\".to_string(), Some(vec![n]));\n                Ok(RTData::LData(ptr))\n            } else {\n                let ptr = env.root.make_obj(\"None\".to_string(), None);\n                Ok(RTData::LData(ptr))\n            }\n        }\n        \"pow\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            if let Some(e) = unsafe { (*n2).to_u32() } {\n                let n = unsafe { (*n1).pow(e) };\n                let n = RTData::Int(env.root.make_int(n));\n                let ptr = env.root.make_obj(\"Some\".to_string(), Some(vec![n]));\n                Ok(RTData::LData(ptr))\n            } else {\n                let ptr = env.root.make_obj(\"None\".to_string(), None);\n                Ok(RTData::LData(ptr))\n            }\n        }\n        \">>\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            if let Some(e) = unsafe { (*n2).to_u64() } {\n                let n = unsafe { (*n1).clone() };\n                let n = n.shr(e);\n                let n = RTData::Int(env.root.make_int(n));\n                let ptr = env.root.make_obj(\"Some\".to_string(), Some(vec![n]));\n                Ok(RTData::LData(ptr))\n            } else {\n                let ptr = env.root.make_obj(\"None\".to_string(), None);\n                Ok(RTData::LData(ptr))\n            }\n        }\n        \"<<\" => {\n            let (n1, n2) = get_int_int(args, pos)?;\n            if let Some(e) = unsafe { (*n2).to_u64() } {\n                let n = unsafe { (*n1).clone() };\n                let n = n.shl(e);\n                let n = RTData::Int(env.root.make_int(n));\n                let ptr = env.root.make_obj(\"Some\".to_string(), Some(vec![n]));\n                Ok(RTData::LData(ptr))\n            } else {\n                let ptr = env.root.make_obj(\"None\".to_string(), None);\n                Ok(RTData::LData(ptr))\n            }\n        }\n        \"chars\" => {\n            let mut tail = RTData::LData(env.root.make_obj(\"Nil\".to_string(), None));\n            if let RTData::Str(st) = &args[0] {\n                let s = st.get_string();\n                for c in s.chars().rev() {\n                    let c = RTData::Char(c);\n                    let cons =\n                        RTData::LData(env.root.make_obj(\"Cons\".to_string(), Some(vec![c, tail])));\n                    tail = cons;\n                }\n            }\n            Ok(tail)\n        }\n        \"str\" => {\n            let mut head = &args[0];\n            let mut s = \"\".to_string();\n            loop {\n                if let RTData::LData(data) = head {\n                    if data.get_ldata().label == \"Cons\" {\n                        if let Some(d) = &data.get_ldata().data {\n                            if let RTData::Char(c) = &d[0] {\n                                s.push(*c);\n                                head = &d[1];\n                            } else {\n                                return Err(RuntimeErr {\n                                    msg: \"not char\".to_string(),\n                                    pos,\n                                });\n                            }\n                        } else {\n                            return Err(RuntimeErr {\n                                msg: \"invalid cons\".to_string(),\n                                pos,\n                            });\n                        }\n                    } else if data.get_ldata().label == \"Nil\" {\n                        break;\n                    } else {\n                        return Err(RuntimeErr {\n                            msg: \"not list\".to_string(),\n                            pos,\n                        });\n                    }\n                }\n            }\n            let ptr = env.root.make_str(s);\n            Ok(RTData::Str(ptr))\n        }\n        \"call-rust\" => {\n            let (n1, n2, n3) = get_int_int_int(args, pos)?;\n            let n = unsafe { (env.ctx.callback)(&*n1, &*n2, &*n3) };\n            if let Some(n) = n {\n                let n = RTData::Int(env.root.make_int(n));\n                let ptr = env.root.make_obj(\"Some\".to_string(), Some(vec![n]));\n                Ok(RTData::LData(ptr))\n            } else {\n                let ptr = env.root.make_obj(\"None\".to_string(), None);\n                Ok(RTData::LData(ptr))\n            }\n        }\n        _ => Err(RuntimeErr {\n            msg: \"unknown built-in function\".to_string(),\n            pos,\n        }),\n    }\n}\n\nfn eval_match(\n    expr: &semantics::MatchNode,\n    env: &mut Environment<'_>,\n) -> Result<RTData, RuntimeErr> {\n    let data = eval_expr(&expr.expr, env)?;\n\n    for c in &expr.cases {\n        env.vars.back_mut().unwrap().push();\n        if eval_pat(&c.pattern, data.clone(), env.vars) {\n            let retval = eval_expr(&c.expr, env)?;\n            env.vars.back_mut().unwrap().pop();\n            return Ok(retval);\n        }\n        env.vars.back_mut().unwrap().pop();\n    }\n\n    let pos = expr.pos;\n    Err(RuntimeErr {\n        msg: \"pattern-matching is not exhaustive\".to_string(),\n        pos,\n    })\n}\n\nfn eval_id(expr: &semantics::IDNode, vars: &mut VecDeque<Variables>) -> RTData {\n    let id = expr.id.to_string();\n    get_data_of_id(&id, vars)\n}\n\nfn eval_list(expr: &semantics::Exprs, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    let mut elm = env.root.make_obj(\"Nil\".to_string(), None);\n    for e in expr.exprs.iter().rev() {\n        let val = eval_expr(e, env)?;\n        elm = env\n            .root\n            .make_obj(\"Cons\".to_string(), Some(vec![val, RTData::LData(elm)]));\n    }\n\n    Ok(RTData::LData(elm))\n}\n\nfn eval_if(expr: &semantics::IfNode, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    let cond = eval_expr(&expr.cond_expr, env)?;\n    let flag = match cond {\n        RTData::Bool(e) => e,\n        _ => {\n            let pos = expr.cond_expr.get_pos();\n            return Err(RuntimeErr {\n                msg: \"type mismatched\".to_string(),\n                pos,\n            });\n        }\n    };\n\n    if flag {\n        eval_expr(&expr.then_expr, env)\n    } else {\n        eval_expr(&expr.else_expr, env)\n    }\n}\n\nfn eval_data(expr: &semantics::DataNode, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    let data = if expr.exprs.is_empty() {\n        None\n    } else {\n        let mut v = Vec::new();\n        for e in &expr.exprs {\n            v.push(eval_expr(e, env)?);\n        }\n        Some(v)\n    };\n\n    let ptr = env.root.make_obj(expr.label.id.to_string(), data);\n\n    Ok(RTData::LData(ptr))\n}\n\nfn eval_let(expr: &semantics::LetNode, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {\n    env.vars.back_mut().unwrap().push();\n\n    for def in &expr.def_vars {\n        let data = eval_expr(&def.expr, env)?;\n        if !eval_pat(&def.pattern, data, env.vars) {\n            let pos = def.pattern.get_pos();\n            return Err(RuntimeErr {\n                msg: \"failed pattern matching\".to_string(),\n                pos,\n            });\n        }\n    }\n\n    let result = eval_expr(&expr.expr, env)?;\n    env.vars.back_mut().unwrap().pop();\n\n    Ok(result)\n}\n\nfn eval_pat(pat: &Pattern, data: RTData, vars: &mut VecDeque<Variables>) -> bool {\n    match pat {\n        Pattern::PatID(p) => {\n            vars.back_mut().unwrap().insert(p.id.to_string(), data);\n            true\n        }\n        Pattern::PatStr(p) => match data {\n            RTData::Str(n) => n.get_string() == &p.str,\n            _ => false,\n        },\n        Pattern::PatChar(p) => match data {\n            RTData::Char(n) => n == p.c,\n            _ => false,\n        },\n        Pattern::PatNum(p) => match data {\n            RTData::Int(n) => n.get_int() == &p.num,\n            _ => false,\n        },\n        Pattern::PatBool(p) => match data {\n            RTData::Bool(n) => n == p.val,\n            _ => false,\n        },\n        Pattern::PatNil(_) => match data {\n            RTData::LData(ptr) => ptr.get_ldata().label == \"Nil\",\n            _ => false,\n        },\n        Pattern::PatTuple(p) => match data {\n            RTData::LData(ptr) => {\n                if ptr.get_ldata().label != \"Tuple\" {\n                    return false;\n                }\n\n                match &ptr.get_ldata().data {\n                    Some(rds) => {\n                        for (pat2, rd) in p.pattern.iter().zip(rds.iter()) {\n                            if !eval_pat(pat2, rd.clone(), vars) {\n                                return false;\n                            }\n                        }\n                        true\n                    }\n                    None => true,\n                }\n            }\n            _ => false,\n        },\n        Pattern::PatData(p) => match data {\n            RTData::LData(ptr) => {\n                if ptr.get_ldata().label != p.label.id {\n                    return false;\n                }\n\n                match &ptr.get_ldata().data {\n                    Some(rds) => {\n                        for (pat2, rd) in p.pattern.iter().zip(rds.iter()) {\n                            if !eval_pat(pat2, rd.clone(), vars) {\n                                return false;\n                            }\n                        }\n                        true\n                    }\n                    None => true,\n                }\n            }\n            _ => false,\n        },\n    }\n}\n\n/// do garbage collection\nfn collect_garbage(vars: &mut VecDeque<Variables>, root: &mut RootObject) {\n    let n = root.len();\n    if n < root.threshold {\n        return;\n    }\n\n    mark(vars);\n    sweep(&mut root.clojure);\n    sweep(&mut root.objects);\n    sweep(&mut root.integers);\n    sweep(&mut root.strings);\n\n    let n = root.len();\n    root.threshold = n * 2;\n    if root.threshold < (MIN_GC_NUM >> 1) {\n        root.threshold = MIN_GC_NUM;\n    }\n}\n\n/// mark reachable objects\nfn mark(vars: &mut VecDeque<Variables>) {\n    for v in vars.iter_mut() {\n        for var in v.vars.iter_mut() {\n            for (_, v) in var.iter_mut() {\n                mark_obj(v);\n            }\n        }\n    }\n}\n\n/// mark reachable objects recursively\nfn mark_obj(data: &mut RTData) {\n    match data {\n        RTData::Str(ptr) => unsafe {\n            write_volatile(ptr.get_ref(), true);\n        },\n        RTData::Int(ptr) => unsafe {\n            write_volatile(ptr.get_ref(), true);\n        },\n        RTData::Lambda(ptr) => unsafe {\n            if !read_volatile(ptr.get_ref()) {\n                write_volatile(ptr.get_ref(), true);\n                if let Some(data) = &mut ptr.get_clojure_mut().data {\n                    for (_, v) in data.iter_mut() {\n                        mark_obj(v);\n                    }\n                }\n            }\n        },\n        RTData::LData(ptr) => unsafe {\n            if !read_volatile(ptr.get_ref()) {\n                write_volatile(ptr.get_ref(), true);\n                if let Some(data) = &mut ptr.get_ldata_mut().data {\n                    for v in data.iter_mut() {\n                        mark_obj(v);\n                    }\n                }\n            }\n        },\n        _ => (),\n    }\n}\n\n/// remove unreachable objects\nfn sweep<T>(root: &mut LinkedList<Pin<Box<(T, bool)>>>) {\n    let mut tail = root.split_off(0);\n    loop {\n        if tail.is_empty() {\n            break;\n        }\n\n        // take head\n        let mut head;\n        if tail.len() == 1 {\n            head = tail.split_off(0);\n        } else {\n            let tmp = tail.split_off(1);\n            head = tail;\n            tail = tmp;\n        };\n\n        // check the head is reachable or not\n        let h = head.front_mut().unwrap();\n        let marked = unsafe { read_volatile(&h.as_ref().1) };\n        let flag = if marked {\n            // the head is reachable\n            let h = h.as_mut();\n            unsafe {\n                h.get_unchecked_mut().1 = false;\n            }\n            true\n        } else {\n            // the head unreachable\n            false\n        };\n\n        // if reachable, append the head\n        if flag {\n            root.append(&mut head);\n        }\n    }\n}\n\npub trait RTDataToRust<T> {\n    fn into(&self) -> T;\n}\n\n/// Get a BigInt value.\nimpl RTDataToRust<BigInt> for RTData {\n    fn into(&self) -> BigInt {\n        if let RTData::Int(data) = self {\n            data.get_int().clone()\n        } else {\n            panic!(\"data is not BigInt\");\n        }\n    }\n}\n\n/// Get a char value.\nimpl RTDataToRust<char> for RTData {\n    fn into(&self) -> char {\n        if let RTData::Char(data) = self {\n            *data\n        } else {\n            panic!(\"data is not Char\");\n        }\n    }\n}\n\n/// Get a String value.\nimpl RTDataToRust<String> for RTData {\n    fn into(&self) -> String {\n        if let RTData::Str(data) = self {\n            data.get_string().clone()\n        } else {\n            panic!(\"data is not String\");\n        }\n    }\n}\n\n/// Get a boolean value.\nimpl RTDataToRust<bool> for RTData {\n    fn into(&self) -> bool {\n        if let RTData::Bool(data) = self {\n            *data\n        } else {\n            panic!(\"data is not Bool\");\n        }\n    }\n}\n\n/// Convert a BLisp's List to a Rust's Vec.\nimpl<T> RTDataToRust<Vec<T>> for RTData\nwhere\n    RTData: RTDataToRust<T>,\n{\n    fn into(&self) -> Vec<T> {\n        if let RTData::LData(data) = self {\n            let ldata = data.get_ldata();\n            let mut result = Vec::new();\n            list_to_vec(ldata, &mut result);\n\n            return result;\n        }\n\n        panic!(\"data is not List\");\n    }\n}\n\n/// Convert a BLisp's Option to a Rust's Option.\nimpl<T> RTDataToRust<Option<T>> for RTData\nwhere\n    RTData: RTDataToRust<T>,\n{\n    fn into(&self) -> Option<T> {\n        if let RTData::LData(data) = self {\n            let ldata = data.get_ldata();\n            match ldata.label.as_str() {\n                \"Some\" => {\n                    if let Some(v) = &ldata.data {\n                        let e: T = RTDataToRust::into(&v[0]);\n                        Some(e)\n                    } else {\n                        panic!(\"invalid Some\")\n                    }\n                }\n                \"None\" => None,\n                _ => panic!(\"label is neither Some nor None\"),\n            }\n        } else {\n            panic!(\"data is not Option\");\n        }\n    }\n}\n\n/// Convert a BLisp's list to a Rust's Vec.\nfn list_to_vec<T>(mut ldata: &LabeledData, result: &mut Vec<T>)\nwhere\n    RTData: RTDataToRust<T>,\n{\n    loop {\n        match ldata.label.as_str() {\n            \"Cons\" => {\n                if let Some(v) = &ldata.data {\n                    let e: T = RTDataToRust::into(&v[0]);\n                    result.push(e);\n\n                    if let RTData::LData(data) = &v[1] {\n                        ldata = data.get_ldata();\n                    } else {\n                        panic!(\"no next in Cons\")\n                    }\n                } else {\n                    panic!(\"invalid Cons\");\n                }\n            }\n            \"Nil\" => break,\n            _ => panic!(\"label is neither Cons nor Nil\"),\n        }\n    }\n}\n\n/// Convert a BLisp's Result to a Rust's Result.\nimpl<T, E> RTDataToRust<Result<T, E>> for RTData\nwhere\n    RTData: RTDataToRust<T> + RTDataToRust<E>,\n{\n    fn into(&self) -> Result<T, E> {\n        if let RTData::LData(data) = self {\n            let ldata = data.get_ldata();\n            match ldata.label.as_str() {\n                \"Ok\" => {\n                    if let Some(v) = &ldata.data {\n                        let e: T = RTDataToRust::into(&v[0]);\n                        Ok(e)\n                    } else {\n                        panic!(\"invalid Ok\")\n                    }\n                }\n                \"Err\" => {\n                    if let Some(v) = &ldata.data {\n                        let e: E = RTDataToRust::into(&v[0]);\n                        Err(e)\n                    } else {\n                        panic!(\"invalid Err\")\n                    }\n                }\n                _ => panic!(\"label is neither Ok nor Err\"),\n            }\n        } else {\n            panic!(\"data is not Result\");\n        }\n    }\n}\n\nmacro_rules! impl_rt_data_to_rust_tuple {\n    ($($(#[$impl_attrs:meta])*\n    [ $(($index:literal, $name_snake:ident, $name_pascal:ident)),+ $(,)? ]),+ $(,)?) => {\n        $($(#[$impl_attrs])*\n        impl<$($name_pascal),*> RTDataToRust<($($name_pascal),*)> for RTData\n        where $(RTData: RTDataToRust<$name_pascal>),* {\n            fn into(&self) -> ($($name_pascal),*) {\n                if let RTData::LData(data) = self {\n                    let ldata = data.get_ldata();\n                    if ldata.label.as_str() == \"Tuple\" {\n                        if let Some(v) = &ldata.data {\n                            $(let $name_snake: $name_pascal = RTDataToRust::into(&v[$index]);)*\n\n                            ($($name_snake),*)\n                        } else {\n                            panic!(\"invalid Tuple\")\n                        }\n                    } else {\n                        panic!(\"label is not Tuple\")\n                    }\n                } else {\n                    panic!(\"data is not a Tuple\")\n                }\n            }\n        })*\n    }\n}\nimpl_rt_data_to_rust_tuple![\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 2.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 3.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 4.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 5.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 6.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 7.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n        (6, v6, T6),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 8.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n        (6, v6, T6),\n        (7, v7, T7),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 9.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n        (6, v6, T6),\n        (7, v7, T7),\n        (8, v8, T8),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 10.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n        (6, v6, T6),\n        (7, v7, T7),\n        (8, v8, T8),\n        (9, v9, T9),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 11.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n        (6, v6, T6),\n        (7, v7, T7),\n        (8, v8, T8),\n        (9, v9, T9),\n        (10, v10, T10),\n    ],\n    /// Convert a BLisp's Tuple to a Rust's Tuple\n    /// where the length is 12.\n    [\n        (0, v0, T0),\n        (1, v1, T1),\n        (2, v2, T2),\n        (3, v3, T3),\n        (4, v4, T4),\n        (5, v5, T5),\n        (6, v6, T6),\n        (7, v7, T7),\n        (8, v8, T8),\n        (9, v9, T9),\n        (10, v10, T10),\n        (11, v11, T11),\n    ],\n];\n\npub trait RustToRTData<T> {\n    fn from(env: &mut Environment<'_>, value: T) -> Self;\n}\n\nimpl RustToRTData<BigInt> for RTData {\n    fn from(env: &mut Environment<'_>, value: BigInt) -> Self {\n        RTData::Int(env.root.make_int(value))\n    }\n}\n\nimpl RustToRTData<char> for RTData {\n    fn from(_env: &mut Environment<'_>, value: char) -> Self {\n        RTData::Char(value)\n    }\n}\n\nimpl RustToRTData<bool> for RTData {\n    fn from(_env: &mut Environment<'_>, value: bool) -> Self {\n        RTData::Bool(value)\n    }\n}\n\nimpl RustToRTData<String> for RTData {\n    fn from(env: &mut Environment<'_>, value: String) -> Self {\n        RTData::Str(env.root.make_str(value))\n    }\n}\n\nimpl<T> RustToRTData<Option<T>> for RTData\nwhere\n    RTData: RustToRTData<T>,\n{\n    fn from(env: &mut Environment<'_>, value: Option<T>) -> Self {\n        if let Some(value) = value {\n            let value = RustToRTData::from(env, value);\n            RTData::LData(env.root.make_obj(\"Some\".to_string(), Some(vec![value])))\n        } else {\n            RTData::LData(env.root.make_obj(\"None\".to_string(), None))\n        }\n    }\n}\n\nimpl<T, E> RustToRTData<Result<T, E>> for RTData\nwhere\n    RTData: RustToRTData<T> + RustToRTData<E>,\n{\n    fn from(env: &mut Environment<'_>, value: Result<T, E>) -> Self {\n        match value {\n            Ok(value) => {\n                let value = RustToRTData::from(env, value);\n                RTData::LData(env.root.make_obj(\"Ok\".to_string(), Some(vec![value])))\n            }\n            Err(value) => {\n                let value = RustToRTData::from(env, value);\n                RTData::LData(env.root.make_obj(\"Err\".to_string(), Some(vec![value])))\n            }\n        }\n    }\n}\n\nimpl RustToRTData<()> for RTData {\n    fn from(env: &mut Environment<'_>, _: ()) -> Self {\n        RTData::LData(env.root.make_obj(\"Tuple\".to_string(), Some(vec![])))\n    }\n}\n\nmacro_rules! impl_rust_to_rt_data_tuple {\n    ($([ $(($name_snake:ident, $name_pascal:ident)),+ $(,)? ]),+ $(,)?) => {\n        $(impl<$($name_pascal),*> RustToRTData<($($name_pascal),*)> for RTData\n        where $(RTData: RustToRTData<$name_pascal>),* {\n            fn from(env: &mut Environment<'_>, ($($name_snake),*): ($($name_pascal),*)) -> Self {\n                $(let $name_snake = <RTData as RustToRTData<$name_pascal>>::from(env, $name_snake);)*\n                RTData::LData(env.root.make_obj(\"Tuple\".to_string(), Some(vec![$($name_snake),*])))\n            }\n        })*\n    }\n}\nimpl_rust_to_rt_data_tuple![\n    [(v0, V0), (v1, V1),],\n    [(v0, V0), (v1, V1), (v2, V2),],\n    [(v0, V0), (v1, V1), (v2, V2), (v3, V3),],\n    [(v0, V0), (v1, V1), (v2, V2), (v3, V3), (v4, V4),],\n    [(v0, V0), (v1, V1), (v2, V2), (v3, V3), (v4, V4), (v5, V5),],\n    [\n        (v0, V0),\n        (v1, V1),\n        (v2, V2),\n        (v3, V3),\n        (v4, V4),\n        (v5, V5),\n        (v6, V6),\n    ],\n    [\n        (v0, V0),\n        (v1, V1),\n        (v2, V2),\n        (v3, V3),\n        (v4, V4),\n        (v5, V5),\n        (v6, V6),\n        (v7, V7),\n    ],\n    [\n        (v0, V0),\n        (v1, V1),\n        (v2, V2),\n        (v3, V3),\n        (v4, V4),\n        (v5, V5),\n        (v6, V6),\n        (v7, V7),\n        (v8, V8),\n    ],\n    [\n        (v0, V0),\n        (v1, V1),\n        (v2, V2),\n        (v3, V3),\n        (v4, V4),\n        (v5, V5),\n        (v6, V6),\n        (v7, V7),\n        (v8, V8),\n        (v9, V9),\n    ],\n    [\n        (v0, V0),\n        (v1, V1),\n        (v2, V2),\n        (v3, V3),\n        (v4, V4),\n        (v5, V5),\n        (v6, V6),\n        (v7, V7),\n        (v8, V8),\n        (v9, V9),\n        (v10, V10),\n    ],\n    [\n        (v0, V0),\n        (v1, V1),\n        (v2, V2),\n        (v3, V3),\n        (v4, V4),\n        (v5, V5),\n        (v6, V6),\n        (v7, V7),\n        (v8, V8),\n        (v9, V9),\n        (v10, V10),\n        (v11, V11),\n    ],\n];\n\nimpl<T> RustToRTData<Vec<T>> for RTData\nwhere\n    RTData: RustToRTData<T>,\n{\n    fn from(env: &mut Environment<'_>, vec: Vec<T>) -> Self {\n        Self::LData(collection_to_list(env, vec.into_iter()))\n    }\n}\nimpl<T, const N: usize> RustToRTData<[T; N]> for RTData\nwhere\n    RTData: RustToRTData<T>,\n{\n    fn from(env: &mut Environment<'_>, slice: [T; N]) -> Self {\n        Self::LData(collection_to_list(env, slice.into_iter()))\n    }\n}\n\n/// Convert a collection into a cons list.\nfn collection_to_list<I, T>(env: &mut Environment<'_>, iter: I) -> LDataType\nwhere\n    I: DoubleEndedIterator<Item = T>,\n    RTData: RustToRTData<T>,\n{\n    let mut iter = iter\n        .map(|item| {\n            (\n                \"Cons\".to_string(),\n                Some(vec![<RTData as RustToRTData<T>>::from(env, item)]),\n            )\n        })\n        .chain([(\"Nil\".to_string(), None)].into_iter())\n        .collect::<Vec<_>>()\n        .into_iter()\n        .map(|(label, data)| env.root.make_obj(label, data))\n        .rev()\n        .peekable();\n\n    let mut root_cons = None;\n    while let Some(item) = iter.next() {\n        match iter.peek_mut() {\n            Some(next) => {\n                next.get_ldata_mut()\n                    .data\n                    .as_mut()\n                    .expect(\"all items after a nil should contain a value\")\n                    .push(RTData::LData(item));\n            }\n            None => {\n                root_cons = Some(item);\n            }\n        }\n    }\n\n    root_cons.expect(\"chaining a nil should ensure that the iterator always has a value\")\n}\n\npub trait FFI {\n    /// Extern expression of BLisp\n    fn blisp_extern(&self) -> &'static str;\n\n    /// Return the corresponding FFI.\n    fn ffi(&self) -> fn(env: &mut Environment<'_>, args: &[RTData]) -> RTData;\n\n    /// The function name.\n    fn name(&self) -> &'static str;\n}\n"
  },
  {
    "path": "src/semantics.rs",
    "content": "use super::{parser, Pos};\nuse crate::{\n    r#macro::Macros,\n    runtime::{Environment, RTData},\n    TypingContext,\n};\nuse alloc::{\n    boxed::Box,\n    collections::{\n        btree_map::{self, BTreeMap},\n        btree_set::BTreeSet,\n        linked_list::LinkedList,\n    },\n    fmt, format,\n    string::{String, ToString},\n    vec,\n    vec::Vec,\n};\nuse num_bigint::BigInt;\n\ntype ID = u64;\ntype Sbst = BTreeMap<ID, Type>;\n\n#[derive(Clone, Debug)]\nenum Type {\n    TCon(Tycon),\n    TVar(ID),\n}\n\n#[derive(Clone, Debug)]\nstruct Tycon {\n    id: String,\n    args: Option<Vec<Type>>,\n}\n\nimpl fmt::Display for Type {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self {\n            Type::TCon(t) => t.fmt(f),\n            Type::TVar(id) => write!(f, \"'t{}\", id),\n        }\n    }\n}\n\nimpl fmt::Display for Tycon {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        if let Some(args) = &self.args {\n            if self.id == \"->\" {\n                let mut iter = args.iter();\n                let e = format!(\"{}\", iter.next().unwrap());\n                let args_str = format!(\"{}\", iter.next().unwrap());\n                let ret = format!(\"{}\", iter.next().unwrap());\n                write!(f, \"({} (-> {} {}))\", e, args_str, ret)\n            } else {\n                let mut s = \"\".to_string();\n                for it in args {\n                    s = format!(\"{} {}\", s, it);\n                }\n\n                if self.id == \"Arguments\" {\n                    write!(f, \"({})\", &s[1..])\n                } else {\n                    write!(f, \"({}{})\", self.id, s)\n                }\n            }\n        } else if self.id == \"Arguments\" {\n            write!(f, \"()\")\n        } else {\n            write!(f, \"{}\", self.id)\n        }\n    }\n}\n\nfn ty_bool() -> Type {\n    Type::TCon(Tycon {\n        id: \"Bool\".to_string(),\n        args: None,\n    })\n}\n\nfn ty_int() -> Type {\n    Type::TCon(Tycon {\n        id: \"Int\".to_string(),\n        args: None,\n    })\n}\n\nfn ty_string() -> Type {\n    Type::TCon(Tycon {\n        id: \"String\".to_string(),\n        args: None,\n    })\n}\n\nfn ty_char() -> Type {\n    Type::TCon(Tycon {\n        id: \"Char\".to_string(),\n        args: None,\n    })\n}\n\nfn ty_var(n: ID) -> Type {\n    Type::TVar(n)\n}\n\nfn ty_tuple(types: Vec<Type>) -> Type {\n    Type::TCon(Tycon {\n        id: \"Tuple\".to_string(),\n        args: Some(types),\n    })\n}\n\nfn ty_list(ty: Type) -> Type {\n    Type::TCon(Tycon {\n        id: \"List\".to_string(),\n        args: Some(vec![ty]),\n    })\n}\n\nfn ty_args(types: Vec<Type>) -> Type {\n    if types.is_empty() {\n        Type::TCon(Tycon {\n            id: \"Arguments\".to_string(),\n            args: None,\n        })\n    } else {\n        Type::TCon(Tycon {\n            id: \"Arguments\".to_string(),\n            args: Some(types),\n        })\n    }\n}\n\nfn ty_fun(effect: &Effect, args: Vec<Type>, ret: Type) -> Type {\n    let tuple = ty_args(args);\n    let ty_effect = match effect {\n        Effect::Pure => Type::TCon(Tycon {\n            id: \"Pure\".to_string(),\n            args: None,\n        }),\n        Effect::IO => Type::TCon(Tycon {\n            id: \"IO\".to_string(),\n            args: None,\n        }),\n    };\n    Type::TCon(Tycon {\n        id: \"->\".to_string(),\n        args: Some(vec![ty_effect, tuple, ret]),\n    })\n}\n\nfn ty_fun_gen_effect(n: ID, args: Vec<Type>, ret: Type) -> Type {\n    let tuple = ty_args(args);\n    let ty_effect = ty_var(n);\n    Type::TCon(Tycon {\n        id: \"->\".to_string(),\n        args: Some(vec![ty_effect, tuple, ret]),\n    })\n}\n\npub struct FunTypes {\n    fun_types: BTreeMap<String, LinkedList<Type>>,\n}\n\nimpl FunTypes {\n    fn new() -> FunTypes {\n        FunTypes {\n            fun_types: BTreeMap::new(),\n        }\n    }\n\n    fn insert(&mut self, key: &str, val: Type) {\n        match self.fun_types.get_mut(key) {\n            Some(list) => {\n                list.push_back(val);\n            }\n            None => {\n                let mut list = LinkedList::new();\n                list.push_back(val);\n                self.fun_types.insert(key.to_string(), list);\n            }\n        }\n    }\n\n    fn contains(&self, key: &str, val: &Type) -> bool {\n        match self.fun_types.get(key) {\n            Some(list) => {\n                for t in list {\n                    if unify(val, t).is_some() {\n                        return true;\n                    }\n                }\n                false\n            }\n            None => false,\n        }\n    }\n}\n\nstruct VarType {\n    var_stack: LinkedList<BTreeMap<String, LinkedList<Type>>>,\n}\n\nimpl VarType {\n    fn new() -> VarType {\n        let mut var_type = VarType {\n            var_stack: LinkedList::new(),\n        };\n        var_type.push();\n        var_type\n    }\n\n    fn push(&mut self) {\n        self.var_stack.push_back(BTreeMap::new());\n    }\n\n    fn pop(&mut self) {\n        self.var_stack.pop_back();\n    }\n\n    fn insert(&mut self, key: String, val: Type) {\n        match self.var_stack.back_mut() {\n            Some(m) => match m.get_mut(&key) {\n                Some(v) => {\n                    v.push_back(val);\n                }\n                None => {\n                    let mut v = LinkedList::new();\n                    v.push_back(val);\n                    m.insert(key, v);\n                }\n            },\n            None => {\n                panic!(\"failed to insert\");\n            }\n        }\n    }\n\n    fn get(&self, key: &str) -> Option<&Type> {\n        for m in self.var_stack.iter().rev() {\n            if let Some(list) = m.get(key) {\n                return list.back();\n            }\n        }\n\n        None\n    }\n}\n\n#[derive(Debug)]\npub struct TypingErr {\n    pub msg: String,\n    pub pos: Pos,\n}\n\nimpl TypingErr {\n    fn new(msg: &str, ast: &parser::Expr) -> TypingErr {\n        TypingErr {\n            msg: msg.to_string(),\n            pos: ast.get_pos(),\n        }\n    }\n}\n\n#[derive(Clone, Debug)]\npub(crate) enum LangExpr {\n    IfExpr(Box<IfNode>),\n    LetExpr(Box<LetNode>),\n    LitStr(StrNode),\n    LitChar(CharNode),\n    LitNum(NumNode),\n    LitBool(BoolNode),\n    IDExpr(IDNode),\n    DataExpr(DataNode),\n    MatchExpr(Box<MatchNode>),\n    ApplyExpr(Apply),\n    ListExpr(Exprs),\n    TupleExpr(Exprs),\n    LambdaExpr(Box<Lambda>),\n}\n\nimpl LangExpr {\n    pub(crate) fn get_pos(&self) -> Pos {\n        match self {\n            LangExpr::IfExpr(e) => e.pos,\n            LangExpr::LetExpr(e) => e.pos,\n            LangExpr::LitStr(e) => e.pos,\n            LangExpr::LitChar(e) => e.pos,\n            LangExpr::LitNum(e) => e.pos,\n            LangExpr::LitBool(e) => e.pos,\n            LangExpr::IDExpr(e) => e.pos,\n            LangExpr::DataExpr(e) => e.pos,\n            LangExpr::MatchExpr(e) => e.pos,\n            LangExpr::ApplyExpr(e) => e.pos,\n            LangExpr::ListExpr(e) => e.pos,\n            LangExpr::TupleExpr(e) => e.pos,\n            LangExpr::LambdaExpr(e) => e.pos,\n        }\n    }\n\n    fn apply_sbst(&mut self, sbst: &Sbst) {\n        let app = |opty: &Option<Type>| opty.as_ref().map(|t| t.apply_sbst(sbst));\n\n        match self {\n            LangExpr::IfExpr(e) => {\n                e.cond_expr.apply_sbst(sbst);\n                e.then_expr.apply_sbst(sbst);\n                e.else_expr.apply_sbst(sbst);\n                e.ty = app(&e.ty);\n            }\n            LangExpr::LetExpr(e) => {\n                for dv in e.def_vars.iter_mut() {\n                    dv.pattern.apply_sbst(sbst);\n                    dv.expr.apply_sbst(sbst);\n                    dv.ty = app(&dv.ty);\n                }\n                e.expr.apply_sbst(sbst);\n                e.ty = app(&e.ty);\n            }\n            LangExpr::LitStr(_)\n            | LangExpr::LitChar(_)\n            | LangExpr::LitNum(_)\n            | LangExpr::LitBool(_) => (),\n            LangExpr::IDExpr(e) => {\n                e.ty = app(&e.ty);\n            }\n            LangExpr::DataExpr(e) => {\n                for it in e.exprs.iter_mut() {\n                    it.apply_sbst(sbst);\n                }\n                e.ty = app(&e.ty);\n            }\n            LangExpr::MatchExpr(e) => {\n                e.ty = app(&e.ty);\n                e.expr.apply_sbst(sbst);\n                for cs in e.cases.iter_mut() {\n                    cs.pattern.apply_sbst(sbst);\n                    cs.expr.apply_sbst(sbst);\n                    cs.ty = app(&cs.ty);\n                }\n            }\n            LangExpr::ApplyExpr(e) => {\n                for it in e.exprs.iter_mut() {\n                    it.apply_sbst(sbst);\n                }\n                e.ty = app(&e.ty);\n            }\n            LangExpr::ListExpr(e) => {\n                for it in e.exprs.iter_mut() {\n                    it.apply_sbst(sbst);\n                }\n                e.ty = app(&e.ty);\n            }\n            LangExpr::TupleExpr(e) => {\n                for it in e.exprs.iter_mut() {\n                    it.apply_sbst(sbst);\n                }\n                e.ty = app(&e.ty);\n            }\n            LangExpr::LambdaExpr(e) => {\n                for it in e.args.iter_mut() {\n                    it.ty = app(&it.ty);\n                }\n                e.expr.apply_sbst(sbst);\n                e.ty = app(&e.ty);\n            }\n        }\n    }\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct Lambda {\n    pub(crate) args: Vec<IDNode>,\n    pub(crate) expr: LangExpr,\n    pub(crate) pos: Pos,\n    pub(crate) vars: Vec<String>,\n    pub(crate) ident: u64,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct StrNode {\n    pub(crate) str: String,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct CharNode {\n    pub(crate) c: char,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct NumNode {\n    pub(crate) num: BigInt,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct BoolNode {\n    pub(crate) val: bool,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct IDNode {\n    pub(crate) id: String,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct Extern {\n    pub(crate) id: IDNode,\n    pub(crate) fun_type: TypeExpr,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct IfNode {\n    pub(crate) cond_expr: LangExpr,\n    pub(crate) then_expr: LangExpr,\n    pub(crate) else_expr: LangExpr,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct LetNode {\n    pub(crate) def_vars: Vec<DefVar>,\n    pub(crate) expr: LangExpr,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct DefVar {\n    pub(crate) pattern: Pattern,\n    pub(crate) expr: LangExpr,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct MatchNode {\n    pub(crate) expr: LangExpr,\n    pub(crate) cases: Vec<MatchCase>,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct DataNode {\n    pub(crate) label: TIDNode,\n    pub(crate) exprs: Vec<LangExpr>,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) enum Pattern {\n    PatStr(StrNode),\n    PatChar(CharNode),\n    PatNum(NumNode),\n    PatBool(BoolNode),\n    PatID(IDNode),\n    PatTuple(PatTupleNode),\n    PatData(PatDataNode),\n    PatNil(PatNilNode),\n}\n\nimpl Pattern {\n    pub(crate) fn get_pos(&self) -> Pos {\n        match self {\n            Pattern::PatStr(e) => e.pos,\n            Pattern::PatChar(e) => e.pos,\n            Pattern::PatNum(e) => e.pos,\n            Pattern::PatBool(e) => e.pos,\n            Pattern::PatID(e) => e.pos,\n            Pattern::PatTuple(e) => e.pos,\n            Pattern::PatData(e) => e.pos,\n            Pattern::PatNil(e) => e.pos,\n        }\n    }\n\n    fn get_type(&self) -> &Option<Type> {\n        match self {\n            Pattern::PatStr(e) => &e.ty,\n            Pattern::PatChar(e) => &e.ty,\n            Pattern::PatNum(e) => &e.ty,\n            Pattern::PatBool(e) => &e.ty,\n            Pattern::PatID(e) => &e.ty,\n            Pattern::PatTuple(e) => &e.ty,\n            Pattern::PatData(e) => &e.ty,\n            Pattern::PatNil(e) => &e.ty,\n        }\n    }\n\n    fn apply_sbst(&mut self, sbst: &Sbst) {\n        let app = |opty: &Option<Type>| opty.as_ref().map(|t| t.apply_sbst(sbst));\n\n        match self {\n            Pattern::PatID(e) => {\n                e.ty = app(&e.ty);\n            }\n            Pattern::PatTuple(e) => {\n                for pat in e.pattern.iter_mut() {\n                    pat.apply_sbst(sbst);\n                }\n                e.ty = app(&e.ty);\n            }\n            Pattern::PatData(e) => {\n                for pat in e.pattern.iter_mut() {\n                    pat.apply_sbst(sbst);\n                }\n                e.ty = app(&e.ty);\n            }\n            Pattern::PatNil(e) => {\n                e.ty = app(&e.ty);\n            }\n            _ => (),\n        }\n    }\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct PatTupleNode {\n    pub(crate) pattern: Vec<Pattern>,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct PatDataNode {\n    pub(crate) label: TIDNode,\n    pub(crate) pattern: Vec<Pattern>,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct PatNilNode {\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct MatchCase {\n    pub(crate) pattern: Pattern,\n    pub(crate) expr: LangExpr,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct Apply {\n    pub(crate) exprs: Vec<LangExpr>,\n    pub(crate) pos: Pos,\n    pub(crate) is_tail: bool,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct Exprs {\n    pub(crate) exprs: Vec<LangExpr>,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct TIDNode {\n    pub(crate) id: String,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct TEBoolNode;\n\n#[derive(Clone, Debug)]\npub(crate) struct TEIntNode;\n\n#[derive(Clone, Debug)]\npub(crate) struct TEStringNode;\n\n#[derive(Clone, Debug)]\npub(crate) struct TECharNode;\n\n#[derive(Clone, Debug)]\npub(crate) struct DataType {\n    pub(crate) name: DataTypeName,\n    pub(crate) members: Vec<DataTypeMem>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct DataTypeName {\n    pub(crate) id: TIDNode,\n    pub(crate) type_args: Vec<IDNode>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct DataTypeMem {\n    pub(crate) id: TIDNode,\n    pub(crate) types: Vec<TypeExpr>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) enum TypeExpr {\n    Bool(TEBoolNode),\n    Int(TEIntNode),\n    String(TEStringNode),\n    Char(TECharNode),\n    List(TEListNode),\n    Tuple(TETupleNode),\n    Fun(TEFunNode),\n    Data(TEDataNode),\n    Id(IDNode),\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct TEListNode {\n    pub(crate) ty: Box<TypeExpr>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct TETupleNode {\n    pub(crate) ty: Vec<TypeExpr>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\nenum Effect {\n    IO,\n    Pure,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct TEFunNode {\n    effect: Effect,\n    pub(crate) args: Vec<TypeExpr>,\n    pub(crate) ret: Box<TypeExpr>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct TEDataNode {\n    pub(crate) id: TIDNode,\n    pub(crate) type_args: Vec<TypeExpr>,\n    pub(crate) pos: Pos,\n}\n\n#[derive(Clone, Debug)]\npub(crate) struct Defun {\n    exported: bool,\n    pub(crate) id: IDNode,\n    pub(crate) args: Vec<IDNode>,\n    pub(crate) fun_type: TypeExpr,\n    effect: Effect,\n    pub(crate) expr: LangExpr,\n    pub(crate) pos: Pos,\n    ty: Option<Type>,\n}\n\ntrait TApp: Sized {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<Self, TypingErr>;\n}\n\nimpl TApp for DataType {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<DataType, TypingErr> {\n        let mut mems = Vec::new();\n        for m in self.members.iter() {\n            mems.push(m.apply(ty)?);\n        }\n\n        Ok(DataType {\n            name: self.name.clone(),\n            members: mems,\n            pos: self.pos,\n        })\n    }\n}\n\nimpl TApp for DataTypeMem {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<DataTypeMem, TypingErr> {\n        let mut v = Vec::new();\n        for it in self.types.iter() {\n            v.push(it.apply(ty)?);\n        }\n\n        Ok(DataTypeMem {\n            id: self.id.clone(),\n            types: v,\n            pos: self.pos,\n        })\n    }\n}\n\nimpl TApp for TypeExpr {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TypeExpr, TypingErr> {\n        match self {\n            TypeExpr::Data(data) => Ok(TypeExpr::Data(data.apply(ty)?)),\n            TypeExpr::List(list) => Ok(TypeExpr::List(list.apply(ty)?)),\n            TypeExpr::Tuple(tuple) => Ok(TypeExpr::Tuple(tuple.apply(ty)?)),\n            TypeExpr::Fun(fun) => Ok(TypeExpr::Fun(fun.apply(ty)?)),\n            TypeExpr::Id(id) => match ty.get(&id.id) {\n                Some(t) => Ok(t.clone()),\n                _ => Ok(TypeExpr::Id(id.clone())),\n            },\n            _ => Ok(self.clone()),\n        }\n    }\n}\n\nimpl TApp for TEListNode {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TEListNode, TypingErr> {\n        Ok(TEListNode {\n            ty: Box::new(self.ty.apply(ty)?),\n            pos: self.pos,\n        })\n    }\n}\n\nimpl TApp for TETupleNode {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TETupleNode, TypingErr> {\n        let mut v = Vec::new();\n        for it in self.ty.iter() {\n            v.push(it.apply(ty)?);\n        }\n\n        Ok(TETupleNode {\n            ty: v,\n            pos: self.pos,\n        })\n    }\n}\n\nimpl TApp for TEFunNode {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TEFunNode, TypingErr> {\n        let mut v = Vec::new();\n        for it in self.args.iter() {\n            v.push(it.apply(ty)?);\n        }\n\n        Ok(TEFunNode {\n            effect: self.effect.clone(),\n            args: v,\n            ret: Box::new(self.ret.apply(ty)?),\n            pos: self.pos,\n        })\n    }\n}\n\nimpl TApp for TEDataNode {\n    fn apply(&self, ty: &BTreeMap<String, TypeExpr>) -> Result<TEDataNode, TypingErr> {\n        let mut v = Vec::new();\n        for it in self.type_args.iter() {\n            v.push(it.apply(ty)?);\n        }\n\n        Ok(TEDataNode {\n            id: self.id.clone(),\n            type_args: v,\n            pos: self.pos,\n        })\n    }\n}\n\npub type CallbackFn = Box<dyn Fn(&BigInt, &BigInt, &BigInt) -> Option<BigInt> + Send>;\npub type FFIFn = BTreeMap<&'static str, fn(env: &mut Environment<'_>, args: &[RTData]) -> RTData>;\n\npub struct Context {\n    pub(crate) funs: BTreeMap<String, Defun>,\n    pub(crate) ext_funs: BTreeMap<String, Extern>,\n    pub(crate) ext_ffi: FFIFn,\n    pub(crate) lambda: BTreeMap<u64, Lambda>,\n    pub(crate) lambda_ident: u64,\n    pub(crate) data: BTreeMap<String, DataType>,\n    pub(crate) built_in: BTreeSet<String>,\n    label2data: BTreeMap<String, String>,\n    pub(crate) callback: CallbackFn,\n    pub(crate) macros: Macros,\n}\n\nimpl Context {\n    fn new(\n        funs: BTreeMap<String, Defun>,\n        ext_funs: BTreeMap<String, Extern>,\n        ext_ffi: FFIFn,\n        data: BTreeMap<String, DataType>,\n        macros: Macros,\n    ) -> Context {\n        let mut built_in = BTreeSet::new();\n\n        built_in.insert(\"+\".to_string());\n        built_in.insert(\"-\".to_string());\n        built_in.insert(\"*\".to_string());\n        built_in.insert(\"/\".to_string());\n        built_in.insert(\">>\".to_string());\n        built_in.insert(\"<<\".to_string());\n        built_in.insert(\"band\".to_string());\n        built_in.insert(\"bor\".to_string());\n        built_in.insert(\"bxor\".to_string());\n        built_in.insert(\"pow\".to_string());\n        built_in.insert(\"sqrt\".to_string());\n        built_in.insert(\"chars\".to_string());\n        built_in.insert(\"str\".to_string());\n        built_in.insert(\"%\".to_string());\n        built_in.insert(\"<\".to_string());\n        built_in.insert(\">\".to_string());\n        built_in.insert(\"=\".to_string());\n        built_in.insert(\"!=\".to_string());\n        built_in.insert(\"<=\".to_string());\n        built_in.insert(\">=\".to_string());\n        built_in.insert(\"lt\".to_string());\n        built_in.insert(\"gt\".to_string());\n        built_in.insert(\"eq\".to_string());\n        built_in.insert(\"neq\".to_string());\n        built_in.insert(\"leq\".to_string());\n        built_in.insert(\"geq\".to_string());\n        built_in.insert(\"and\".to_string());\n        built_in.insert(\"or\".to_string());\n        built_in.insert(\"xor\".to_string());\n        built_in.insert(\"not\".to_string());\n        built_in.insert(\"call-rust\".to_string());\n\n        Context {\n            funs,\n            ext_funs,\n            ext_ffi,\n            data,\n            built_in,\n            label2data: BTreeMap::new(),\n            lambda: BTreeMap::new(),\n            lambda_ident: 0,\n            callback: Box::new(|_, _, _| None),\n            macros,\n        }\n    }\n\n    pub fn set_callback(&mut self, func: CallbackFn) {\n        self.callback = func;\n    }\n\n    fn typing(&mut self) -> Result<(), TypingErr> {\n        self.check_data_def()?;\n        self.check_label()?;\n        self.check_data_rec()?;\n        self.check_defun_type()?;\n        self.typing_functions()?;\n        self.check_defun_type_after_infer()?;\n        self.check_match_exhaustive()?;\n        self.find_tail_call();\n        self.get_free_var_in_lambda();\n\n        Ok(())\n    }\n\n    fn check_match_exhaustive(&self) -> Result<(), TypingErr> {\n        for fun in self.funs.values() {\n            exhaustive_expr(&fun.expr, self)?;\n        }\n        Ok(())\n    }\n\n    fn find_tail_call(&mut self) {\n        for fun in self.funs.values_mut() {\n            tail_call(&mut fun.expr);\n        }\n        for fun in self.lambda.values_mut() {\n            tail_call(&mut fun.expr);\n        }\n    }\n\n    fn check_label(&mut self) -> Result<(), TypingErr> {\n        for dt in self.data.values() {\n            for mem in &dt.members {\n                if self.label2data.contains_key(&mem.id.id) {\n                    let msg = format!(\"{} is multiply defined\", mem.id.id);\n                    return Err(TypingErr {\n                        msg,\n                        pos: mem.id.pos,\n                    });\n                }\n\n                self.label2data\n                    .insert(mem.id.id.clone(), dt.name.id.id.clone());\n            }\n        }\n\n        Ok(())\n    }\n\n    fn typing_functions(&mut self) -> Result<(), TypingErr> {\n        let mut ext_funs = BTreeMap::new();\n        for (_, ext_fun) in self.ext_funs.iter() {\n            let mut fun = ext_fun.clone();\n            self.typing_extern(&mut fun)?;\n            ext_funs.insert(fun.id.id.to_string(), fun);\n        }\n\n        self.ext_funs = ext_funs;\n\n        let mut funs = BTreeMap::new();\n        for (_, defun) in self.funs.iter() {\n            let mut defun = defun.clone();\n            self.typing_defun(&mut defun)?;\n            funs.insert(defun.id.id.to_string(), defun);\n        }\n\n        self.funs = funs;\n\n        Ok(())\n    }\n\n    fn typing_extern(&self, fun: &mut Extern) -> Result<(), TypingErr> {\n        let mut num_tv = 0;\n        let fun_type = self.to_type(&fun.fun_type, &mut num_tv).unwrap(); // defined type\n        fun.ty = Some(fun_type);\n        Ok(())\n    }\n\n    fn typing_defun(&self, defun: &mut Defun) -> Result<(), TypingErr> {\n        let mut var_type = VarType::new();\n        let mut num_tv = 0;\n        let mut args_orig = Vec::new();\n\n        // initialize types of arguments\n        for t in &defun.args {\n            let tv = ty_var(num_tv);\n            var_type.insert(t.id.to_string(), tv.clone());\n            args_orig.push(tv);\n            num_tv += 1;\n        }\n\n        // infer type of the expression\n        let sbst = Sbst::new();\n        let (ret, sbst) = self.typing_expr(&mut defun.expr, sbst, &mut var_type, &mut num_tv)?;\n\n        let args = args_orig.iter().map(|x| x.apply_sbst(&sbst)).collect();\n\n        let fun_type1 = self.to_type(&defun.fun_type, &mut num_tv).unwrap(); // defined type\n        let fun_type2 = ty_fun(&defun.effect, args, ret); // inferred type\n\n        // check defined function types with inferred type\n\n        let s1 = match unify(&fun_type1, &fun_type2) {\n            None => {\n                let msg = format!(\n                    \"function type was mismatched\\n    inferred: {}\\n     defined: {}\",\n                    fun_type2, fun_type1\n                );\n                return Err(TypingErr {\n                    msg,\n                    pos: defun.pos,\n                });\n            }\n            Some(s) => s,\n        };\n\n        let sbst = compose(&s1, &sbst);\n\n        // update function type\n        defun.ty = Some(fun_type1.apply_sbst(&sbst));\n\n        // update types in the expression\n        defun.expr.apply_sbst(&sbst);\n\n        // update types of arguments\n        for (arg, ty) in defun.args.iter_mut().zip(args_orig.iter()) {\n            arg.ty = Some(ty.apply_sbst(&sbst));\n        }\n\n        Ok(())\n    }\n\n    fn typing_expr(\n        &self,\n        expr: &mut LangExpr,\n        sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        match expr {\n            LangExpr::LitStr(_) => Ok((ty_string(), sbst)),\n            LangExpr::LitChar(_) => Ok((ty_char(), sbst)),\n            LangExpr::LitBool(_) => Ok((ty_bool(), sbst)),\n            LangExpr::LitNum(_) => Ok((ty_int(), sbst)),\n            LangExpr::IfExpr(e) => self.typing_if(e, sbst, var_type, num_tv),\n            LangExpr::IDExpr(e) => self.typing_var(e, sbst, var_type, num_tv),\n            LangExpr::LetExpr(e) => self.typing_let(e, sbst, var_type, num_tv),\n            LangExpr::MatchExpr(e) => self.typing_match(e, sbst, var_type, num_tv),\n            LangExpr::TupleExpr(e) => self.typing_tuple(e, sbst, var_type, num_tv),\n            LangExpr::ListExpr(e) => self.typing_list(e, sbst, var_type, num_tv),\n            LangExpr::ApplyExpr(e) => self.typing_app(e, sbst, var_type, num_tv),\n            LangExpr::DataExpr(e) => self.typing_data(e, sbst, var_type, num_tv),\n            LangExpr::LambdaExpr(e) => self.typing_lambda(e, sbst, var_type, num_tv),\n        }\n    }\n\n    fn typing_lambda(\n        &self,\n        expr: &mut Lambda,\n        sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        var_type.push();\n\n        // generate new type variables for arguments\n        for arg in &mut expr.args {\n            let ty = ty_var(*num_tv);\n            *num_tv += 1;\n            arg.ty = Some(ty.clone());\n\n            if arg.id != \"_\" {\n                var_type.insert(arg.id.to_string(), ty.clone());\n            }\n        }\n\n        // infer the type of the expression\n        let (ret_ty, sbst) = self.typing_expr(&mut expr.expr, sbst, var_type, num_tv)?;\n\n        var_type.pop();\n\n        // generate function type\n        let mut v = Vec::new();\n        for arg in &mut expr.args {\n            match &arg.ty {\n                Some(t) => {\n                    let t2 = t.apply_sbst(&sbst);\n                    v.push(t2.clone());\n                    arg.ty = Some(t2);\n                }\n                None => (),\n            }\n        }\n\n        let ty = ty_fun(&Effect::Pure, v, ret_ty);\n\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_data(\n        &self,\n        expr: &mut DataNode,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        let data_type;\n        let label_types;\n        // get type of label and types of label's elements\n        match self.get_type_of_label(&expr.label.id, num_tv) {\n            Ok((t, m)) => {\n                data_type = t;\n                label_types = m;\n            }\n            Err(msg) => {\n                return Err(TypingErr { msg, pos: expr.pos });\n            }\n        }\n\n        // check the number of elements\n        if label_types.len() != expr.exprs.len() {\n            let msg = format!(\n                \"{} requires exactly {} arguments but actually passed {}\",\n                expr.label.id,\n                label_types.len(),\n                expr.exprs.len()\n            );\n            return Err(TypingErr { msg, pos: expr.pos });\n        }\n\n        // check types of the elements and arguments\n        for (e, ty) in expr.exprs.iter_mut().zip(label_types.iter()) {\n            let r = self.typing_expr(e, sbst, var_type, num_tv)?;\n            sbst = r.1;\n            let t0 = ty.apply_sbst(&sbst);\n            let t1 = r.0.apply_sbst(&sbst);\n            let s1 = match unify(&t0, &t1) {\n                Some(s) => s,\n                None => {\n                    let msg = format!(\"mismatched type\\n  expected: {}\\n    actual: {}\", t0, t1);\n                    return Err(TypingErr {\n                        msg,\n                        pos: e.get_pos(),\n                    });\n                }\n            };\n            sbst = compose(&s1, &sbst);\n        }\n\n        let ty = data_type.apply_sbst(&sbst);\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_app(\n        &self,\n        expr: &mut Apply,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        let mut iter = expr.exprs.iter_mut();\n\n        // get function\n        let e1 = match iter.next() {\n            Some(e) => e,\n            None => {\n                return Err(TypingErr {\n                    msg: \"require function\".to_string(),\n                    pos: expr.pos,\n                });\n            }\n        };\n\n        // get function type\n        let r = self.typing_expr(e1, sbst, var_type, num_tv)?;\n        sbst = r.1;\n        let t1 = r.0; // function type\n\n        // get arguments\n        let mut v = Vec::new();\n        for e in iter {\n            let r = self.typing_expr(e, sbst, var_type, num_tv)?;\n            sbst = r.1;\n            v.push(r.0);\n        }\n\n        // get return type\n        let ret = ty_var(*num_tv);\n        *num_tv += 1;\n\n        // get inferred function type\n        let fun_ty = ty_fun_gen_effect(*num_tv, v, ret.clone());\n        *num_tv += 1;\n\n        match unify(&t1, &fun_ty) {\n            Some(s1) => {\n                sbst = compose(&s1, &sbst);\n            }\n            None => {\n                let msg = format!(\n                    \"mismatched type\\n  expected: {}\\n    actual: {}\",\n                    fun_ty, t1\n                );\n                return Err(TypingErr { msg, pos: expr.pos });\n            }\n        }\n\n        let t = ret.apply_sbst(&sbst);\n        expr.ty = Some(t.clone());\n\n        Ok((t, sbst))\n    }\n\n    fn typing_tuple(\n        &self,\n        expr: &mut Exprs,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        let mut v = Vec::new();\n        for e in expr.exprs.iter_mut() {\n            let (t, s) = self.typing_expr(e, sbst, var_type, num_tv)?;\n            sbst = s;\n            v.push(t);\n        }\n\n        let ty = ty_tuple(v);\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_list(\n        &self,\n        expr: &mut Exprs,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        let mut ty = None; // type of the first element\n\n        for e in expr.exprs.iter_mut() {\n            let (t, s) = self.typing_expr(e, sbst, var_type, num_tv)?;\n            sbst = s;\n            match &ty {\n                None => {\n                    ty = Some(t);\n                }\n                Some(t0) => {\n                    let t0 = t0.apply_sbst(&sbst);\n                    // check current element's type is same as the first element's type\n                    match unify(&t0, &t) {\n                        Some(s1) => {\n                            sbst = compose(&s1, &sbst);\n                        }\n                        None => {\n                            let msg =\n                                format!(\"mismatched type\\n  expected: {}\\n    actual: {}\", t0, t);\n                            return Err(TypingErr {\n                                msg,\n                                pos: e.get_pos(),\n                            });\n                        }\n                    }\n                }\n            }\n        }\n\n        match ty {\n            Some(t0) => {\n                let tyls = ty_list(t0.apply_sbst(&sbst));\n                expr.ty = Some(tyls.clone());\n                Ok((tyls, sbst))\n            }\n            None => {\n                // Nil\n                let t = ty_var(*num_tv);\n                let tyls = ty_list(t);\n                *num_tv += 1;\n                expr.ty = Some(tyls.clone());\n                Ok((tyls, sbst))\n            }\n        }\n    }\n\n    fn typing_match(\n        &self,\n        expr: &mut MatchNode,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        // for (match e_0 (c_1 e_1) (c_2 e_2) ... (c_n e_n))\n\n        // get e_0's type\n        let r = self.typing_expr(&mut expr.expr, sbst, var_type, num_tv)?;\n        let mut type_head = r.0;\n        sbst = r.1;\n\n        let mut e_ty = None;\n        for cs in expr.cases.iter_mut() {\n            var_type.push();\n\n            // get c_n's type\n            let (pat_ty, s) = self.typing_pat(&mut cs.pattern, sbst, var_type, num_tv)?;\n            sbst = s;\n\n            // check types of e_0 and c_n are same\n            type_head = type_head.apply_sbst(&sbst);\n            let s1 = match unify(&type_head, &pat_ty) {\n                Some(s) => s,\n                None => {\n                    let msg = format!(\n                        \"mismatched type\\n  expected: {}\\n    actual: {}\",\n                        type_head, pat_ty\n                    );\n                    return Err(TypingErr {\n                        msg,\n                        pos: cs.pattern.get_pos(),\n                    });\n                }\n            };\n\n            sbst = compose(&s1, &sbst);\n\n            // get e_n's type\n            let (ty, s) = self.typing_expr(&mut cs.expr, sbst, var_type, num_tv)?;\n            sbst = s;\n\n            // check types of e_{n-1} and e_n are same\n            if let Some(t_prev) = e_ty {\n                let s1 = match unify(&t_prev, &ty) {\n                    Some(s) => s,\n                    None => {\n                        let msg = format!(\n                            \"mismatched type\\n  expected: {}\\n    actual: {}\",\n                            t_prev, ty\n                        );\n                        return Err(TypingErr { msg, pos: cs.pos });\n                    }\n                };\n\n                sbst = compose(&sbst, &s1);\n            }\n\n            let ty = ty.apply_sbst(&sbst);\n            cs.ty = Some(ty.clone());\n            e_ty = Some(ty);\n\n            var_type.pop();\n        }\n\n        expr.ty = e_ty.clone();\n\n        Ok((e_ty.unwrap(), sbst))\n    }\n\n    fn typing_var(\n        &self,\n        expr: &mut IDNode,\n        sbst: Sbst,\n        var_type: &VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        let ty = match var_type.get(&expr.id) {\n            Some(t) => t.apply_sbst(&sbst),\n            None => {\n                // look up external function\n                if let Some(fun) = self.ext_funs.get(&expr.id) {\n                    self.to_type(&fun.fun_type, num_tv).unwrap()\n                } else {\n                    // look up function\n                    match self.funs.get(&expr.id) {\n                        Some(defun) => self.to_type(&defun.fun_type, num_tv).unwrap(),\n                        None => {\n                            match expr.id.as_ref() {\n                                // built-in functions\n                                \"+\" | \"-\" | \"*\" | \"/\" | \"%\" | \"band\" | \"bor\" | \"bxor\" => {\n                                    ty_fun(&Effect::Pure, vec![ty_int(), ty_int()], ty_int())\n                                }\n                                \"=\" | \"<\" | \">\" | \"<=\" | \">=\" | \"!=\" => {\n                                    let tv = ty_var(*num_tv);\n                                    *num_tv += 1;\n                                    ty_fun(&Effect::Pure, vec![tv.clone(), tv], ty_bool())\n                                }\n                                \"eq\" | \"lt\" | \"gt\" | \"leq\" | \"geq\" | \"neq\" => {\n                                    let tv1 = ty_var(*num_tv);\n                                    *num_tv += 1;\n                                    let tv2 = ty_var(*num_tv);\n                                    *num_tv += 1;\n                                    ty_fun(&Effect::Pure, vec![tv1, tv2], ty_bool())\n                                }\n                                \"and\" | \"or\" | \"xor\" => {\n                                    ty_fun(&Effect::Pure, vec![ty_bool(), ty_bool()], ty_bool())\n                                }\n                                \"not\" => ty_fun(&Effect::Pure, vec![ty_bool()], ty_bool()),\n                                \"sqrt\" => ty_fun(\n                                    &Effect::Pure,\n                                    vec![ty_int()],\n                                    Type::TCon(Tycon {\n                                        id: \"Option\".to_string(),\n                                        args: Some(vec![ty_int()]),\n                                    }),\n                                ),\n                                \"pow\" | \"<<\" | \">>\" => {\n                                    // (Pure (-> (Int Int) (Option Int)))\n                                    ty_fun(\n                                        &Effect::Pure,\n                                        vec![ty_int(), ty_int()],\n                                        Type::TCon(Tycon {\n                                            id: \"Option\".to_string(),\n                                            args: Some(vec![ty_int()]),\n                                        }),\n                                    )\n                                }\n                                \"chars\" => {\n                                    // (Pure (-> (String) (List Char)))\n                                    ty_fun(\n                                        &Effect::Pure,\n                                        vec![ty_string()],\n                                        Type::TCon(Tycon {\n                                            id: \"List\".to_string(),\n                                            args: Some(vec![ty_char()]),\n                                        }),\n                                    )\n                                }\n                                \"str\" => {\n                                    // (Pure (-> ((List Char)) String))\n                                    ty_fun(\n                                        &Effect::Pure,\n                                        vec![Type::TCon(Tycon {\n                                            id: \"List\".to_string(),\n                                            args: Some(vec![ty_char()]),\n                                        })],\n                                        ty_string(),\n                                    )\n                                }\n                                \"call-rust\" => {\n                                    // (IO (-> (Int Int Int) (Option Int)))\n                                    ty_fun(\n                                        &Effect::IO,\n                                        vec![ty_int(), ty_int(), ty_int()],\n                                        Type::TCon(Tycon {\n                                            id: \"Option\".to_string(),\n                                            args: Some(vec![ty_int()]),\n                                        }),\n                                    )\n                                }\n                                _ => {\n                                    let msg = format!(\"{} is not defined 5\", expr.id);\n                                    return Err(TypingErr { msg, pos: expr.pos });\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        };\n\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_if(\n        &self,\n        expr: &mut IfNode,\n        sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        // condition\n        let (ty_cond, sbst) = self.typing_expr(&mut expr.cond_expr, sbst, var_type, num_tv)?;\n\n        // check the type of condition is Bool\n        let s1 = match unify(&ty_bool(), &ty_cond) {\n            Some(s) => s,\n            None => {\n                let msg = format!(\n                    \"condition of if expression must be Bool, but found {}\",\n                    ty_cond\n                );\n                return Err(TypingErr {\n                    msg,\n                    pos: expr.cond_expr.get_pos(),\n                });\n            }\n        };\n\n        let sbst = compose(&s1, &sbst);\n\n        // then and else expressions\n        let (ty_then, sbst) = self.typing_expr(&mut expr.then_expr, sbst, var_type, num_tv)?;\n        let (ty_else, sbst) = self.typing_expr(&mut expr.else_expr, sbst, var_type, num_tv)?;\n\n        // check types of expressions are same\n        let s1 = match unify(&ty_then, &ty_else) {\n            Some(s) => s,\n            None => {\n                let msg = format!(\n                    \"when (if c e1 e2), the types of e1 and e2 must be same\\n  e1: {}\\n  e2: {}\",\n                    ty_then, ty_else\n                );\n                return Err(TypingErr {\n                    msg,\n                    pos: expr.else_expr.get_pos(),\n                });\n            }\n        };\n\n        let sbst = compose(&s1, &sbst);\n        let ty = ty_then.apply_sbst(&sbst);\n\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_let(\n        &self,\n        expr: &mut LetNode,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        var_type.push();\n\n        for dv in expr.def_vars.iter_mut() {\n            let (t1, s) = self.typing_expr(&mut dv.expr, sbst, var_type, num_tv)?;\n            let (t2, s) = self.typing_pat(&mut dv.pattern, s, var_type, num_tv)?;\n            sbst = s;\n\n            let s1 = match unify(&t1, &t2) {\n                Some(s) => s,\n                None => {\n                    let msg = format!(\"mismatched type\\n   left: {}\\n  right: {}\", t2, t1);\n                    return Err(TypingErr { msg, pos: dv.pos });\n                }\n            };\n            sbst = compose(&s1, &sbst);\n            dv.ty = Some(t1.apply_sbst(&sbst));\n        }\n\n        let r = self.typing_expr(&mut expr.expr, sbst, var_type, num_tv)?;\n\n        var_type.pop();\n        expr.ty = Some(r.0.clone());\n\n        Ok(r)\n    }\n\n    fn typing_pat(\n        &self,\n        expr: &mut Pattern,\n        sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        match expr {\n            Pattern::PatStr(_) => Ok((ty_string(), sbst)),\n            Pattern::PatChar(_) => Ok((ty_char(), sbst)),\n            Pattern::PatBool(_) => Ok((ty_bool(), sbst)),\n            Pattern::PatNum(_) => Ok((ty_int(), sbst)),\n            Pattern::PatID(e) => Ok(self.typing_pat_id(e, sbst, var_type, num_tv)),\n            Pattern::PatData(e) => self.typing_pat_data(e, sbst, var_type, num_tv),\n            Pattern::PatTuple(e) => self.typing_pat_tuple(e, sbst, var_type, num_tv),\n            Pattern::PatNil(e) => Ok(self.typing_pat_nil(e, sbst, num_tv)),\n        }\n    }\n\n    fn typing_pat_tuple(\n        &self,\n        expr: &mut PatTupleNode,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        let mut v = Vec::new();\n        for pat in expr.pattern.iter_mut() {\n            let (t, s) = self.typing_pat(pat, sbst, var_type, num_tv)?;\n            sbst = s;\n            v.push(t);\n        }\n\n        let ty = ty_tuple(v);\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_pat_id(\n        &self,\n        expr: &mut IDNode,\n        sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> (Type, Sbst) {\n        // generate new type variable (internal representation)\n        let ty = ty_var(*num_tv);\n        *num_tv += 1;\n        expr.ty = Some(ty.clone());\n\n        if expr.id != \"_\" {\n            var_type.insert(expr.id.to_string(), ty.clone());\n        }\n\n        (ty, sbst)\n    }\n\n    fn typing_pat_data(\n        &self,\n        expr: &mut PatDataNode,\n        mut sbst: Sbst,\n        var_type: &mut VarType,\n        num_tv: &mut ID,\n    ) -> Result<(Type, Sbst), TypingErr> {\n        // get the type of label and the types of label's elements\n        let data_type; // type of label\n        let label_types; // types of label's elements\n        match self.get_type_of_label(&expr.label.id, num_tv) {\n            Ok((t, m)) => {\n                data_type = t;\n                label_types = m;\n            }\n            Err(msg) => {\n                return Err(TypingErr {\n                    msg,\n                    pos: expr.label.pos,\n                });\n            }\n        }\n\n        // check the number of arguments\n        if label_types.len() != expr.pattern.len() {\n            let msg = format!(\n                \"{} requires exactly {} arguments but actually passed {}\",\n                expr.label.id,\n                label_types.len(),\n                expr.pattern.len()\n            );\n            return Err(TypingErr {\n                msg,\n                pos: expr.label.pos,\n            });\n        }\n\n        // check type of each element\n        for (pat, lt) in expr.pattern.iter_mut().zip(label_types.iter()) {\n            let r = self.typing_pat(pat, sbst, var_type, num_tv)?;\n            sbst = r.1;\n            let lt = lt.apply_sbst(&sbst);\n            let s1 = match unify(&lt, &r.0) {\n                Some(s) => s,\n                None => {\n                    let msg = format!(\"mismatched type\\n  expected: {}\\n    actual: {}\", lt, r.0);\n                    return Err(TypingErr {\n                        msg,\n                        pos: pat.get_pos(),\n                    });\n                }\n            };\n            sbst = compose(&s1, &sbst);\n        }\n\n        let ty = data_type.apply_sbst(&sbst);\n        expr.ty = Some(ty.clone());\n\n        Ok((ty, sbst))\n    }\n\n    fn typing_pat_nil(&self, expr: &mut PatNilNode, sbst: Sbst, num_tv: &mut ID) -> (Type, Sbst) {\n        let tv = ty_var(*num_tv);\n        *num_tv += 1;\n        let ty = ty_list(tv);\n        expr.ty = Some(ty.clone());\n        (ty, sbst)\n    }\n\n    fn to_type(&self, expr: &TypeExpr, num_tv: &mut ID) -> Result<Type, String> {\n        let mut tv2type = BTreeMap::new();\n        get_tv2type_from_type_expr(expr, num_tv, &mut tv2type);\n        apply_tv2type_to_type_expr(expr, &tv2type)\n    }\n\n    /// If\n    /// ```lisp\n    /// (data (Tree t)\n    ///   (Node (Tree t) (Tree t))\n    ///   Leaf)\n    /// ```\n    /// then get_type_of_label(\"Node\", 2)\n    /// returns Ok((Tree (TVar 2)), vec!((Tree (TVar 2)), ((Tree (TVar 2))))\n    fn get_type_of_label(&self, label: &str, num_tv: &mut ID) -> Result<(Type, Vec<Type>), String> {\n        // find the name of data of the label\n        let data_name;\n        match self.label2data.get(label) {\n            Some(n) => {\n                data_name = n;\n            }\n            None => {\n                match label {\n                    // built-in data type\n                    // (data (List a)\n                    //     (Cons a (List a))\n                    //     Nil)\n                    \"Cons\" => {\n                        let tv = ty_var(*num_tv);\n                        let ty = ty_list(tv.clone());\n                        *num_tv += 1;\n                        return Ok((ty.clone(), vec![tv, ty]));\n                    }\n                    \"Nil\" => {\n                        let tv = ty_var(*num_tv);\n                        let ty = ty_list(tv);\n                        *num_tv += 1;\n                        return Ok((ty, vec![]));\n                    }\n                    _ => {\n                        let msg = format!(\"{} is not defined\", label);\n                        return Err(msg);\n                    }\n                }\n            }\n        }\n\n        // find corresponding data\n        let data_node = match self.data.get(data_name) {\n            Some(n) => n,\n            None => {\n                let msg = format!(\"could not find data of label {}\", label);\n                return Err(msg);\n            }\n        };\n\n        // get the type of the data\n        let mut types = Vec::new();\n        for i in 0..data_node.name.type_args.len() {\n            types.push(ty_var(i as ID + *num_tv));\n        }\n        *num_tv += data_node.name.type_args.len() as u64;\n\n        // generate a map from type variable to type\n        let mut tv2type = BTreeMap::new();\n        for (k, v) in data_node.name.type_args.iter().zip(types.iter()) {\n            tv2type.insert(k.id.clone(), v.clone());\n        }\n\n        // find corresponding member\n        let mut mem = None;\n        for m in &data_node.members {\n            if m.id.id == *label {\n                mem = Some(m);\n                break;\n            }\n        }\n\n        // return type of label and label's type\n        match mem {\n            Some(mem) => {\n                let mut label_types = Vec::new();\n                for t in &mem.types {\n                    label_types.push(apply_tv2type_to_type_expr(t, &tv2type)?);\n                }\n\n                // the type of the data\n                let data_type = Type::TCon(Tycon {\n                    id: data_name.to_string(),\n                    args: if types.is_empty() { None } else { Some(types) },\n                });\n\n                Ok((data_type, label_types))\n            }\n            None => {\n                let msg = format!(\"could not find label {}\", label);\n                Err(msg)\n            }\n        }\n    }\n\n    fn check_data_def(&self) -> Result<(), TypingErr> {\n        for (_, d) in self.data.iter() {\n            self.check_data_def_data(d)?;\n        }\n\n        Ok(())\n    }\n\n    fn check_data_def_data(&self, data: &DataType) -> Result<(), TypingErr> {\n        let mut args = BTreeSet::new();\n        for arg in data.name.type_args.iter() {\n            if args.contains(&arg.id) {\n                let msg = format!(\"{} is multiply used\", arg.id);\n                return Err(TypingErr { msg, pos: arg.pos });\n            }\n\n            args.insert(arg.id.clone());\n        }\n\n        for mem in data.members.iter() {\n            self.check_data_def_mem(mem, &args)?;\n        }\n\n        Ok(())\n    }\n\n    fn check_data_def_mem(\n        &self,\n        mem: &DataTypeMem,\n        args: &BTreeSet<String>,\n    ) -> Result<(), TypingErr> {\n        for it in mem.types.iter() {\n            self.check_def_type(it, Some(args))?\n        }\n\n        Ok(())\n    }\n\n    fn check_def_type(\n        &self,\n        ty: &TypeExpr,\n        args: Option<&BTreeSet<String>>,\n    ) -> Result<(), TypingErr> {\n        match ty {\n            TypeExpr::Id(id) => {\n                if let Some(m) = args {\n                    if !m.contains(&id.id) {\n                        let msg = format!(\"{} is undefined\", id.id);\n                        return Err(TypingErr { msg, pos: id.pos });\n                    }\n                }\n            }\n            TypeExpr::List(list) => {\n                self.check_def_type(&list.ty, args)?;\n            }\n            TypeExpr::Tuple(tuple) => {\n                for it in tuple.ty.iter() {\n                    self.check_def_type(it, args)?;\n                }\n            }\n            TypeExpr::Data(data) => {\n                match self.data.get(&data.id.id) {\n                    Some(dt) => {\n                        if dt.name.type_args.len() != data.type_args.len() {\n                            let msg = format!(\n                                \"{} takes {} type arguments but actually passed {}\",\n                                data.id.id,\n                                dt.name.type_args.len(),\n                                data.type_args.len()\n                            );\n                            return Err(TypingErr {\n                                msg,\n                                pos: data.id.pos,\n                            });\n                        }\n                    }\n                    None => {\n                        let msg = format!(\"{} is unkown type\", data.id.id);\n                        return Err(TypingErr {\n                            msg,\n                            pos: data.id.pos,\n                        });\n                    }\n                }\n\n                for it in data.type_args.iter() {\n                    self.check_def_type(it, args)?;\n                }\n            }\n            TypeExpr::Fun(fun) => {\n                for it in fun.args.iter() {\n                    self.check_def_type(it, args)?\n                }\n\n                self.check_def_type(&fun.ret, args)?\n            }\n            _ => {}\n        }\n\n        Ok(())\n    }\n\n    /// check data definition is not infinite recursive\n    fn check_data_rec(&self) -> Result<(), TypingErr> {\n        let mut checked = LinkedList::new();\n        for (_, d) in self.data.iter() {\n            let mut visited = BTreeSet::new();\n            let mut inst = LinkedList::new();\n            inst.push_back(d.pos);\n            if self.check_data_rec_data(d, &mut visited, &mut checked, &mut inst)? {\n                let msg = format!(\"{}'s definition is infinitely recursive\", d.name.id.id);\n                return Err(TypingErr {\n                    msg,\n                    pos: d.name.id.pos,\n                });\n            }\n            checked.push_back(d.clone());\n        }\n\n        Ok(())\n    }\n\n    /// Ok(true) if the type is inifinite recursive\n    /// Ok(false) if the type is not recursive or limited recursive\n    ///\n    /// infinite recursive data\n    /// ```lisp\n    /// (data Num (Succ Num))\n    /// ```\n    ///\n    /// limited recursive date\n    /// ```lisp\n    /// (data (Tree t)\n    ///   (Node (Tree t) (Tree t))\n    ///   Leaf)\n    ///\n    /// (data Num\n    ///   (Succ Num)\n    ///   Zero)\n    /// ```\n    fn check_data_rec_data(\n        &self,\n        data: &DataType,\n        visited: &mut BTreeSet<String>,\n        checked: &mut LinkedList<DataType>,\n        inst: &mut LinkedList<Pos>,\n    ) -> Result<bool, TypingErr> {\n        if visited.contains(&data.name.id.id) {\n            return Ok(true);\n        }\n\n        let mut ret = true;\n\n        visited.insert(data.name.id.id.clone());\n        for mem in data.members.iter() {\n            inst.push_back(mem.pos);\n            let result = self.check_data_rec_mem(mem, visited, checked, inst)?;\n            ret = result && ret;\n            inst.pop_back();\n        }\n\n        Ok(ret)\n    }\n\n    fn check_data_rec_mem(\n        &self,\n        mem: &DataTypeMem,\n        visited: &mut BTreeSet<String>,\n        checked: &mut LinkedList<DataType>,\n        inst: &mut LinkedList<Pos>,\n    ) -> Result<bool, TypingErr> {\n        let mut ret = false;\n\n        for ty in mem.types.iter() {\n            if self.check_data_rec_ty(ty, visited, checked, inst)? {\n                ret = true;\n            }\n        }\n\n        Ok(ret)\n    }\n\n    fn check_data_rec_ty(\n        &self,\n        ty: &TypeExpr,\n        visited: &mut BTreeSet<String>,\n        checked: &mut LinkedList<DataType>,\n        inst: &mut LinkedList<Pos>,\n    ) -> Result<bool, TypingErr> {\n        match ty {\n            TypeExpr::List(_list) => Ok(false),\n            TypeExpr::Tuple(tuple) => {\n                let mut ret = false;\n\n                inst.push_back(tuple.pos);\n                for it in tuple.ty.iter() {\n                    if self.check_data_rec_ty(it, visited, checked, inst)? {\n                        ret = true;\n                    }\n                }\n                inst.pop_back();\n\n                Ok(ret)\n            }\n            TypeExpr::Data(data) => {\n                let dt = self.type_data_node2data_type(data)?;\n                inst.push_back(data.pos);\n                let ret = self.check_data_rec_data(&dt, visited, checked, inst);\n                inst.pop_back();\n                ret\n            }\n            TypeExpr::Fun(_fun) => Ok(false),\n            _ => Ok(false),\n        }\n    }\n\n    fn type_data_node2data_type(&self, data: &TEDataNode) -> Result<DataType, TypingErr> {\n        let dt = match self.data.get(&data.id.id) {\n            Some(t) => t,\n            None => {\n                return Err(TypingErr {\n                    msg: \"no such type\".to_string(),\n                    pos: data.id.pos,\n                });\n            }\n        };\n\n        if data.type_args.len() != dt.name.type_args.len() {\n            let msg = format!(\n                \"{} takes {} type arguments but actually passed {}\",\n                data.id.id,\n                dt.name.type_args.len(),\n                data.type_args.len()\n            );\n            return Err(TypingErr { msg, pos: data.pos });\n        }\n\n        let mut map = BTreeMap::new();\n        for (k, v) in dt.name.type_args.iter().zip(data.type_args.iter()) {\n            map.insert(k.id.clone(), v.clone());\n        }\n\n        dt.apply(&map)\n    }\n\n    fn check_defun_type(&self) -> Result<(), TypingErr> {\n        for (_, fun) in self.funs.iter() {\n            self.check_def_type(&fun.fun_type, None)?;\n        }\n\n        Ok(())\n    }\n\n    fn check_defun_type_after_infer(&mut self) -> Result<(), TypingErr> {\n        let mut m = FunTypes::new();\n        for (_, fun) in self.funs.iter() {\n            self.check_type_infer(fun, &mut m)?;\n        }\n\n        Ok(())\n    }\n\n    /// check type inference has been correctly done?\n    ///\n    /// If an inferred type of defun has no type variables,\n    /// then the types of the expression must not contain type variables.\n    ///\n    /// If an effect of a function is Pure,\n    /// then the expression must not contain IO function.\n    fn check_type_infer(&self, defun: &Defun, fun_types: &mut FunTypes) -> Result<(), TypingErr> {\n        // check effect\n        check_type_has_io(&defun.ty, &defun.pos, &Sbst::new(), &defun.effect)?;\n\n        // if function type contains type variables, just return Ok\n        match &defun.ty {\n            Some(t) => {\n                if has_tvar(t) {\n                    return Ok(());\n                }\n            }\n            None => {\n                return Err(TypingErr {\n                    msg: \"function type has not inferred yet\".to_string(),\n                    pos: defun.pos,\n                });\n            }\n        }\n\n        // get arguments\n        let mut vars = VarType::new();\n        vars.push();\n        for arg in &defun.args {\n            match &arg.ty {\n                Some(t) => {\n                    vars.insert(arg.id.to_string(), t.clone());\n                }\n                None => {\n                    return Err(TypingErr {\n                        msg: \"argument type has not inferred yet\".to_string(),\n                        pos: arg.pos,\n                    });\n                }\n            }\n        }\n\n        self.check_expr_type(\n            &defun.expr,\n            fun_types,\n            &mut vars,\n            &Sbst::new(),\n            &defun.effect,\n            true,\n        )\n    }\n\n    fn check_expr_type(\n        &self,\n        expr: &LangExpr,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        match expr {\n            LangExpr::IDExpr(e) => self.check_id_type(e, fun_types, vars, sbst, effect, chk_rec),\n            LangExpr::IfExpr(e) => self.check_if_type(e, fun_types, vars, sbst, effect, chk_rec),\n            LangExpr::LetExpr(e) => self.check_let_type(e, fun_types, vars, sbst, effect, chk_rec),\n            LangExpr::MatchExpr(e) => {\n                self.check_match_type(e, fun_types, vars, sbst, effect, chk_rec)\n            }\n            LangExpr::ApplyExpr(e) => {\n                self.check_apply_type(e, fun_types, vars, sbst, effect, chk_rec)\n            }\n            LangExpr::ListExpr(e) => {\n                self.check_exprs_type(e, fun_types, vars, sbst, effect, chk_rec)\n            }\n            LangExpr::TupleExpr(e) => {\n                self.check_exprs_type(e, fun_types, vars, sbst, effect, chk_rec)\n            }\n            LangExpr::DataExpr(e) => {\n                self.check_data_type(e, fun_types, vars, sbst, effect, chk_rec)\n            }\n            LangExpr::LambdaExpr(e) => self.check_lambda_type(e, fun_types, vars, sbst, chk_rec),\n            _ => Ok(()),\n        }\n    }\n\n    fn check_lambda_type(\n        &self,\n        expr: &Lambda,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, &Effect::Pure)?;\n\n        vars.push();\n        for arg in &expr.args {\n            vars.insert(arg.id.to_string(), arg.ty.as_ref().unwrap().clone());\n        }\n        self.check_expr_type(&expr.expr, fun_types, vars, sbst, &Effect::Pure, chk_rec)?;\n        vars.pop();\n\n        Ok(())\n    }\n\n    fn check_data_type(\n        &self,\n        expr: &DataNode,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n\n        for e in &expr.exprs {\n            self.check_expr_type(e, fun_types, vars, sbst, effect, chk_rec)?;\n        }\n        Ok(())\n    }\n\n    fn check_apply_type(\n        &self,\n        expr: &Apply,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n\n        for e in &expr.exprs {\n            self.check_expr_type(e, fun_types, vars, sbst, effect, chk_rec)?;\n        }\n        Ok(())\n    }\n\n    fn check_exprs_type(\n        &self,\n        expr: &Exprs,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n\n        for e in &expr.exprs {\n            self.check_expr_type(e, fun_types, vars, sbst, effect, chk_rec)?;\n        }\n        Ok(())\n    }\n\n    fn check_match_type(\n        &self,\n        expr: &MatchNode,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n\n        self.check_expr_type(&expr.expr, fun_types, vars, sbst, effect, chk_rec)?;\n\n        for c in &expr.cases {\n            vars.push();\n            check_pat_type(&c.pattern, vars, sbst, effect)?;\n            self.check_expr_type(&c.expr, fun_types, vars, sbst, effect, chk_rec)?;\n            vars.pop();\n        }\n\n        Ok(())\n    }\n\n    fn check_id_type(\n        &self,\n        expr: &IDNode,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n        match vars.get(&expr.id.to_string()) {\n            Some(_) => (),\n            None => {\n                if self.ext_funs.get(&expr.id).is_some() {\n                    if !chk_rec {\n                        let msg = format!(\"{} is not defined\", expr.id);\n                        return Err(TypingErr { msg, pos: expr.pos });\n                    }\n                } else {\n                    match self.funs.get(&expr.id) {\n                        Some(defun) => {\n                            if !chk_rec && !defun.exported {\n                                let msg = format!(\"{} is not defined 2\", expr.id);\n                                return Err(TypingErr { msg, pos: expr.pos });\n                            }\n\n                            let call_ty = expr.ty.as_ref().unwrap().apply_sbst(sbst);\n                            self.check_defun_type_recur(&call_ty, defun, fun_types, true)?;\n                        }\n                        None => {\n                            if self.built_in.contains(&expr.id) {\n                                if !chk_rec && expr.id == \"call-rust\" {\n                                    let msg = format!(\"{} is not defined 3\", expr.id);\n                                    return Err(TypingErr { msg, pos: expr.pos });\n                                }\n                            } else {\n                                let msg = format!(\"{} is not defined 4\", expr.id);\n                                return Err(TypingErr { msg, pos: expr.pos });\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    fn check_defun_type_recur(\n        &self,\n        call_ty: &Type,\n        defun: &Defun,\n        fun_types: &mut FunTypes,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        // check only functions whose type has type variables\n        let defun_ty = match &defun.ty {\n            Some(t) => {\n                if !has_tvar(t) {\n                    return Ok(());\n                }\n                t\n            }\n            None => {\n                return Err(TypingErr {\n                    msg: \"function type has not inferred yet\".to_string(),\n                    pos: defun.pos,\n                });\n            }\n        };\n\n        // already checked?\n        let id = defun.id.id.to_string();\n        if fun_types.contains(&id, call_ty) {\n            return Ok(());\n        }\n\n        fun_types.insert(&id, call_ty.clone());\n\n        // check type with caller side\n        let sbst = match unify(call_ty, defun_ty) {\n            Some(s) => s,\n            None => {\n                let msg = format!(\n                    \"mismatched type\\n  expected: {}\\n    actual: {}\",\n                    call_ty, defun_ty\n                );\n                return Err(TypingErr {\n                    msg,\n                    pos: defun.pos,\n                });\n            }\n        };\n\n        // check effect\n        check_type_has_io(&defun.ty, &defun.pos, &sbst, &defun.effect)?;\n\n        // get arguments\n        let mut vars = VarType::new();\n        vars.push();\n        for arg in &defun.args {\n            match &arg.ty {\n                Some(t) => {\n                    vars.insert(arg.id.to_string(), t.apply_sbst(&sbst));\n                }\n                None => {\n                    return Err(TypingErr {\n                        msg: \"argument type has not inferred yet\".to_string(),\n                        pos: arg.pos,\n                    });\n                }\n            }\n        }\n\n        // check function type recursively\n        self.check_expr_type(\n            &defun.expr,\n            fun_types,\n            &mut vars,\n            &sbst,\n            &defun.effect,\n            chk_rec,\n        )\n    }\n\n    fn check_if_type(\n        &self,\n        expr: &IfNode,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n        self.check_expr_type(&expr.cond_expr, fun_types, vars, sbst, effect, chk_rec)?;\n        self.check_expr_type(&expr.then_expr, fun_types, vars, sbst, effect, chk_rec)?;\n        self.check_expr_type(&expr.else_expr, fun_types, vars, sbst, effect, chk_rec)?;\n        Ok(())\n    }\n\n    fn check_let_type(\n        &self,\n        expr: &LetNode,\n        fun_types: &mut FunTypes,\n        vars: &mut VarType,\n        sbst: &Sbst,\n        effect: &Effect,\n        chk_rec: bool,\n    ) -> Result<(), TypingErr> {\n        check_type_has_no_tvars(&expr.ty, &expr.pos, sbst)?;\n        check_type_has_io(&expr.ty, &expr.pos, sbst, effect)?;\n\n        vars.push();\n\n        for def in &expr.def_vars {\n            self.check_expr_type(&def.expr, fun_types, vars, sbst, effect, chk_rec)?;\n            check_pat_type(&def.pattern, vars, sbst, effect)?;\n        }\n\n        self.check_expr_type(&expr.expr, fun_types, vars, sbst, effect, chk_rec)?;\n        vars.pop();\n\n        Ok(())\n    }\n\n    /// collect lambda expressions and\n    /// free variables in the expressions\n    fn get_free_var_in_lambda(&mut self) {\n        let mut funs = BTreeSet::new();\n        for name in self.funs.keys() {\n            funs.insert(name.to_string());\n        }\n\n        for fun in self.funs.values_mut() {\n            let mut local_vars = VarType::new();\n            for arg in &fun.args {\n                local_vars.insert(arg.id.to_string(), arg.ty.clone().unwrap());\n            }\n            get_free_var_expr(\n                &mut fun.expr,\n                &funs,\n                &mut local_vars,\n                &mut Vec::new(),\n                &mut self.lambda_ident,\n                &mut self.lambda,\n            );\n        }\n    }\n}\n\nfn get_tv2type_from_type_expr(\n    expr: &TypeExpr,\n    num_tv: &mut ID,\n    tv2type: &mut BTreeMap<String, Type>,\n) {\n    match expr {\n        TypeExpr::List(e) => {\n            get_tv2type_from_type_expr(&e.ty, num_tv, tv2type);\n        }\n        TypeExpr::Tuple(e) => {\n            for it in &e.ty {\n                get_tv2type_from_type_expr(it, num_tv, tv2type);\n            }\n        }\n        TypeExpr::Fun(e) => {\n            for it in &e.args {\n                get_tv2type_from_type_expr(it, num_tv, tv2type);\n            }\n            get_tv2type_from_type_expr(&e.ret, num_tv, tv2type);\n        }\n        TypeExpr::Data(e) => {\n            for it in &e.type_args {\n                get_tv2type_from_type_expr(it, num_tv, tv2type);\n            }\n        }\n        TypeExpr::Id(e) => {\n            tv2type.insert(e.id.clone(), ty_var(*num_tv));\n            *num_tv += 1;\n        }\n        _ => (),\n    }\n}\n\n/// If\n/// ```lisp\n/// (data (Tree t)\n///   (Node (Tree t) (Tree t))\n///   Leaf)\n/// ```\n/// and tv2type = {t: Int} then\n/// apply_tv2type_to_type_expr((Tree t), tv2type) returns (Tree Int)\nfn apply_tv2type_to_type_expr(\n    type_expr: &TypeExpr,\n    tv2type: &BTreeMap<String, Type>,\n) -> Result<Type, String> {\n    match type_expr {\n        TypeExpr::Char(_) => Ok(ty_char()),\n        TypeExpr::String(_) => Ok(ty_string()),\n        TypeExpr::Bool(_) => Ok(ty_bool()),\n        TypeExpr::Int(_) => Ok(ty_int()),\n        TypeExpr::List(list) => {\n            let t = apply_tv2type_to_type_expr(&list.ty, tv2type)?;\n            Ok(ty_list(t))\n        }\n        TypeExpr::Tuple(tuple) => {\n            let mut v = Vec::new();\n            for t in &tuple.ty {\n                v.push(apply_tv2type_to_type_expr(t, tv2type)?);\n            }\n            Ok(ty_tuple(v))\n        }\n        TypeExpr::Fun(fun) => {\n            let mut args = Vec::new();\n            for a in &fun.args {\n                args.push(apply_tv2type_to_type_expr(a, tv2type)?);\n            }\n            let r = apply_tv2type_to_type_expr(&fun.ret, tv2type)?;\n            Ok(ty_fun(&fun.effect, args, r))\n        }\n        TypeExpr::Data(data) => {\n            let mut v = Vec::new();\n            for t in &data.type_args {\n                v.push(apply_tv2type_to_type_expr(t, tv2type)?);\n            }\n\n            Ok(Type::TCon(Tycon {\n                id: data.id.id.to_string(),\n                args: if v.is_empty() { None } else { Some(v) },\n            }))\n        }\n        TypeExpr::Id(id) => match tv2type.get(&id.id) {\n            Some(t) => Ok(t.clone()),\n            None => {\n                let msg = format!(\"type variable {} is undefined\", id.id);\n                Err(msg)\n            }\n        },\n    }\n}\n\nfn check_pat_type(\n    expr: &Pattern,\n    vars: &mut VarType,\n    sbst: &Sbst,\n    effect: &Effect,\n) -> Result<(), TypingErr> {\n    match expr {\n        Pattern::PatID(e) => {\n            check_type_has_no_tvars(&e.ty, &e.pos, sbst)?;\n            check_type_has_io(&e.ty, &e.pos, sbst, effect)?;\n            vars.insert(e.id.to_string(), e.ty.as_ref().unwrap().clone());\n            Ok(())\n        }\n        Pattern::PatTuple(e) => {\n            check_type_has_no_tvars(&e.ty, &e.pos, sbst)?;\n            check_type_has_io(&e.ty, &e.pos, sbst, effect)?;\n            for it in &e.pattern {\n                check_pat_type(it, vars, sbst, effect)?;\n            }\n            Ok(())\n        }\n        Pattern::PatData(e) => {\n            check_type_has_no_tvars(&e.ty, &e.pos, sbst)?;\n            check_type_has_io(&e.ty, &e.pos, sbst, effect)?;\n            for it in &e.pattern {\n                check_pat_type(it, vars, sbst, effect)?;\n            }\n            Ok(())\n        }\n        _ => Ok(()),\n    }\n}\n\nfn get_free_var_expr(\n    expr: &mut LangExpr,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    match expr {\n        LangExpr::IfExpr(e) => get_free_var_if(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::LetExpr(e) => get_free_var_let(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::IDExpr(e) => get_free_var_id(e, funs, local_vars, ext_vars),\n        LangExpr::DataExpr(e) => get_free_var_data(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::MatchExpr(e) => get_free_var_match(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::ApplyExpr(e) => get_free_var_apply(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::ListExpr(e) => get_free_var_exprs(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::TupleExpr(e) => get_free_var_exprs(e, funs, local_vars, ext_vars, ident, lambda),\n        LangExpr::LambdaExpr(e) => {\n            get_free_var_lambda(e, funs, local_vars, ext_vars, ident, lambda)\n        }\n        _ => {}\n    }\n}\n\nfn get_free_var_apply(\n    exprs: &mut Apply,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    for e in &mut exprs.exprs {\n        get_free_var_expr(e, funs, local_vars, ext_vars, ident, lambda);\n    }\n}\n\nfn get_free_var_exprs(\n    exprs: &mut Exprs,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    for e in &mut exprs.exprs {\n        get_free_var_expr(e, funs, local_vars, ext_vars, ident, lambda);\n    }\n}\n\nfn get_free_var_match(\n    expr: &mut MatchNode,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    get_free_var_expr(&mut expr.expr, funs, local_vars, ext_vars, ident, lambda);\n\n    for c in &mut expr.cases {\n        local_vars.push();\n        get_free_var_pattern(&c.pattern, local_vars);\n        get_free_var_expr(&mut c.expr, funs, local_vars, ext_vars, ident, lambda);\n        local_vars.pop();\n    }\n}\n\nfn get_free_var_data(\n    expr: &mut DataNode,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    for e in &mut expr.exprs {\n        get_free_var_expr(e, funs, local_vars, ext_vars, ident, lambda);\n    }\n}\n\nfn get_free_var_id(\n    expr: &mut IDNode,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n) {\n    let key = expr.id.to_string();\n    match local_vars.get(&key) {\n        Some(_) => (),\n        None => {\n            if !funs.contains(&key) {\n                ext_vars.push(expr.id.to_string());\n            }\n        }\n    }\n}\n\nfn get_free_var_let(\n    expr: &mut LetNode,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    local_vars.push();\n    for dv in &mut expr.def_vars {\n        get_free_var_expr(&mut dv.expr, funs, local_vars, ext_vars, ident, lambda);\n        get_free_var_pattern(&dv.pattern, local_vars);\n    }\n\n    get_free_var_expr(&mut expr.expr, funs, local_vars, ext_vars, ident, lambda);\n    local_vars.pop();\n}\n\nfn get_free_var_if(\n    expr: &mut IfNode,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    get_free_var_expr(\n        &mut expr.cond_expr,\n        funs,\n        local_vars,\n        ext_vars,\n        ident,\n        lambda,\n    );\n    get_free_var_expr(\n        &mut expr.then_expr,\n        funs,\n        local_vars,\n        ext_vars,\n        ident,\n        lambda,\n    );\n    get_free_var_expr(\n        &mut expr.else_expr,\n        funs,\n        local_vars,\n        ext_vars,\n        ident,\n        lambda,\n    );\n}\n\nfn get_free_var_lambda(\n    expr: &mut Lambda,\n    funs: &BTreeSet<String>,\n    local_vars: &mut VarType,\n    ext_vars: &mut Vec<String>,\n    ident: &mut u64,\n    lambda: &mut BTreeMap<u64, Lambda>,\n) {\n    {\n        let mut local_vars = VarType::new();\n        for arg in &expr.args {\n            local_vars.insert(arg.id.to_string(), arg.ty.clone().unwrap());\n        }\n\n        let mut ext_vars = Vec::new();\n\n        get_free_var_expr(\n            &mut expr.expr,\n            funs,\n            &mut local_vars,\n            &mut ext_vars,\n            ident,\n            lambda,\n        );\n\n        expr.vars = ext_vars;\n    }\n\n    // if\n    // (lambda (x) (lambda (y) z))\n    // then\n    // (lambda (x) ...) contains a free variable \"z\"\n    for var in &expr.vars {\n        match local_vars.get(var) {\n            Some(_) => (),\n            None => {\n                ext_vars.push(var.to_string());\n            }\n        }\n    }\n\n    expr.ident = *ident;\n    lambda.insert(*ident, expr.clone());\n    *ident += 1;\n}\n\nfn get_free_var_pattern(pat: &Pattern, local_vars: &mut VarType) {\n    match pat {\n        Pattern::PatID(id) => {\n            if id.id != \"_\" {\n                local_vars.insert(id.id.to_string(), id.ty.clone().unwrap());\n            }\n        }\n        Pattern::PatTuple(tuple) => {\n            for it in &tuple.pattern {\n                get_free_var_pattern(it, local_vars);\n            }\n        }\n        Pattern::PatData(data) => {\n            for it in &data.pattern {\n                get_free_var_pattern(it, local_vars);\n            }\n        }\n        Pattern::PatNum(_)\n        | Pattern::PatBool(_)\n        | Pattern::PatNil(_)\n        | Pattern::PatStr(_)\n        | Pattern::PatChar(_) => (),\n    }\n}\n\nfn check_type_has_no_tvars(ty: &Option<Type>, pos: &Pos, sbst: &Sbst) -> Result<(), TypingErr> {\n    match ty {\n        Some(t) => {\n            if has_tvar(&t.apply_sbst(sbst)) {\n                let msg = format!(\"inferred type still contains type variables\\n  type: {}\", t);\n                return Err(TypingErr { msg, pos: *pos });\n            }\n        }\n        None => {\n            return Err(TypingErr {\n                msg: \"type has not inferred yet\".to_string(),\n                pos: *pos,\n            });\n        }\n    }\n    Ok(())\n}\n\nfn check_type_has_io(\n    ty: &Option<Type>,\n    pos: &Pos,\n    sbst: &Sbst,\n    effect: &Effect,\n) -> Result<(), TypingErr> {\n    match ty {\n        Some(t) => {\n            if let Effect::Pure = effect {\n                if has_io(&t.apply_sbst(sbst)) {\n                    let msg = format!(\"Pure function contains an IO function\\n type: {}\", t);\n                    return Err(TypingErr { msg, pos: *pos });\n                }\n            }\n        }\n        None => {\n            return Err(TypingErr {\n                msg: \"type has not inferred yet\".to_string(),\n                pos: *pos,\n            });\n        }\n    }\n\n    Ok(())\n}\n\n/// Does type contain IO?\nfn has_io(ty: &Type) -> bool {\n    match ty {\n        Type::TCon(t) => {\n            if t.id == \"IO\" {\n                return true;\n            }\n\n            if let Some(args) = &t.args {\n                for arg in args {\n                    if has_io(arg) {\n                        return true;\n                    }\n                }\n            }\n\n            false\n        }\n        Type::TVar(_) => false,\n    }\n}\n\n/// Does type contain type variables?\nfn has_tvar(ty: &Type) -> bool {\n    match ty {\n        Type::TCon(t) => {\n            if let Some(args) = &t.args {\n                for arg in args {\n                    if has_tvar(arg) {\n                        return true;\n                    }\n                }\n            }\n            false\n        }\n        Type::TVar(_) => true,\n    }\n}\n\npub(crate) fn typing_expr(\n    expr: &parser::Expr,\n    ctx: &Context,\n) -> Result<(LangExpr, BTreeMap<u64, Lambda>), TypingErr> {\n    let mut expr = expr2typed_expr(expr)?;\n    let mut num_tv = 0;\n    let (_, sbst) = ctx.typing_expr(&mut expr, Sbst::new(), &mut VarType::new(), &mut num_tv)?;\n\n    expr.apply_sbst(&sbst);\n\n    // check call only exported functions\n    ctx.check_expr_type(\n        &expr,\n        &mut FunTypes::new(),\n        &mut VarType::new(),\n        &Sbst::new(),\n        &Effect::IO,\n        false,\n    )?;\n\n    exhaustive_expr(&expr, ctx)?;\n\n    // capture free variables\n    // TODO: should be cached\n    let mut funs = BTreeSet::new();\n    for name in ctx.funs.keys() {\n        funs.insert(name.to_string());\n    }\n\n    let mut ident = ctx.lambda_ident;\n    let mut lambda = BTreeMap::new();\n    get_free_var_expr(\n        &mut expr,\n        &funs,\n        &mut VarType::new(),\n        &mut Vec::new(),\n        &mut ident,\n        &mut lambda,\n    );\n\n    for (_, v) in lambda.iter_mut() {\n        tail_call(&mut v.expr);\n    }\n\n    Ok((expr, lambda))\n}\n\npub fn exprs2context(typing_context: TypingContext) -> Result<Context, TypingErr> {\n    let mut funs = BTreeMap::new();\n    let mut ext_funs = BTreeMap::new();\n    let mut ext_ffi = BTreeMap::new();\n    let mut data = BTreeMap::new();\n    let msg = \"top expression must be data, defun, or export\";\n\n    for e in typing_context.exprs.iter() {\n        match e {\n            parser::Expr::Apply(es, _) => {\n                let mut iter = es.iter();\n\n                match iter.next() {\n                    Some(parser::Expr::ID(id, _)) => {\n                        if id == \"defun\" || id == \"export\" {\n                            let f = expr2defun(e)?;\n\n                            if ext_funs.contains_key(&f.id.id) {\n                                let msg = format!(\"{} is multiply defined\", f.id.id);\n                                return Err(TypingErr { msg, pos: f.id.pos });\n                            }\n\n                            if let btree_map::Entry::Vacant(entry) = funs.entry(f.id.id.to_string())\n                            {\n                                entry.insert(f);\n                            } else {\n                                let msg = format!(\"{} is multiply defined\", f.id.id);\n                                return Err(TypingErr { msg, pos: f.id.pos });\n                            }\n                        } else if id == \"extern\" {\n                            let f = expr2extern(e)?;\n\n                            if funs.contains_key(&f.id.id) {\n                                let msg = format!(\"{} is multiply defined\", f.id.id);\n                                return Err(TypingErr { msg, pos: f.id.pos });\n                            }\n\n                            if let btree_map::Entry::Vacant(entry) =\n                                ext_funs.entry(f.id.id.to_string())\n                            {\n                                entry.insert(f);\n                            } else {\n                                let msg = format!(\"{} is multiply defined\", f.id.id);\n                                return Err(TypingErr { msg, pos: f.id.pos });\n                            }\n                        } else if id == \"data\" {\n                            let d = expr2data(e)?;\n                            if data.contains_key(&d.name.id.id) {\n                                let msg = format!(\"data type {} is multiply defined\", d.name.id.id);\n                                return Err(TypingErr {\n                                    msg,\n                                    pos: d.name.pos,\n                                });\n                            }\n\n                            data.insert(d.name.id.id.clone(), d);\n                        } else if id == \"macro\" {\n                            // Do nothing.\n                        } else {\n                            return Err(TypingErr::new(msg, e));\n                        }\n                    }\n                    _ => {\n                        return Err(TypingErr::new(msg, e));\n                    }\n                }\n            }\n            _ => {\n                return Err(TypingErr::new(msg, e));\n            }\n        }\n    }\n\n    for ffi in typing_context.ext_funs.iter() {\n        ext_ffi.insert(ffi.name(), ffi.ffi());\n    }\n\n    let mut ctx = Context::new(funs, ext_funs, ext_ffi, data, typing_context.macros);\n    ctx.typing()?;\n\n    Ok(ctx)\n}\n\n/// $DATA := ( data $DATA_NAME $MEMBER+ )\nfn expr2data(expr: &parser::Expr) -> Result<DataType, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, pos) => {\n            let mut iter = exprs.iter();\n            iter.next(); // must be \"data\"\n\n            // $DATA_NAME\n            let data_name = match iter.next() {\n                Some(e) => expr2data_name(e)?,\n                _ => return Err(TypingErr::new(\"require data name\", expr)),\n            };\n\n            // $MEMBER+\n            let mut mems = Vec::new();\n            for mem in iter {\n                let data_mem = expr2data_mem(mem)?;\n                mems.push(data_mem);\n            }\n\n            Ok(DataType {\n                name: data_name,\n                members: mems,\n                pos: *pos,\n            })\n        }\n        _ => Err(TypingErr::new(\"syntax error on data definition\", expr)),\n    }\n}\n\n/// $DATA_NAME := $TID | ( $TID $ID* )\nfn expr2data_name(expr: &parser::Expr) -> Result<DataTypeName, TypingErr> {\n    match expr {\n        parser::Expr::ID(_, pos) => {\n            let tid = expr2type_id(expr)?;\n            Ok(DataTypeName {\n                id: tid,\n                type_args: Vec::new(),\n                pos: *pos,\n            })\n        }\n        parser::Expr::Apply(exprs, pos) => {\n            let mut args = Vec::new();\n            let mut iter = exprs.iter();\n            let tid;\n\n            match iter.next() {\n                Some(e) => {\n                    tid = expr2type_id(e)?;\n                }\n                _ => {\n                    return Err(TypingErr::new(\n                        \"must type identifier (with type arguments)\",\n                        expr,\n                    ))\n                }\n            }\n\n            for it in iter {\n                let id = expr2id(it)?;\n                args.push(id);\n            }\n\n            Ok(DataTypeName {\n                id: tid,\n                type_args: args,\n                pos: *pos,\n            })\n        }\n        _ => Err(TypingErr::new(\n            \"must type identifier (with type arguments)\",\n            expr,\n        )),\n    }\n}\n\nfn expr2type_id(expr: &parser::Expr) -> Result<TIDNode, TypingErr> {\n    match expr {\n        parser::Expr::ID(id, pos) => match id.chars().next() {\n            Some(c) => {\n                if c.is_ascii_uppercase() {\n                    Ok(TIDNode {\n                        id: id.to_string(),\n                        pos: *pos,\n                    })\n                } else {\n                    Err(TypingErr::new(\"the first character must be captal\", expr))\n                }\n            }\n            _ => Err(TypingErr::new(\"error\", expr)),\n        },\n        _ => Err(TypingErr::new(\"must be type identifier\", expr)),\n    }\n}\n\nfn expr2id(expr: &parser::Expr) -> Result<IDNode, TypingErr> {\n    match expr {\n        parser::Expr::ID(id, pos) => match id.chars().next() {\n            Some(c) => {\n                if c.is_ascii_uppercase() {\n                    Err(TypingErr::new(\n                        \"the first character must not be captal\",\n                        expr,\n                    ))\n                } else {\n                    Ok(IDNode {\n                        id: id.to_string(),\n                        pos: *pos,\n                        ty: None,\n                    })\n                }\n            }\n            _ => Err(TypingErr::new(\"error\", expr)),\n        },\n        _ => Err(TypingErr::new(\"must be identifier\", expr)),\n    }\n}\n\n/// $MEMBER := $TID | ( $TID $TYPE* )\nfn expr2data_mem(expr: &parser::Expr) -> Result<DataTypeMem, TypingErr> {\n    match expr {\n        parser::Expr::ID(_, pos) => {\n            // $TID\n            let tid = expr2type_id(expr)?;\n            Ok(DataTypeMem {\n                id: tid,\n                types: Vec::new(),\n                pos: *pos,\n            })\n        }\n        parser::Expr::Apply(exprs, pos) => {\n            // ( $TID $TYPE* )\n            let mut iter = exprs.iter();\n            let tid = match iter.next() {\n                Some(e) => expr2type_id(e)?,\n                _ => return Err(TypingErr::new(\"must type identifier\", expr)),\n            };\n\n            let mut types = Vec::new();\n            for it in iter {\n                let pt = expr2type(it)?;\n                types.push(pt);\n            }\n\n            Ok(DataTypeMem {\n                id: tid,\n                types,\n                pos: *pos,\n            })\n        }\n        _ => Err(TypingErr::new(\"must be type identifier (with types)\", expr)),\n    }\n}\n\n/// Convert `parser::Expr`, which is untyped to `Extern`, which is typed.\n///\n/// $EXTERN := ( extern $ID $TYPE_ARROW )\nfn expr2extern(expr: &parser::Expr) -> Result<Extern, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, _pos) => {\n            let mut iter = exprs.iter();\n\n            // extern\n            match iter.next() {\n                Some(parser::Expr::ID(id, _)) => {\n                    if id != \"extern\" {\n                        return Err(TypingErr::new(\"require extern\", expr));\n                    }\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require extern\", expr));\n                }\n            }\n\n            // $ID\n            let id = match iter.next() {\n                Some(e) => expr2id(e)?,\n                _ => {\n                    return Err(TypingErr::new(\"require function name\", expr));\n                }\n            };\n\n            // $TYPE_ARROW\n            let pos_ty;\n            let (args, ret) = match iter.next() {\n                Some(e) => {\n                    pos_ty = e.get_pos();\n                    expr2type_arrow(e)?\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require function type\", expr));\n                }\n            };\n\n            Ok(Extern {\n                id,\n                fun_type: TypeExpr::Fun(TEFunNode {\n                    effect: Effect::IO,\n                    args,\n                    ret: Box::new(ret),\n                    pos: pos_ty,\n                }),\n                ty: None,\n            })\n        }\n        _ => Err(TypingErr::new(\"syntax error on extern\", expr)),\n    }\n}\n\n/// Convert `parser::Expr`, which is untyped to `Defun`, which is typed.\n///\n/// $DEFUN := ( $HEAD_DEFUN $ID ( $ID* ) $TYPE_FUN $EXPR )\nfn expr2defun(expr: &parser::Expr) -> Result<Defun, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, pos) => {\n            let mut iter = exprs.iter();\n\n            // $HEAD_DEFUN := export | defun\n            let exported = match iter.next() {\n                Some(parser::Expr::ID(id, _)) => id == \"export\",\n                _ => {\n                    return Err(TypingErr::new(\"require defun or export\", expr));\n                }\n            };\n\n            // $ID\n            let id = match iter.next() {\n                Some(e) => expr2id(e)?,\n                _ => {\n                    return Err(TypingErr::new(\"require function name\", expr));\n                }\n            };\n\n            // ( $ID* )\n            let mut args = Vec::new();\n            match iter.next() {\n                Some(parser::Expr::Apply(exprs, _)) => {\n                    for it in exprs.iter() {\n                        let arg = expr2id(it)?;\n                        args.push(arg);\n                    }\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require arguments\", expr));\n                }\n            }\n\n            // $TYPE_FUN\n            let fun = match iter.next() {\n                Some(e) => expr2type_fun(e)?,\n                _ => {\n                    return Err(TypingErr::new(\"require function type\", expr));\n                }\n            };\n\n            // $EXPR\n            let body = match iter.next() {\n                Some(e) => expr2typed_expr(e)?,\n                _ => {\n                    return Err(TypingErr::new(\"require expression\", expr));\n                }\n            };\n\n            let effect = match &fun {\n                TypeExpr::Fun(e) => e.effect.clone(),\n                _ => {\n                    panic!(\"failed to get effect\");\n                }\n            };\n\n            Ok(Defun {\n                exported,\n                id,\n                args,\n                fun_type: fun,\n                effect,\n                expr: body,\n                pos: *pos,\n                ty: None,\n            })\n        }\n        _ => Err(TypingErr::new(\"syntax error on function definition\", expr)),\n    }\n}\n\n/// $TYPE_ARROW = ( -> $TYPES $TYPE )\nfn expr2type_arrow(expr: &parser::Expr) -> Result<(Vec<TypeExpr>, TypeExpr), TypingErr> {\n    let args;\n    let ret;\n    match expr {\n        parser::Expr::Apply(exprs2, _) => {\n            let mut iter = exprs2.iter();\n            let e2 = iter.next();\n            match e2 {\n                Some(parser::Expr::ID(arr, _)) => {\n                    if arr != \"->\" {\n                        return Err(TypingErr::new(\"must be \\\"->\\\"\", e2.unwrap()));\n                    }\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require \\\"->\\\"\", expr));\n                }\n            }\n\n            // $TYPES\n            match iter.next() {\n                Some(t) => {\n                    args = expr2types(t)?;\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require types for arguments\", expr));\n                }\n            }\n\n            // $TYPE\n            match iter.next() {\n                Some(t) => {\n                    ret = expr2type(t)?;\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require type for return value\", expr));\n                }\n            }\n        }\n        _ => {\n            return Err(TypingErr::new(\"require function type\", expr));\n        }\n    }\n\n    Ok((args, ret))\n}\n\n/// $TYPE_FUN := ( $EFFECT $TYPE_ARROW )\nfn expr2type_fun(expr: &parser::Expr) -> Result<TypeExpr, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, _pos) => {\n            let mut iter = exprs.iter();\n\n            // $EFFECT := Pure | IO\n            let effect;\n            let e = iter.next();\n            match e {\n                Some(parser::Expr::ID(eff, _)) => {\n                    if eff == \"IO\" {\n                        effect = Effect::IO;\n                    } else if eff == \"Pure\" {\n                        effect = Effect::Pure;\n                    } else {\n                        return Err(TypingErr::new(\n                            \"effect must be \\\"Pure\\\" or \\\"IO\\\"\",\n                            e.unwrap(),\n                        ));\n                    }\n                }\n                _ => {\n                    return Err(TypingErr::new(\"invalid effect\", expr));\n                }\n            }\n\n            // $TYPE_ARROW\n            if let Some(e1) = iter.next() {\n                let (args, ret) = expr2type_arrow(e1)?;\n                Ok(TypeExpr::Fun(TEFunNode {\n                    effect,\n                    args,\n                    ret: Box::new(ret),\n                    pos: e1.get_pos(),\n                }))\n            } else {\n                Err(TypingErr::new(\"require a function type\", expr))\n            }\n        }\n        _ => Err(TypingErr::new(\"must be function type\", expr)),\n    }\n}\n\n/// $TYPES := ( $TYPE* )\nfn expr2types(expr: &parser::Expr) -> Result<Vec<TypeExpr>, TypingErr> {\n    match expr {\n        parser::Expr::Apply(types, _) => {\n            // ( $TYPES* )\n            Ok(list_types2vec_types(types)?)\n        }\n        _ => Err(TypingErr::new(\"require types of arguments\", expr)),\n    }\n}\n\n/// $TYPE := Int | Bool | String | Char | $TYPE_LIST | $TYPE_TUPLE | $TYPE_FUN | $TYPE_DATA | $ID\nfn expr2type(expr: &parser::Expr) -> Result<TypeExpr, TypingErr> {\n    match expr {\n        parser::Expr::ID(id, pos) => {\n            // Int | Bool | String | $TID\n            match id.as_ref() {\n                \"Int\" => Ok(TypeExpr::Int(TEIntNode)),\n                \"Bool\" => Ok(TypeExpr::Bool(TEBoolNode)),\n                \"String\" => Ok(TypeExpr::String(TEStringNode)),\n                \"Char\" => Ok(TypeExpr::Char(TECharNode)),\n                _ => {\n                    let c = id.chars().next().unwrap();\n                    if c.is_ascii_uppercase() {\n                        let tid = expr2type_id(expr)?;\n                        Ok(TypeExpr::Data(TEDataNode {\n                            id: tid,\n                            type_args: Vec::new(),\n                            pos: *pos,\n                        }))\n                    } else {\n                        Ok(TypeExpr::Id(expr2id(expr)?))\n                    }\n                }\n            }\n        }\n        parser::Expr::List(list, _) => {\n            // $TYPE_LIST := '( $TYPE )\n            if list.len() != 1 {\n                return Err(TypingErr::new(\n                    \"require exactly one type as a type argument for list type\",\n                    expr,\n                ));\n            }\n\n            match list.iter().next() {\n                Some(e) => {\n                    let ty = Box::new(expr2type(e)?);\n                    Ok(TypeExpr::List(TEListNode {\n                        ty,\n                        pos: e.get_pos(),\n                    }))\n                }\n                _ => Err(TypingErr::new(\"require type\", expr)),\n            }\n        }\n        parser::Expr::Tuple(tuple, pos) => {\n            // $TYPE_TUPLE := [ $TYPE* ]\n            let mut types = Vec::new();\n            for it in tuple {\n                types.push(expr2type(it)?);\n            }\n\n            Ok(TypeExpr::Tuple(TETupleNode {\n                ty: types,\n                pos: *pos,\n            }))\n        }\n        parser::Expr::Apply(exprs, pos) => {\n            // ( $TID $TYPE* )\n            let mut iter = exprs.iter();\n\n            // $TID\n            let e = iter.next();\n            let tid = match e {\n                Some(parser::Expr::ID(id, _)) => {\n                    // $TYPE_FUN\n                    if id == \"Pure\" || id == \"IO\" {\n                        let ty = expr2type_fun(expr)?;\n                        return Ok(ty);\n                    }\n                    expr2type_id(e.unwrap())?\n                }\n                _ => {\n                    return Err(TypingErr::new(\"require type\", expr));\n                }\n            };\n\n            // $TYPE*\n            let mut args = Vec::new();\n            for it in iter {\n                args.push(expr2type(it)?);\n            }\n\n            Ok(TypeExpr::Data(TEDataNode {\n                id: tid,\n                type_args: args,\n                pos: *pos,\n            }))\n        }\n        _ => Err(TypingErr::new(\"must be type\", expr)),\n    }\n}\n\nfn list_types2vec_types(exprs: &LinkedList<parser::Expr>) -> Result<Vec<TypeExpr>, TypingErr> {\n    let mut v = Vec::new();\n    for e in exprs {\n        v.push(expr2type(e)?);\n    }\n\n    Ok(v)\n}\n\n/// Convert `parser::Expr`, which is untyped to `LangExpr`, which is typed.\n///\n/// $EXPR := $LITERAL | $ID | $TID | $LET | $IF | $LAMBDA | $MATCH | $LIST | $TUPLE | $GENDATA | $APPLY\nfn expr2typed_expr(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {\n    match expr {\n        parser::Expr::Char(c, pos) => Ok(LangExpr::LitChar(CharNode {\n            c: *c,\n            pos: *pos,\n            ty: Some(ty_string()),\n        })),\n        parser::Expr::Str(str, pos) => Ok(LangExpr::LitStr(StrNode {\n            str: str.clone(),\n            pos: *pos,\n            ty: Some(ty_string()),\n        })),\n        parser::Expr::Num(num, pos) => Ok(LangExpr::LitNum(NumNode {\n            num: num.clone(),\n            pos: *pos,\n            ty: Some(ty_int()),\n        })),\n        parser::Expr::Bool(val, pos) => Ok(LangExpr::LitBool(BoolNode {\n            val: *val,\n            pos: *pos,\n            ty: Some(ty_bool()),\n        })),\n        parser::Expr::ID(id, pos) => {\n            let c = id.chars().next().unwrap();\n            if c.is_ascii_uppercase() {\n                // $TID\n                let tid = expr2type_id(expr)?;\n                Ok(LangExpr::DataExpr(DataNode {\n                    label: tid,\n                    exprs: Vec::new(),\n                    pos: *pos,\n                    ty: None,\n                }))\n            } else {\n                Ok(LangExpr::IDExpr(IDNode {\n                    id: id.to_string(),\n                    pos: *pos,\n                    ty: None,\n                }))\n            }\n        }\n        parser::Expr::List(list, pos) => {\n            let mut elms = Vec::new();\n            for it in list {\n                elms.push(expr2typed_expr(it)?);\n            }\n            Ok(LangExpr::ListExpr(Exprs {\n                exprs: elms,\n                pos: *pos,\n                ty: None,\n            }))\n        }\n        parser::Expr::Tuple(tuple, pos) => {\n            let mut elms = Vec::new();\n            for it in tuple {\n                elms.push(expr2typed_expr(it)?);\n            }\n            Ok(LangExpr::TupleExpr(Exprs {\n                exprs: elms,\n                pos: *pos,\n                ty: None,\n            }))\n        }\n        parser::Expr::Apply(exprs, pos) => {\n            if exprs.is_empty() {\n                return Err(TypingErr::new(\"empty expression\", expr));\n            }\n\n            let mut iter = exprs.iter();\n\n            match iter.next() {\n                Some(parser::Expr::ID(id, _)) => {\n                    let c = id.chars().next().unwrap();\n                    if c.is_ascii_uppercase() {\n                        // $TID\n                        return expr2data_expr(expr);\n                    } else if id == \"if\" {\n                        return expr2if(expr);\n                    } else if id == \"let\" {\n                        return expr2let(expr);\n                    } else if id == \"match\" {\n                        return expr2match(expr);\n                    } else if id == \"lambda\" {\n                        return expr2lambda(expr);\n                    }\n                }\n                Some(_) => (),\n                None => {\n                    return Err(TypingErr::new(\"require function application\", expr));\n                }\n            }\n\n            let mut elms = Vec::new();\n            for it in exprs {\n                elms.push(expr2typed_expr(it)?);\n            }\n            Ok(LangExpr::ApplyExpr(Apply {\n                exprs: elms,\n                pos: *pos,\n                is_tail: false,\n                ty: None,\n            }))\n        }\n    }\n}\n\n/// $GENDATA := ( $TID $EXPR* )\nfn expr2data_expr(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {\n    let exprs = match expr {\n        parser::Expr::Apply(e, _) => e,\n        _ => {\n            return Err(TypingErr::new(\"not data expression\", expr));\n        }\n    };\n\n    let mut iter = exprs.iter();\n    let tid = expr2type_id(iter.next().unwrap())?;\n\n    let mut v = Vec::new();\n    for e in iter {\n        v.push(expr2typed_expr(e)?);\n    }\n\n    Ok(LangExpr::DataExpr(DataNode {\n        label: tid,\n        exprs: v,\n        pos: expr.get_pos(),\n        ty: None,\n    }))\n}\n\n/// $IF := ( if $EXPR $EXPR $EXPR )\nfn expr2if(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {\n    let exprs = match expr {\n        parser::Expr::Apply(e, _) => e,\n        _ => {\n            return Err(TypingErr::new(\"not if expression\", expr));\n        }\n    };\n\n    let mut iter = exprs.iter();\n    iter.next(); // must be \"if\"\n\n    let f = |next, msg| match next {\n        Some(e) => expr2typed_expr(e),\n        _ => Err(TypingErr::new(msg, expr)),\n    };\n\n    let cond = f(iter.next(), \"if requires condition\")?;\n    let then = f(iter.next(), \"if requires then expression\")?;\n    let else_expr = f(iter.next(), \"if requires else expression\")?;\n\n    Ok(LangExpr::IfExpr(Box::new(IfNode {\n        cond_expr: cond,\n        then_expr: then,\n        else_expr,\n        pos: expr.get_pos(),\n        ty: None,\n    })))\n}\n\n/// $LET := ( let ( $DEFVAR+ ) $EXPR )\nfn expr2let(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {\n    let exprs = match expr {\n        parser::Expr::Apply(e, _) => e,\n        _ => {\n            return Err(TypingErr::new(\"not apply expression\", expr));\n        }\n    };\n\n    let mut iter = exprs.iter();\n    iter.next(); // must be \"let\"\n\n    // ( $DEFVAR+ )\n    let mut def_vars = Vec::new();\n    let e = iter.next();\n    match e {\n        Some(parser::Expr::Apply(dvs, _)) => {\n            if dvs.is_empty() {\n                return Err(TypingErr::new(\"require variable binding\", e.unwrap()));\n            }\n\n            for it in dvs.iter() {\n                def_vars.push(expr2def_vars(it)?);\n            }\n        }\n        _ => {\n            return Err(TypingErr::new(\"require variable binding\", expr));\n        }\n    }\n\n    // $EXPR\n    let e = iter.next();\n    let body = match e {\n        Some(body_expr) => expr2typed_expr(body_expr)?,\n        _ => {\n            return Err(TypingErr::new(\"require body\", expr));\n        }\n    };\n\n    Ok(LangExpr::LetExpr(Box::new(LetNode {\n        def_vars,\n        expr: body,\n        pos: expr.get_pos(),\n        ty: None,\n    })))\n}\n\n/// $LETPAT := $ID | [ $LETPAT+ ] | ($TID $LETPAT+ )\nfn expr2letpat(expr: &parser::Expr) -> Result<Pattern, TypingErr> {\n    match expr {\n        parser::Expr::ID(id, pos) => {\n            // $ID\n            let c = id.chars().next().unwrap();\n            if c.is_ascii_uppercase() {\n                Err(TypingErr::new(\"invalid pattern\", expr))\n            } else {\n                Ok(Pattern::PatID(IDNode {\n                    id: id.to_string(),\n                    pos: *pos,\n                    ty: None,\n                }))\n            }\n        }\n        parser::Expr::Tuple(tuple, pos) => {\n            // [ $LETPAT+ ]\n            if tuple.is_empty() {\n                return Err(TypingErr::new(\"require at least one pattern\", expr));\n            }\n\n            let mut pattern = Vec::new();\n            for it in tuple {\n                pattern.push(expr2letpat(it)?);\n            }\n\n            Ok(Pattern::PatTuple(PatTupleNode {\n                pattern,\n                pos: *pos,\n                ty: None,\n            }))\n        }\n        parser::Expr::Apply(exprs, pos) => {\n            // ($TID $LETPAT+ )\n            if exprs.len() < 2 {\n                return Err(TypingErr::new(\n                    \"require label and at least one pattern\",\n                    expr,\n                ));\n            }\n\n            let mut iter = exprs.iter();\n            let tid = expr2type_id(iter.next().unwrap())?;\n\n            let mut v = Vec::new();\n            for it in iter {\n                v.push(expr2letpat(it)?);\n            }\n\n            Ok(Pattern::PatData(PatDataNode {\n                label: tid,\n                pattern: v,\n                pos: *pos,\n                ty: None,\n            }))\n        }\n        _ => Err(TypingErr::new(\"invalid pattern\", expr)),\n    }\n}\n\n/// $DEFVAR := ( $LETPAT $EXPR )\nfn expr2def_vars(expr: &parser::Expr) -> Result<DefVar, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, pos) => {\n            if exprs.len() != 2 {\n                return Err(TypingErr::new(\"invalid variable definition\", expr));\n            }\n\n            let mut iter = exprs.iter();\n\n            let pattern = expr2letpat(iter.next().unwrap())?; // $LETPAT\n            let body = expr2typed_expr(iter.next().unwrap())?; // $EXPR\n\n            Ok(DefVar {\n                pattern,\n                expr: body,\n                pos: *pos,\n                ty: None,\n            })\n        }\n        _ => Err(TypingErr::new(\"must be variable definition(s)\", expr)),\n    }\n}\n\n/// $PATTERN := $LITERAL | $ID | $TID | [ $PATTERN+ ] | ( $TID $PATTERN* ) | '()\nfn expr2mpat(expr: &parser::Expr) -> Result<Pattern, TypingErr> {\n    match expr {\n        parser::Expr::ID(id, pos) => {\n            let c = id.chars().next().unwrap();\n            if c.is_ascii_uppercase() {\n                // $TID\n                let tid = expr2type_id(expr)?;\n                Ok(Pattern::PatData(PatDataNode {\n                    label: tid,\n                    pattern: Vec::new(),\n                    pos: *pos,\n                    ty: None,\n                }))\n            } else {\n                // $ID\n                let id_node = expr2id(expr)?;\n                Ok(Pattern::PatID(id_node))\n            }\n        }\n        parser::Expr::Char(c, pos) => {\n            // $LITERAL\n            Ok(Pattern::PatChar(CharNode {\n                c: *c,\n                pos: *pos,\n                ty: Some(ty_string()),\n            }))\n        }\n        parser::Expr::Str(str, pos) => {\n            // $LITERAL\n            Ok(Pattern::PatStr(StrNode {\n                str: str.clone(),\n                pos: *pos,\n                ty: Some(ty_string()),\n            }))\n        }\n        parser::Expr::Bool(val, pos) => {\n            // $LITERAL\n            Ok(Pattern::PatBool(BoolNode {\n                val: *val,\n                pos: *pos,\n                ty: Some(ty_bool()),\n            }))\n        }\n        parser::Expr::Num(num, pos) => {\n            // $LITERAL\n            Ok(Pattern::PatNum(NumNode {\n                num: num.clone(),\n                pos: *pos,\n                ty: Some(ty_int()),\n            }))\n        }\n        parser::Expr::Tuple(exprs, pos) => {\n            // [ $PATTERN+ ]\n            let mut pattern = Vec::new();\n            for it in exprs {\n                pattern.push(expr2mpat(it)?);\n            }\n\n            Ok(Pattern::PatTuple(PatTupleNode {\n                pattern,\n                pos: *pos,\n                ty: None,\n            }))\n        }\n        parser::Expr::Apply(exprs, pos) => {\n            // ( $TID $PATTERN* )\n            let mut iter = exprs.iter();\n            let first = iter.next();\n\n            let tid = match first {\n                Some(e) => expr2type_id(e)?,\n                _ => {\n                    return Err(TypingErr::new(\"invalid pattern\", expr));\n                }\n            };\n\n            let mut pattern = Vec::new();\n            for it in iter {\n                pattern.push(expr2mpat(it)?);\n            }\n\n            Ok(Pattern::PatData(PatDataNode {\n                label: tid,\n                pattern,\n                pos: *pos,\n                ty: None,\n            }))\n        }\n        parser::Expr::List(list, pos) => {\n            if !list.is_empty() {\n                return Err(TypingErr::new(\"list pattern is not supported\", expr));\n            }\n\n            Ok(Pattern::PatNil(PatNilNode {\n                pos: *pos,\n                ty: None,\n            }))\n        }\n    }\n}\n\n/// $CASE := ( $PATTERN $EXPR )\nfn expr2case(expr: &parser::Expr) -> Result<MatchCase, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, pos) => {\n            if exprs.len() != 2 {\n                return Err(TypingErr::new(\"case require exactly 2 expressions\", expr));\n            }\n\n            let mut iter = exprs.iter();\n            let pattern = expr2mpat(iter.next().unwrap())?;\n            let body = expr2typed_expr(iter.next().unwrap())?;\n\n            Ok(MatchCase {\n                pattern,\n                expr: body,\n                pos: *pos,\n                ty: None,\n            })\n        }\n        _ => Err(TypingErr::new(\"invalid case\", expr)),\n    }\n}\n\n/// $MATCH := ( match $EXPR $CASE+ )\nfn expr2match(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {\n    match expr {\n        parser::Expr::Apply(exprs, pos) => {\n            let mut iter = exprs.iter();\n            iter.next(); // must be \"match\"\n\n            let cond = match iter.next() {\n                Some(e) => expr2typed_expr(e)?,\n                _ => {\n                    return Err(TypingErr::new(\"no condition\", expr));\n                }\n            };\n\n            let mut cases = Vec::new();\n            for it in iter {\n                cases.push(expr2case(it)?);\n            }\n\n            if cases.is_empty() {\n                return Err(TypingErr::new(\"require at least one case\", expr));\n            }\n\n            let node = MatchNode {\n                expr: cond,\n                cases,\n                pos: *pos,\n                ty: None,\n            };\n            Ok(LangExpr::MatchExpr(Box::new(node)))\n        }\n        _ => Err(TypingErr::new(\"invalid match\", expr)),\n    }\n}\n\n/// $LAMBDA := (lambda ($ID*) $EXPR)\nfn expr2lambda(expr: &parser::Expr) -> Result<LangExpr, TypingErr> {\n    let exprs;\n    let pos;\n    match expr {\n        parser::Expr::Apply(e, p) => {\n            exprs = e;\n            pos = p;\n        }\n        _ => {\n            return Err(TypingErr::new(\"not lambda expression\", expr));\n        }\n    }\n\n    let mut iter = exprs.iter();\n    iter.next(); // must be \"lambda\"\n\n    // get arguments\n    let args = match iter.next() {\n        Some(parser::Expr::Apply(e, _)) => e,\n        _ => {\n            return Err(TypingErr::new(\"require arguments\", expr));\n        }\n    };\n\n    let mut v = Vec::new();\n    for a in args {\n        v.push(expr2id(a)?);\n    }\n\n    // get expression\n    let body = match iter.next() {\n        Some(e) => expr2typed_expr(e)?,\n        _ => {\n            return Err(TypingErr::new(\"require arguments\", expr));\n        }\n    };\n\n    Ok(LangExpr::LambdaExpr(Box::new(Lambda {\n        args: v,\n        expr: body,\n        pos: *pos,\n        vars: Vec::new(),\n        ident: 0,\n        ty: None,\n    })))\n}\n\nimpl Type {\n    fn has_tvar(&self, id: ID) -> bool {\n        match self {\n            Type::TVar(n) => id == *n,\n            Type::TCon(tc) => tc.has_tvar(id),\n        }\n    }\n\n    fn apply_sbst(&self, sbst: &Sbst) -> Type {\n        match self {\n            Type::TVar(n) => match sbst.get(n) {\n                Some(t) => t.clone(),\n                None => self.clone(),\n            },\n            Type::TCon(tc) => tc.apply_sbst(sbst),\n        }\n    }\n}\n\nimpl Tycon {\n    fn has_tvar(&self, id: ID) -> bool {\n        if let Some(args) = &self.args {\n            for t in args {\n                if t.has_tvar(id) {\n                    return true;\n                }\n            }\n        }\n\n        false\n    }\n\n    fn apply_sbst(&self, sbst: &Sbst) -> Type {\n        let mut v = Vec::new();\n        if let Some(args) = &self.args {\n            for t in args {\n                v.push(t.apply_sbst(sbst));\n            }\n        }\n\n        Type::TCon(Tycon {\n            id: self.id.clone(),\n            args: if v.is_empty() { None } else { Some(v) },\n        })\n    }\n}\n\nfn unify(lhs: &Type, rhs: &Type) -> Option<Sbst> {\n    let mut sbst = Sbst::new();\n    match (lhs, rhs) {\n        (Type::TVar(id1), Type::TVar(id2)) => {\n            if id1 != id2 {\n                sbst.insert(*id1, rhs.clone());\n            }\n            Some(sbst)\n        }\n        (Type::TVar(id), _) => {\n            if rhs.has_tvar(*id) {\n                return None;\n            }\n            sbst.insert(*id, rhs.clone());\n            Some(sbst)\n        }\n        (_, Type::TVar(id)) => {\n            if lhs.has_tvar(*id) {\n                return None;\n            }\n            sbst.insert(*id, lhs.clone());\n            Some(sbst)\n        }\n        (Type::TCon(ty_lhs), Type::TCon(ty_rhs)) => {\n            if ty_lhs.id != ty_rhs.id {\n                return None;\n            }\n\n            match (&ty_lhs.args, &ty_rhs.args) {\n                (None, Some(_)) => None,\n                (Some(_), None) => None,\n                (None, None) => Some(sbst),\n                (Some(args1), Some(args2)) => {\n                    if args1.len() != args2.len() {\n                        return None;\n                    }\n\n                    for (t1, t2) in args1.iter().zip(args2.iter()) {\n                        let s = unify(&t1.apply_sbst(&sbst), &t2.apply_sbst(&sbst))?;\n                        sbst = compose(&s, &sbst);\n                    }\n                    Some(sbst)\n                }\n            }\n        }\n    }\n}\n\n/// - S: substitution\n/// - x: type variable\n/// - T: type\n///\n/// S := x : T, S\n///\n/// S1・S2\n/// compose(S1, S2) = {\n///   x : T.apply_sbst(S1) if x : T in S2\n///   x : T                if x : T in S1 and x not in domain(S2)\n/// }\nfn compose(s1: &Sbst, s2: &Sbst) -> Sbst {\n    let mut sbst = Sbst::new();\n\n    for (x, t) in s2.iter() {\n        sbst.insert(*x, t.apply_sbst(s1));\n    }\n\n    for (x, t) in s1.iter() {\n        sbst.entry(*x).or_insert_with(|| t.clone());\n    }\n\n    sbst\n}\n\n/// find tail call\nfn tail_call(expr: &mut LangExpr) {\n    let l = tail_call_expr(expr);\n\n    for e in l {\n        if let LangExpr::ApplyExpr(app) = e {\n            app.is_tail = true\n        }\n    }\n}\n\nfn tail_call_expr(expr: &mut LangExpr) -> LinkedList<&mut LangExpr> {\n    match expr {\n        LangExpr::ApplyExpr(_) => {\n            let mut l = LinkedList::new();\n            l.push_back(expr);\n            l\n        }\n        LangExpr::IfExpr(e) => {\n            let mut l = tail_call_expr(&mut e.then_expr);\n            l.append(&mut tail_call_expr(&mut e.else_expr));\n            l\n        }\n        LangExpr::MatchExpr(e) => {\n            let mut l = LinkedList::new();\n            for c in e.cases.iter_mut() {\n                l.append(&mut tail_call_expr(&mut c.expr));\n            }\n            l\n        }\n        LangExpr::LetExpr(e) => tail_call_expr(&mut e.expr),\n        LangExpr::LambdaExpr(e) => {\n            tail_call(&mut e.expr);\n            LinkedList::new()\n        }\n        _ => LinkedList::new(),\n    }\n}\n\nfn exhaustive_expr(expr: &LangExpr, ctx: &Context) -> Result<(), TypingErr> {\n    match expr {\n        LangExpr::MatchExpr(e) => exhaustive_match(e, ctx),\n        LangExpr::IfExpr(e) => exhaustive_if(e, ctx),\n        LangExpr::LetExpr(e) => exhaustive_let(e, ctx),\n        LangExpr::LambdaExpr(e) => exhaustive_expr(&e.expr, ctx),\n        LangExpr::DataExpr(e) => exhaustive_exprs(&e.exprs, ctx),\n        LangExpr::ApplyExpr(e) => exhaustive_exprs(&e.exprs, ctx),\n        LangExpr::ListExpr(e) => exhaustive_exprs(&e.exprs, ctx),\n        LangExpr::TupleExpr(e) => exhaustive_exprs(&e.exprs, ctx),\n        _ => Ok(()),\n    }\n}\n\nfn exhaustive_exprs(exprs: &[LangExpr], ctx: &Context) -> Result<(), TypingErr> {\n    for e in exprs {\n        exhaustive_expr(e, ctx)?;\n    }\n    Ok(())\n}\n\nfn exhaustive_let(expr: &LetNode, ctx: &Context) -> Result<(), TypingErr> {\n    for dv in &expr.def_vars {\n        exhaustive_expr(&dv.expr, ctx)?;\n    }\n\n    exhaustive_expr(&expr.expr, ctx)?;\n\n    Ok(())\n}\n\nfn exhaustive_if(expr: &IfNode, ctx: &Context) -> Result<(), TypingErr> {\n    exhaustive_expr(&expr.cond_expr, ctx)?;\n    exhaustive_expr(&expr.then_expr, ctx)?;\n    exhaustive_expr(&expr.else_expr, ctx)?;\n    Ok(())\n}\n\nfn exhaustive_match(expr: &MatchNode, ctx: &Context) -> Result<(), TypingErr> {\n    exhaustive_expr(&expr.expr, ctx)?;\n\n    let mut patterns = LinkedList::new();\n    for cs in &expr.cases {\n        patterns.push_back(&cs.pattern);\n    }\n\n    check_pattern_exhaustive(&patterns, ctx, &expr.pos)?;\n\n    for cs in &expr.cases {\n        exhaustive_expr(&cs.expr, ctx)?;\n    }\n\n    Ok(())\n}\n\nstruct Patterns<'a> {\n    pat: BTreeMap<(String, usize), LinkedList<&'a Pattern>>,\n}\n\nimpl<'a> Patterns<'a> {\n    fn new() -> Patterns<'a> {\n        Patterns {\n            pat: BTreeMap::new(),\n        }\n    }\n\n    fn insert(&mut self, label: &str, idx: usize, p: &'a Pattern) {\n        match self.pat.get_mut(&(label.to_string(), idx)) {\n            Some(lst) => {\n                lst.push_back(p);\n            }\n            None => {\n                let mut lst = LinkedList::new();\n                lst.push_back(p);\n                self.pat.insert((label.to_string(), idx), lst);\n            }\n        }\n    }\n}\n\nfn check_pattern_exhaustive(\n    patterns: &LinkedList<&Pattern>,\n    ctx: &Context,\n    pos: &Pos,\n) -> Result<(), TypingErr> {\n    if patterns.is_empty() {\n        return Err(TypingErr {\n            msg: \"no pattern\".to_string(),\n            pos: *pos,\n        });\n    }\n\n    let Some(ty) = patterns.front().unwrap().get_type() else {\n        return Ok(());\n    };\n\n    // list up labels of type\n    // example:\n    // if\n    //   (data (Maybe a)\n    //     (Just a)\n    //     Nothing)\n    // then\n    //   pat = [Just, Nothing]\n    let mut pat = BTreeSet::new();\n    match &ty {\n        Type::TCon(tc) => {\n            match tc.id.as_ref() {\n                \"Tuple\" => {\n                    pat.insert(\"Tuple\".to_string());\n                }\n                \"List\" => {\n                    pat.insert(\"Cons\".to_string());\n                    pat.insert(\"Nil\".to_string());\n                }\n                \"Bool\" => {\n                    pat.insert(\"true\".to_string());\n                    pat.insert(\"false\".to_string());\n                }\n                \"Int\" => {\n                    // integer type must be matched by general pattern\n                    pat.insert(\"'dummy\".to_string());\n                }\n                \"String\" => {\n                    // string type must be matched by general pattern\n                    pat.insert(\"'dummy\".to_string());\n                }\n                \"Char\" => {\n                    // char type must be matched by general pattern\n                    pat.insert(\"'dummy\".to_string());\n                }\n                _ => match ctx.data.get(&tc.id) {\n                    Some(data) => {\n                        pat = BTreeSet::new();\n                        for mem in &data.members {\n                            pat.insert(mem.id.id.clone());\n                        }\n                    }\n                    None => {\n                        let msg = format!(\"could not found \\\"{}\\\" type\", ty);\n                        return Err(TypingErr { msg, pos: *pos });\n                    }\n                },\n            }\n        }\n        _ => {\n            return Ok(());\n        }\n    }\n\n    // remove labels specified in patterns\n    // example 1:\n    // if\n    //   pat = [Just, Nothing]\n    //   and\n    //   (match (Just 10)\n    //     ((Just x) x))\n    // then\n    //   pat = [Nothing]\n    //\n    // if variable pattern occurs then \"is_all\" becomes true\n    // example 2:\n    // if\n    //   (match (Just 10)\n    //     (x x))\n    // then\n    //   is_all = true\n    let mut is_all = false;\n    for p in patterns {\n        match p {\n            Pattern::PatID(_) => {\n                is_all = true;\n            }\n            Pattern::PatData(p) => {\n                // TODO: warning\n                // if is_all then unreachable\n                pat.remove(&p.label.id);\n            }\n            Pattern::PatBool(p) => {\n                // TODO: warning\n                // if is_all then unreachable\n                if p.val {\n                    pat.remove(\"true\");\n                } else {\n                    pat.remove(\"false\");\n                }\n            }\n            Pattern::PatTuple(_) => {\n                // TODO: warning\n                // if is_all then unreachable\n                pat.remove(\"Tuple\");\n            }\n            Pattern::PatNil(_) => {\n                pat.remove(\"Nil\");\n            }\n            _ => {}\n        }\n    }\n\n    if is_all {\n        // success\n        Ok(())\n    } else if pat.is_empty() {\n        // success but need to check recursively\n        let mut ps = Patterns::new();\n        for p in patterns {\n            match p {\n                Pattern::PatData(e) => {\n                    for (i, p2) in e.pattern.iter().enumerate() {\n                        ps.insert(&e.label.id, i, p2);\n                    }\n                }\n                Pattern::PatTuple(e) => {\n                    for (i, p2) in e.pattern.iter().enumerate() {\n                        ps.insert(\"Tuple\", i, p2);\n                    }\n                }\n                _ => {}\n            }\n        }\n\n        for plst in ps.pat.values() {\n            check_pattern_exhaustive(plst, ctx, pos)?;\n        }\n\n        Ok(())\n    } else {\n        // fail\n        Err(TypingErr {\n            msg: \"pattern is not exhaustive\".to_string(),\n            pos: *pos,\n        })\n    }\n}\n"
  },
  {
    "path": "tests/embedded.rs",
    "content": "use blisp::embedded;\nuse num_bigint::{BigInt, ToBigInt};\n\n#[embedded]\nfn test_fun(\n    _z: BigInt,\n    _a: Vec<BigInt>,\n    _b: (BigInt, BigInt),\n    _c: Option<BigInt>,\n    _d: Result<BigInt, String>,\n) -> Option<BigInt> {\n    let temp = 5.to_bigint();\n    temp\n}\n\n#[embedded]\nfn add_four_ints(a: BigInt, b: (BigInt, BigInt), c: Option<BigInt>) -> Result<BigInt, String> {\n    let mut result = a + b.0 + b.1;\n    if let Some(n) = c {\n        result += n;\n    }\n\n    Ok(result)\n}\n\n#[embedded]\nfn no_return() {}\n\n#[test]\nfn test_embedded() {\n    // test_fun\n    let code = \"(export call_test_fun ()\n        (IO (-> () (Option Int)))\n        (test_fun 1 '(2 3) [4 5] (Some 6) (Ok 7))\n    )\";\n    let exprs = blisp::init(code, vec![Box::new(TestFun)]).unwrap();\n    let ctx = blisp::typing(exprs).unwrap();\n    let result = blisp::eval(\"(call_test_fun)\", &ctx).unwrap();\n\n    let front = result.front().unwrap().as_ref().unwrap();\n    assert_eq!(front, \"(Some 5)\");\n\n    // add_for_ints\n    let code = \"(export call_add_four_ints (n)\n        (IO (-> ((Option Int)) (Result Int String)))\n        (add_four_ints 1 [2 3] n)\n    )\";\n    let exprs = blisp::init(code, vec![Box::new(AddFourInts)]).unwrap();\n    let ctx = blisp::typing(exprs).unwrap();\n    let result = blisp::eval(\"(call_add_four_ints (Some 4))\", &ctx).unwrap();\n\n    let front = result.front().unwrap().as_ref().unwrap();\n    assert_eq!(front, \"(Ok 10)\");\n\n    // no_return\n    let code = \"(export call_no_return ()\n        (IO (-> () []))\n        (no_return)\n    )\";\n    let exprs = blisp::init(code, vec![Box::new(NoReturn)]).unwrap();\n    let ctx = blisp::typing(exprs).unwrap();\n    let result = blisp::eval(\"(call_no_return)\", &ctx).unwrap();\n    result.front().unwrap().as_ref().unwrap();\n}\n"
  },
  {
    "path": "tests/transpile.rs",
    "content": "use blisp;\n\n#[test]\nfn test_transpile() {\n    let expr = \"\n    (defun snoc (l y)\n    (Pure (-> (\n        '(t) t)\n    '(t)))\n    (match l\n        (nil (Cons y nil))\n        ((Cons h b) (Cons h (snoc b y)))))\n\n    (defun rev (l)\n    (Pure (-> (\n        '(t))\n    '(t)))\n    (match l\n        (nil nil)\n        ((Cons h t) (snoc (rev t) h))))\n        \";\n    let exprs = blisp::init(expr, vec![]).unwrap();\n    let ctx = blisp::typing(exprs).unwrap();\n\n    println!(\"{}\", blisp::transpile(&ctx));\n}\n"
  }
]