├── .gitignore ├── example ├── arrow1.ron ├── error.ron ├── right-assoc.ron ├── use-do-end-for-block.ron ├── use-percent-for-newline.ron ├── plus2.ron ├── succ.ron ├── arrow3.ron ├── plus10.ron ├── test_ambiguity3.ron ├── test_ambiguity.ron ├── multiple_use.ron ├── test_ambiguity2.ron ├── arrow2.ron ├── logic.utf8.ron ├── if.ron ├── type.ron ├── error-undefined-nonterminal.ron ├── plus.ron ├── error-rule-head.ron ├── error-syntax-undefined-operator.ron ├── reflexive-transitive-closure.ron ├── or.ron ├── error-unclosed-brace.ron ├── error-evaluation-simple.ron ├── error-rule-body.ron ├── ski.ron ├── ski.utf8.ron ├── error-op-missing-colon.ron ├── error-evaluation-type.ron ├── syntax.ron ├── error-missing-arrow.ron ├── and.ron ├── cont.ron ├── add.ron ├── evaluation-context.add.right-first.ron ├── evaluation-context.add.left-first.ron ├── evaluation-context.add.manual-expansion.ron ├── evaluation-context.add.ron ├── evaluation-context.add.recursive.ron ├── syntax-without-macro.ron ├── tapl.booleans.utf8.ron ├── parse.test.ron ├── tapl.booleans.ron ├── tapl.typed-booleans.ron ├── letcc.ron ├── ocaml.ron ├── tapl.arithmetic.ron ├── dcont.ron ├── lambda-full.ron ├── lambda-call-by-name.ron ├── lambda-call-by-value.ron ├── lambda-full-context.ron ├── tapl.typed-arithmetic.ron ├── lambda.ron ├── ml-peano.ron ├── tapl.base-type.ron ├── fspl.imp.ron ├── tapl.unit.ron ├── tapl.simply-typed-lambda.ron ├── tapl.ascription.ron ├── tapl.let.ron ├── tapl.typed-lambda.arith.ron ├── tapl.sum.ron ├── tapl.pair.ron ├── tapl.tuple.ron ├── tapl.record.ron ├── tapl.fix.ron ├── tapl.record.pattern.ron └── tapl.simple.full.ron ├── .trunk ├── .gitignore ├── configs │ ├── .markdownlint.yaml │ └── .shellcheckrc └── trunk.yaml ├── test-errors.sh ├── README.md └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | memo.* -------------------------------------------------------------------------------- /example/arrow1.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ -> _ 2 | 3 | 1 -> 2 4 | 5 | main { 6 | 1 -> x 7 | } -------------------------------------------------------------------------------- /example/error.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ -> _ 2 | 3 | 1 -> 2 4 | 2 -> 3 5 | 3 => 4 6 | 7 | main { 8 | 1 -> x 9 | } -------------------------------------------------------------------------------- /example/right-assoc.ron: -------------------------------------------------------------------------------- 1 | op 50 r : _ + _ 2 | op 10 : _ = _ 3 | 4 | main { 5 | < ((1 + 2) + (3 + 4)) = x > 6 | } -------------------------------------------------------------------------------- /.trunk/.gitignore: -------------------------------------------------------------------------------- 1 | *out 2 | *logs 3 | *actions 4 | *notifications 5 | *tools 6 | plugins 7 | user_trunk.yaml 8 | user.yaml 9 | tmp 10 | -------------------------------------------------------------------------------- /.trunk/configs/.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | # Prettier friendly markdownlint config (all formatting rules disabled) 2 | extends: markdownlint/style/prettier 3 | -------------------------------------------------------------------------------- /example/use-do-end-for-block.ron: -------------------------------------------------------------------------------- 1 | # test1 2 | # test2 3 | use do end for block 4 | 5 | op 50 : _ -> _ 6 | 7 | 1 -> 2 8 | 9 | main do 10 | 1 -> x 11 | end -------------------------------------------------------------------------------- /example/use-percent-for-newline.ron: -------------------------------------------------------------------------------- 1 | # test1 2 | # test2 3 | use % for newline 4 | op 50 : _ -> _ 5 | 6 | 1 -> 2 % 2 -> 3 7 | 8 | main { 9 | 1 -> x 10 | } -------------------------------------------------------------------------------- /example/plus2.ron: -------------------------------------------------------------------------------- 1 | op 50 : S _ 2 | op 50 : _ + _ = _ 3 | 4 | 0 + n = n 5 | (S n) + m = (S l) { 6 | n + m = l 7 | } 8 | 9 | main { 10 | S 0 + S S 0 = x 11 | } -------------------------------------------------------------------------------- /example/succ.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ + _ = _ 2 | op 50 : succ _ 3 | 4 | 0 + n = n 5 | succ m + n = succ p { 6 | m + n = p 7 | } 8 | 9 | main { 10 | succ 0 + succ 0 = x 11 | } -------------------------------------------------------------------------------- /example/arrow3.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ -> _ 2 | op 50 : _ => _ 3 | 4 | 1 -> 2; 2 -> 3; 5 | x => y { x -> z; z => y } 6 | x => y { x -> y } 7 | x => x 8 | 9 | main { 10 | 1 => x 11 | } -------------------------------------------------------------------------------- /example/plus10.ron: -------------------------------------------------------------------------------- 1 | op 20 : _ + _ 2 | op 10 : _ is _ 3 | op 10 : _ = _ 4 | 5 | a + b = c { 6 | 7 | } 8 | 9 | main { 10 | 10 + 20 = x 11 | x + 30 = y 12 | } -------------------------------------------------------------------------------- /example/test_ambiguity3.ron: -------------------------------------------------------------------------------- 1 | use % for newline 2 | use do end for block 3 | 4 | op 99 : _ _ 5 | op 99 : succ _ 6 | op 99 : map _ _ _ => _ 7 | 8 | main do 9 | succ 0 10 | end 11 | -------------------------------------------------------------------------------- /example/test_ambiguity.ron: -------------------------------------------------------------------------------- 1 | use % for newline 2 | use do end for block 3 | 4 | op 70 : ( _ , _ ) 5 | op 68 r : _ , _ 6 | op 100 : map _ _ _ => _ 7 | 8 | main do 9 | (1, 2) 10 | end 11 | -------------------------------------------------------------------------------- /example/multiple_use.ron: -------------------------------------------------------------------------------- 1 | # Test multiple use directives 2 | use % for newline 3 | use do end for block 4 | 5 | op 50 : _ -> _ 6 | 7 | 1 -> 2 % 2 -> 3 8 | 9 | main do 10 | 1 -> x 11 | end 12 | -------------------------------------------------------------------------------- /.trunk/configs/.shellcheckrc: -------------------------------------------------------------------------------- 1 | enable=all 2 | source-path=SCRIPTDIR 3 | disable=SC2154 4 | 5 | # If you're having issues with shellcheck following source, disable the errors via: 6 | # disable=SC1090 7 | # disable=SC1091 8 | -------------------------------------------------------------------------------- /example/test_ambiguity2.ron: -------------------------------------------------------------------------------- 1 | use % for newline 2 | use do end for block 3 | 4 | op 50 : if _ then _ else _ 5 | op 50 : if _ then _ 6 | op 100 : map _ with _ and _ to _ 7 | 8 | main do 9 | if 1 then 2 10 | end 11 | -------------------------------------------------------------------------------- /example/arrow2.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ -> _ 2 | op 50 : _ => _ 3 | 4 | 1 -> 2 5 | 2 -> 3 6 | 7 | x => y { 8 | x -> z 9 | z => y 10 | } 11 | x => y { 12 | x -> y 13 | } 14 | x => x 15 | 16 | main { 17 | 1 => x 18 | } -------------------------------------------------------------------------------- /example/logic.utf8.ron: -------------------------------------------------------------------------------- 1 | # 論理演算の例(UTF-8記号使用) 2 | op 10 : _ → _ 3 | op 50 : _ ∧ _ 4 | 5 | # AND 演算 6 | true ∧ true → true 7 | true ∧ false → false 8 | false ∧ true → false 9 | false ∧ false → false 10 | 11 | main { 12 | true ∧ false → x 13 | } 14 | 15 | -------------------------------------------------------------------------------- /example/if.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ |- _ => _ 2 | op 50 : if _ then _ else _ 3 | 4 | c |- 0 => 0 5 | c |- 1 => 1 6 | c |- true => true 7 | c |- if e1 then e2 else e3 => v { 8 | c |- e1 => true 9 | c |- e2 => v 10 | } 11 | 12 | main { 13 | _ |- if true then 0 else 1 => v 14 | } -------------------------------------------------------------------------------- /example/type.ron: -------------------------------------------------------------------------------- 1 | op 50 : if _ then _ else _ 2 | op 50 : _ |- _ : _ 3 | 4 | _ |- 0 : int 5 | _ |- true : bool 6 | c |- if e1 then e2 else e3 : t { 7 | c |- e1 : bool 8 | c |- e2 : t 9 | c |- e3 : t 10 | } 11 | 12 | main { 13 | _ |- if true then 0 else 0 : t 14 | } -------------------------------------------------------------------------------- /example/error-undefined-nonterminal.ron: -------------------------------------------------------------------------------- 1 | # Error test: undefined nonterminal symbol 2 | # Ts is referenced in T definition but not defined 3 | 4 | op 10 : _ => _ 5 | 6 | syntax { 7 | t ::= a | b 8 | T ::= Nat | Bool | ( Ts ) 9 | x ::= a | b 10 | } 11 | 12 | main { 13 | t? a 14 | } 15 | -------------------------------------------------------------------------------- /example/plus.ron: -------------------------------------------------------------------------------- 1 | # 演算子を宣言 2 | op 50 : S _ 3 | op 50 : _ plus _ is _ 4 | 5 | syntax { 6 | constants ::= Z 7 | } 8 | 9 | # 規則1 10 | Z plus n is n 11 | 12 | # 規則2 13 | (S n1) plus n2 is (S n) { 14 | n1 plus n2 is n 15 | } 16 | 17 | # 問い合わせ 18 | main { 19 | (S Z) plus (S Z) is x 20 | } -------------------------------------------------------------------------------- /example/error-rule-head.ron: -------------------------------------------------------------------------------- 1 | # エラーケース3: ルールヘッドの構文エラー 2 | 3 | op 100 : _ + _ 4 | op 50 : _ => _ 5 | op 30 : _ : _ 6 | 7 | syntax { 8 | t ::= n | t + t 9 | n ::= 0 | 1 | 2 10 | } 11 | 12 | 0 + 1 => 1 13 | 1 + 1 => 2 14 | 1 + 2 3 # エラー: => が欠けている(ルールヘッドのエラー) 15 | 16 | main { 17 | 1 + 1 => x 18 | } 19 | 20 | -------------------------------------------------------------------------------- /example/error-syntax-undefined-operator.ron: -------------------------------------------------------------------------------- 1 | # エラーケース2: syntaxブロック内で未定義の演算子を使用 2 | 3 | op 100 : _ + _ 4 | op 50 : if _ then _ else _ 5 | 6 | syntax { 7 | t ::= n | t + t | if t then t else t | t && t # エラー: && 演算子が未定義 8 | n ::= 0 | 1 | 2 9 | } 10 | 11 | 0 + 1 => 1 12 | 1 + 1 => 2 13 | 14 | main { 15 | 1 + 1 => x 16 | } 17 | 18 | -------------------------------------------------------------------------------- /example/reflexive-transitive-closure.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ -> _ 2 | op 50 : _ --> _ 3 | 4 | # 1-step reduction 5 | 1 -> 2 6 | 2 -> 3 7 | 2 -> 5 8 | 3 -> 4 9 | 10 | # reflexive transitive closure of -> 11 | x --> y { 12 | x -> z 13 | z --> y 14 | } 15 | x --> y { 16 | x -> y 17 | } 18 | x --> x 19 | 20 | main { 21 | 1 --> x 22 | 5 --> y 23 | } -------------------------------------------------------------------------------- /example/or.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ or _ 2 | op 30 : _ -> _ 3 | op 30 : _ => _ 4 | 5 | false or b -> b 6 | true or b -> true 7 | 8 | x or y -> x' or y { x -> x' } 9 | x or y -> x or y' { y -> y' } 10 | x => true { x -> true } 11 | x => false { x -> false } 12 | x => y { x -> z; z => y } 13 | x => y { x -> y } 14 | x => x 15 | 16 | main { 17 | (false or false) or (false or false) => x 18 | } -------------------------------------------------------------------------------- /example/error-unclosed-brace.ron: -------------------------------------------------------------------------------- 1 | # エラーケース7: 閉じ括弧が欠けている 2 | 3 | op 100 : _ + _ 4 | op 50 : _ => _ 5 | 6 | syntax { 7 | t ::= n | t + t 8 | n ::= 0 | 1 | 2 9 | } 10 | 11 | 0 + 1 => 1 12 | 1 + 1 => 2 13 | 14 | # エラー: 閉じ括弧 } が欠けている 15 | t1 + t2 => t3 { 16 | t1 => n1 17 | t2 => n2 18 | n1 + n2 => t3 19 | # } が欠けている 20 | 21 | main { 22 | 1 + 1 => x 23 | } 24 | 25 | -------------------------------------------------------------------------------- /example/error-evaluation-simple.ron: -------------------------------------------------------------------------------- 1 | # エラーケース5: 評価時のエラー(mainブロックで条件が満たせない) 2 | 3 | op 100 : _ + _ 4 | op 50 : _ => _ 5 | 6 | syntax { 7 | t ::= n | t + t 8 | n ::= 0 | 1 | 2 | 3 9 | } 10 | 11 | # 足し算のルール(3 + は定義していない) 12 | 0 + 1 => 1 13 | 1 + 1 => 2 14 | 1 + 2 => 3 15 | 2 + 1 => 3 16 | 2 + 2 => 4 17 | 18 | main { 19 | # エラー: 3 + 1 のルールが定義されていない 20 | 3 + 1 => x 21 | } 22 | 23 | -------------------------------------------------------------------------------- /example/error-rule-body.ron: -------------------------------------------------------------------------------- 1 | # エラーケース4: ルールボディの構文エラー 2 | 3 | op 100 : _ + _ 4 | op 50 : _ => _ 5 | op 30 : _ : _ 6 | 7 | syntax { 8 | t ::= n | t + t 9 | n ::= 0 | 1 | 2 10 | } 11 | 12 | 0 + 1 => 1 13 | 1 + 1 => 2 14 | 15 | # ルールボディに構文エラー 16 | t1 + t2 => t3 { 17 | t1 => n1 18 | t2 n2 wrongtoken # エラー: => が欠けている 19 | n1 + n2 => t3 20 | } 21 | 22 | main { 23 | 1 + 1 => x 24 | } 25 | 26 | -------------------------------------------------------------------------------- /example/ski.ron: -------------------------------------------------------------------------------- 1 | # 演算子を宣言 2 | op 50 : _ -> _ 3 | op 50 : _ => _ 4 | op 100 : _ _ 5 | 6 | syntax { 7 | constants ::= I | K | S 8 | } 9 | 10 | # 規則1 11 | I x -> x 12 | K x y -> x 13 | S x y z -> x z (y z) 14 | 15 | # 規則2 16 | x y -> x' y { x -> x' } 17 | x y -> x y' { y -> y' } 18 | 19 | # 規則3 20 | x => y { x -> z; z => y } 21 | x => y { x -> y } 22 | x => x 23 | 24 | # 問い合わせ 25 | main { 26 | S K S K => x 27 | } -------------------------------------------------------------------------------- /example/ski.utf8.ron: -------------------------------------------------------------------------------- 1 | # 演算子を宣言(UTF-8の矢印記号を使用) 2 | op 50 : _ → _ 3 | op 50 : _ ⇒ _ 4 | op 100 : _ _ 5 | 6 | syntax { 7 | constants ::= I | K | S 8 | } 9 | 10 | # 規則1 11 | I x → x 12 | K x y → x 13 | S x y z → x z (y z) 14 | 15 | # 規則2 16 | x y → x' y { x → x' } 17 | x y → x y' { y → y' } 18 | 19 | # 規則3 20 | x ⇒ y { x → z; z ⇒ y } 21 | x ⇒ y { x → y } 22 | x ⇒ x 23 | 24 | # 問い合わせ 25 | main { 26 | S K S K ⇒ x 27 | } 28 | 29 | -------------------------------------------------------------------------------- /example/error-op-missing-colon.ron: -------------------------------------------------------------------------------- 1 | # エラーケース1: 演算子定義で : が欠けている 2 | 3 | op 100 : _ + _ 4 | op 50 if _ then _ else _ # エラー: : が欠けている 5 | op 30 : _ : _ 6 | 7 | syntax { 8 | t ::= n | t + t | if t then t else t 9 | n ::= 0 | 1 | 2 10 | } 11 | 12 | 0 + 1 => 1 13 | 1 + 1 => 2 14 | 1 + 2 => 3 15 | 2 + 1 => 3 16 | 2 + 2 => 4 17 | 18 | if 0 then t1 else t2 => t2 19 | if n then t1 else t2 => t1 { 20 | n \= 0 21 | } 22 | 23 | main { 24 | if 1 then 2 else 0 => x 25 | } 26 | 27 | -------------------------------------------------------------------------------- /example/error-evaluation-type.ron: -------------------------------------------------------------------------------- 1 | # エラーケース5: 評価時の型エラー(構文は正しいが評価で失敗) 2 | 3 | op 100 : _ + _ 4 | op 50 : _ => _ 5 | op 40 r : _ -> _ 6 | op 30 : _ ⊢ _ : _ 7 | 8 | syntax { 9 | t ::= n | t + t 10 | n ::= 0 | 1 | 2 11 | T ::= Nat | T -> T 12 | } 13 | 14 | # 型推論ルール 15 | ⊢ 0 : Nat 16 | ⊢ 1 : Nat 17 | ⊢ 2 : Nat 18 | 19 | ⊢ t1 + t2 : Nat { 20 | ⊢ t1 : Nat 21 | ⊢ t2 : Nat 22 | } 23 | 24 | main { 25 | # エラー: 1 + 2 の型は Nat だが、Nat -> Nat を要求している 26 | ⊢ 1 + 2 : Nat -> Nat 27 | } 28 | -------------------------------------------------------------------------------- /example/syntax.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ -> _ 2 | op 30 : _ --> _ 3 | op 50 : if _ then _ else _ 4 | 5 | syntax { 6 | v ::= true | false 7 | t ::= v | if t then t else t 8 | } 9 | 10 | if true then t1 else t2 -> t1 11 | if false then t1 else t2 -> t2 12 | if t1 then t2 else t3 -> if t4 then t2 else t3 { 13 | t1 -> t4 14 | } 15 | 16 | t1 --> t2 { 17 | t1 -> t3 18 | t3 --> t2 19 | } 20 | t --> t' { 21 | t -> t' 22 | } 23 | t --> t 24 | 25 | main { 26 | if (if true then false else true) then false else true --> v 27 | } -------------------------------------------------------------------------------- /example/error-missing-arrow.ron: -------------------------------------------------------------------------------- 1 | # エラーケース6: 矢印が欠けている(構文的には正しいが、型が合わない) 2 | 3 | op 50 : λ _ : _ . _ 4 | op 40 r : _ -> _ 5 | op 30 : _ : _ 6 | op 20 : _ , _ 7 | op 10 : _ ⊢ _ : _ 8 | 9 | syntax { 10 | t ::= x | λ x : T . t 11 | x ::= a | b | c 12 | T ::= Bool | T -> T 13 | } 14 | 15 | # T-Abs 16 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 17 | Γ, x : T1 ⊢ t : T2 18 | } 19 | 20 | # T-Var 21 | Γ ⊢ x : T { 22 | x : T 23 | } 24 | 25 | main { 26 | # エラー: Bool -> の後ろが欠けている 27 | φ, a : Bool ⊢ λ a : Bool . a : Bool -> 28 | } 29 | 30 | -------------------------------------------------------------------------------- /example/and.ron: -------------------------------------------------------------------------------- 1 | op 50 : _ && _ 2 | op 40 : _ is _ 3 | op 30 : if _ then _ else _ 4 | op 10 : _ => _ 5 | 6 | false => false 7 | true => true 8 | 9 | false && false is false 10 | false && true is false 11 | true && false is false 12 | true && true is true 13 | 14 | e1 && e2 => v { 15 | e1 => v1 16 | e2 => v2 17 | v1 && v2 is v 18 | } 19 | 20 | if e1 then e2 else e3 => v { 21 | e1 => true 22 | e2 => v 23 | } 24 | if e1 then e2 else e3 => v { 25 | e1 => false 26 | e3 => v 27 | } 28 | 29 | main { 30 | if true && false then true else false => v 31 | } 32 | -------------------------------------------------------------------------------- /example/cont.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 40 : _ + _ 3 | op 30 : [ _ ] 4 | op 20 : _ is _ 5 | op 20 : _ >> _ 6 | op 10 : _ => _ // _ 7 | op 10 : _ >> _ // _ 8 | 9 | syntax { 10 | constants ::= H 11 | } 12 | 13 | v => 0 // v { 14 | 15 | } 16 | i >> k // v { 17 | 18 | i => k // v 19 | } 20 | e1 + e2 >> k // v { 21 | e1 >> ( [ H + e2 ] >> k ) // v 22 | } 23 | v1 => [ H + e ] >> k // v2 { 24 | e >> ( [ v1 + H ] >> k ) // v2 25 | } 26 | v1 => [ v2 + H ] >> k // v { 27 | 28 | v3 => k // v 29 | } 30 | 31 | main { 32 | 1 + 10 + 100 >> 0 // v 33 | } -------------------------------------------------------------------------------- /example/add.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 50 : _ + _ 3 | op 40 : _ is _ 4 | op 10 : _ -> _ 5 | op 10 : _ --> _ 6 | 7 | syntax { 8 | e ::= # 式 9 | n # 数 10 | | e + e # 足し算 11 | v ::= n # 値 12 | n ::= # 整数 13 | } 14 | 15 | n1 + n2 -> n3 { 16 | 17 | } 18 | 19 | e1 + e2 -> e1' + e2 { 20 | e1 -> e1' 21 | } 22 | 23 | v + e1 -> v + e1' { 24 | e1 -> e1' 25 | } 26 | 27 | e1 --> e2 { 28 | e1 -> e3 29 | e3 --> e2 30 | } 31 | 32 | e --> e' { 33 | e -> e' 34 | } 35 | 36 | e --> e 37 | 38 | main { 39 | (1 + 2) + (3 + 4) --> x 40 | } -------------------------------------------------------------------------------- /example/evaluation-context.add.right-first.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 50 : _ + _ 3 | op 40 : _ is _ 4 | op 10 : _ -> _ 5 | 6 | syntax { 7 | e ::= # 式 8 | n # 数 9 | | e + e # 足し算 10 | v ::= n # 値 11 | n ::= # 整数 12 | } 13 | 14 | # 評価文脈 15 | context syntax { 16 | E ::= e + _ | _ + v # 右から順に簡約 17 | } 18 | 19 | context rule { 20 | E [e1] -> E [e2] { # 簡約規則 21 | e1 -> e2 22 | } 23 | } 24 | 25 | n1 + n2 -> n3 { 26 | 27 | } 28 | 29 | main { 30 | (1 + 2) + (3 + 4) -> x 31 | # x = 1 + 2 + 7 32 | } -------------------------------------------------------------------------------- /example/evaluation-context.add.left-first.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 50 : _ + _ 3 | op 40 : _ is _ 4 | op 10 : _ -> _ 5 | 6 | syntax { 7 | e ::= # 式 8 | n # 数 9 | | e + e # 足し算 10 | v ::= n # 値 11 | n ::= # 整数 12 | } 13 | 14 | # 評価文脈 15 | context syntax { 16 | E ::= 17 | _ + e 18 | | v + _ # 文法:左から順に簡約 19 | } 20 | context rule { 21 | E [e1] -> E [e2] { # 簡約規則 22 | e1 -> e2 23 | } 24 | } 25 | 26 | n1 + n2 -> n3 { 27 | 28 | } 29 | 30 | main { 31 | (1 + 2) + (3 + 4) -> x 32 | # x = 3 + (3 + 4) 33 | } -------------------------------------------------------------------------------- /example/evaluation-context.add.manual-expansion.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 50 : _ + _ 3 | op 40 : _ is _ 4 | op 10 : _ -> _ 5 | op 10 : _ --> _ 6 | 7 | syntax { 8 | e ::= # 式 9 | n # 数 10 | | e + e # 足し算 11 | v ::= n # 値 12 | n ::= # 整数 13 | } 14 | 15 | e1 + e -> e2 + e { 16 | e1 -> e2 17 | } 18 | v + e1 -> v + e2 { 19 | e1 -> e2 20 | } 21 | 22 | n1 + n2 -> n3 { 23 | 24 | } 25 | 26 | e1 --> e2 { 27 | e1 -> e3 28 | e3 --> e2 29 | } 30 | 31 | e --> e' { 32 | e -> e' 33 | } 34 | e --> e 35 | 36 | main { 37 | (1 + 2) + 3 --> x 38 | } -------------------------------------------------------------------------------- /example/evaluation-context.add.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 50 : _ + _ 3 | op 40 : _ is _ 4 | op 10 : _ -> _ 5 | op 10 : _ --> _ 6 | 7 | syntax { 8 | e ::= # 式 9 | n # 数 10 | | e + e # 足し算 11 | v ::= n # 値 12 | n ::= # 整数 13 | } 14 | 15 | # 評価文脈 16 | context syntax { 17 | E ::= _ + e | v + _ # 文法:左から順に簡約:_ が穴 18 | } 19 | 20 | context rule { 21 | E [e1] -> E [e2] { # 簡約規則 22 | e1 -> e2 23 | } 24 | } 25 | 26 | n1 + n2 -> n3 { 27 | 28 | } 29 | 30 | e1 --> e2 { 31 | e1 -> e3 32 | e3 --> e2 33 | } 34 | e --> e' { 35 | e -> e' 36 | } 37 | e --> e 38 | 39 | main { 40 | (1 + 2) + (3 + 4) --> x 41 | # x = 10 42 | } -------------------------------------------------------------------------------- /example/evaluation-context.add.recursive.ron: -------------------------------------------------------------------------------- 1 | op 90 : integer _ 2 | op 50 : _ + _ 3 | op 40 : _ is _ 4 | op 10 : _ -> _ 5 | op 10 : _ --> _ 6 | 7 | syntax { 8 | e ::= # 式 9 | n # 数 10 | | e + e # 足し算 11 | v ::= n # 値 12 | n ::= # 整数 13 | } 14 | 15 | # 評価文脈 16 | context syntax { 17 | # 再帰的な文法:左から順に簡約 18 | E ::= _ | e + E | E + v 19 | } 20 | 21 | context rule { 22 | # 簡約規則 23 | E [e1] -> E [e2] { 24 | e1 -> e2 25 | } 26 | } 27 | 28 | n1 + n2 -> n3 { 29 | 30 | } 31 | 32 | e1 --> e2 { 33 | e1 -> e3 34 | e3 --> e2 35 | } 36 | 37 | e --> e' { 38 | e -> e' 39 | } 40 | 41 | main { 42 | (1 + 2) + (3 + 4) --> x 43 | # x = 10 44 | } -------------------------------------------------------------------------------- /example/syntax-without-macro.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ -> _ 2 | op 30 : _ --> _ 3 | op 50 : if _ then _ else _ 4 | op 99 : V _ 5 | op 99 : T _ 6 | 7 | V true 8 | V false 9 | T v1 { 10 | V v1 11 | } 12 | T (if t1 then t2 else t3) { 13 | T t1 14 | T t2 15 | T t3 16 | } 17 | 18 | if true then t1 else t2 -> t1 { 19 | T t1 20 | T t2 21 | } 22 | if false then t1 else t2 -> t2 { 23 | T t1 24 | T t2 25 | } 26 | if t1 then t2 else t3 -> if t4 then t2 else t3 { 27 | t1 -> t4 28 | T t1 29 | T t2 30 | T t3 31 | T t4 32 | } 33 | 34 | t1 --> t2 { 35 | t1 -> t3 36 | t3 --> t2 37 | T t1 38 | T t2 39 | T t3 40 | } 41 | t --> t' { 42 | t -> t' 43 | T t 44 | T t' 45 | } 46 | t --> t { 47 | T t 48 | } 49 | 50 | main { 51 | if (if true then false else true) then false else true --> v 52 | V v 53 | } -------------------------------------------------------------------------------- /example/tapl.booleans.utf8.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ → _ 2 | op 30 : _ ⇒ _ 3 | op 50 : if _ then _ else _ 4 | 5 | syntax { 6 | t ::= # terms: 7 | true # constant true 8 | | false # constant false 9 | | if t then t else t # conditional 10 | 11 | v ::= # values: 12 | true # true value 13 | | false # false value 14 | } 15 | 16 | if true then t2 else t3 → t2 # E-IfTrue 17 | if false then t2 else t3 → t3 # E-ifFalse 18 | # E-If 19 | if t1 then t2 else t3 → if t1' then t2 else t3 { 20 | t1 → t1' 21 | } 22 | 23 | t1 ⇒ t2 { 24 | t1 → t3 25 | t3 ⇒ t2 26 | } 27 | t ⇒ t' { 28 | t → t' 29 | } 30 | t ⇒ t 31 | 32 | main { 33 | if (if true then false else true) then false else true ⇒ v 34 | } -------------------------------------------------------------------------------- /example/parse.test.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : simple extension : full 2 | use % for newline 3 | 4 | op 99 : _ _ 5 | op 80 : succ _ # successor 6 | op 80 : pred _ # predecessor 7 | op 80 : iszero _ # zero test 8 | op 50 : if _ then _ else _ 9 | op 40 r : _ -> _ 10 | 11 | syntax { 12 | t ::= # terms 13 | true # constant true 14 | | false # constant false 15 | | if t then t else t # conditional 16 | | 0 # constant zero 17 | | succ t # successor 18 | | pred t # predecessor 19 | | iszero t # zero test 20 | } 21 | 22 | main { 23 | t? if iszero 0 then (pred pred pred pred pred pred pred pred 0) else true 24 | } -------------------------------------------------------------------------------- /example/tapl.booleans.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ -> _ 2 | op 30 : _ --> _ 3 | op 50 : if _ then _ else _ 4 | 5 | syntax { 6 | t ::= # terms: 7 | true # constant true 8 | | false # constant false 9 | | if t then t else t # conditional 10 | 11 | v ::= # values: 12 | true # true value 13 | | false # false value 14 | } 15 | 16 | if true then t2 else t3 -> t2 # E-IfTrue 17 | if false then t2 else t3 -> t3 # E-ifFalse 18 | # E-If 19 | if t1 then t2 else t3 -> if t1' then t2 else t3 { 20 | t1 -> t1' 21 | } 22 | 23 | t1 --> t2 { 24 | t1 -> t3 25 | t3 --> t2 26 | } 27 | t --> t' { 28 | t -> t' 29 | } 30 | t --> t 31 | 32 | main { 33 | if (if true then false else true) then false else true --> v 34 | } -------------------------------------------------------------------------------- /example/tapl.typed-booleans.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ -> _ 2 | op 30 : _ --> _ 3 | op 30 : _ : _ # typing relation 4 | op 50 : if _ then _ else _ 5 | 6 | syntax { 7 | t ::= # terms: 8 | true # constant true 9 | | false # constant false 10 | | if t then t else t # conditional 11 | 12 | v ::= # values: 13 | true # true value 14 | | false # false value 15 | 16 | T ::= 17 | Bool 18 | } 19 | 20 | true : Bool 21 | false : Bool 22 | 23 | if t1 then t2 else t3 : T { 24 | t1 : Bool 25 | t2 : T 26 | t3 : T 27 | } 28 | 29 | if true then t2 else t3 -> t2 # E-IfTrue 30 | if false then t2 else t3 -> t3 # E-ifFalse 31 | # E-If 32 | if t1 then t2 else t3 -> if t1' then t2 else t3 { 33 | t1 -> t1' 34 | } 35 | 36 | t1 --> t2 { 37 | t1 -> t3 38 | t3 --> t2 39 | } 40 | t --> t' { 41 | t -> t' 42 | } 43 | t --> t 44 | 45 | main { 46 | if (if true then false else true) then false else true : T 47 | } -------------------------------------------------------------------------------- /.trunk/trunk.yaml: -------------------------------------------------------------------------------- 1 | # This file controls the behavior of Trunk: https://docs.trunk.io/cli 2 | # To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml 3 | version: 0.1 4 | cli: 5 | version: 1.25.0 6 | # Trunk provides extensibility via plugins. (https://docs.trunk.io/plugins) 7 | plugins: 8 | sources: 9 | - id: trunk 10 | ref: v1.7.3 11 | uri: https://github.com/trunk-io/plugins 12 | # Many linters and tools depend on runtimes - configure them here. (https://docs.trunk.io/runtimes) 13 | runtimes: 14 | enabled: 15 | - go@1.21.0 16 | - node@22.16.0 17 | - python@3.10.8 18 | # This is the section where you manage your linters. (https://docs.trunk.io/check/configuration) 19 | lint: 20 | enabled: 21 | - git-diff-check 22 | - markdownlint@0.45.0 23 | - prettier@3.6.2 24 | - shellcheck@0.11.0 25 | - shfmt@3.6.0 26 | - trufflehog@3.90.11 27 | actions: 28 | disabled: 29 | - trunk-announce 30 | - trunk-check-pre-push 31 | - trunk-fmt-pre-commit 32 | enabled: 33 | - trunk-upgrade-available 34 | -------------------------------------------------------------------------------- /example/letcc.ron: -------------------------------------------------------------------------------- 1 | op 99 : _ _ 2 | op 90 : integer _ 3 | op 90 : cont _ 4 | op 50 : _ + _ 5 | op 40 : [ _ |- _ ] 6 | op 40 : [ _ ] 7 | op 30 : _ \= _ 8 | op 30 : _ = _ 9 | op 20 : _ , _ 10 | op 20 : letcc _ in _ 11 | op 20 : _ is _ 12 | op 20 : _ >> _ 13 | op 10 : _ => _ // _ 14 | op 10 : _ |- _ >> _ // _ 15 | op 10 : _ |- _ => _ 16 | 17 | v => 0 // v { 18 | 19 | } 20 | c |- i >> k // v { 21 | 22 | i => k // v 23 | } 24 | c |- e1 + e2 >> k // v { 25 | c |- e1 >> ( [ c |- H + e2 ] >> k ) // v 26 | } 27 | v1 => [ c |- H + e ] >> k // v2 { 28 | c |- e >> ( [ v1 + H ] >> k ) // v2 29 | } 30 | v1 => [ v2 + H ] >> k // v { 31 | 32 | v3 => k // v 33 | } 34 | c |- letcc x in e >> k // v { 35 | c, x = cont k |- e >> k // v 36 | } 37 | c |- e1 e2 >> k // v { 38 | c |- e1 >> ( [ c |- H e2 ] >> k ) // v 39 | } 40 | v1 => [ c |- H e ] >> k // v2 { 41 | c |- e >> ( [ v1 H ] >> k ) // v2 42 | } 43 | v1 => [ (cont k1) H ] >> k2 // v2 { 44 | v1 => k1 // v2 45 | } 46 | 47 | c |- x >> k // v { 48 | c |- x => v1 49 | v1 => k // v 50 | } 51 | 52 | x = v |- x => v 53 | c, x = v |- x => v 54 | c, y = v' |- x => v { 55 | 56 | c |- x => v 57 | } 58 | 59 | main { 60 | 0 |- 1 + letcc k in 10 + k 100 >> 0 // v 61 | } 62 | -------------------------------------------------------------------------------- /example/ocaml.ron: -------------------------------------------------------------------------------- 1 | # OCaml 風の構文でフィボナッチ関数 2 | op 90 : _ _ 3 | op 80 : integer _ 4 | op 60 : _ + _ 5 | op 60 : _ - _ 6 | op 60 : _ < _ 7 | op 60 : _ >= _ 8 | op 50 : _ -> _ 9 | op 40 : _ is _ 10 | op 40 : _ = _ 11 | op 40 : _ \= _ 12 | op 30 : _ , _ 13 | op 25 : [ _ |- _ ] 14 | op 20 : if _ then _ else _ 15 | op 20 : let rec _ _ = _ in _ 16 | op 10 : _ |- _ => _ 17 | 18 | # c |- e => v は、環境 c で式 e を評価すると値 v になるの意味 19 | 20 | # 整数はそのままで値 21 | c |- n => n { 22 | 23 | } 24 | 25 | # 足し算と引き算 26 | c |- e1 + e2 => v { 27 | c |- e1 => v1 28 | c |- e2 => v2 29 | 30 | } 31 | c |- e1 - e2 => v { 32 | c |- e1 => v1 33 | c |- e2 => v2 34 | 35 | } 36 | 37 | # 大小比較 38 | c |- e1 < e2 => true { 39 | c |- e1 => v1 40 | c |- e2 => v2 41 | 42 | } 43 | c |- e1 < e2 => false { 44 | c |- e1 => v1 45 | c |- e2 => v2 46 | = v2> 47 | } 48 | 49 | # if 式 50 | c |- if e1 then e2 else e3 => v { 51 | c |- e1 => true 52 | c |- e2 => v 53 | } 54 | c |- if e1 then e2 else e3 => v { 55 | c |- e1 => false 56 | c |- e3 => v 57 | } 58 | 59 | # 環境と変数 60 | x = v |- x => v 61 | c, x = v |- x => v 62 | c, y = v' |- x => v { 63 | 64 | c |- x => v 65 | } 66 | 67 | # let rec による関数定義 68 | c |- let rec f x = e1 in e2 => v { 69 | c, f = [c |- f = x -> e1] |- e2 => v 70 | } 71 | 72 | # 関数の適用  73 | c |- e1 e2 => v { 74 | c |- e1 => [c2 |- f = x -> e0] 75 | c |- e2 => v2 76 | c2, f = [c2 |- f = x -> e0] , x = v2 |- e0 => v 77 | } 78 | 79 | main { 80 | 0 |- let rec fib n = if n < 2 then n else fib (n - 1) + fib (n - 2) in fib 9 => v 81 | } -------------------------------------------------------------------------------- /example/tapl.arithmetic.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ -> _ # one step evaluation 2 | op 30 : _ --> _ # multi step evaluation 3 | op 50 : if _ then _ else _ # conditional 4 | op 80 : succ _ # successor 5 | op 80 : pred _ # predecessor 6 | op 80 : iszero _ # zero test 7 | 8 | syntax { 9 | t ::= # terms: 10 | true # constant true 11 | | false # constant false 12 | | if t then t else t # conditional 13 | | 0 # constant zero 14 | | succ t # successor 15 | | pred t # predecessor 16 | | iszero t # zero test 17 | 18 | v ::= # values: 19 | true # true value 20 | | false # false value 21 | | nv # numeric value 22 | 23 | nv ::= # numeric values: 24 | 0 # zero 25 | | succ nv # successor value 26 | } 27 | 28 | if true then t2 else t3 -> t2 # E-IfTrue 29 | if false then t2 else t3 -> t3 # E-IfFalse 30 | if t1 then t2 else t3 -> if t1' then t2 else t3 { 31 | t1 -> t1' # E-If 32 | } 33 | 34 | succ t1 -> succ t2 { # E-Succ 35 | t1 -> t2 36 | } 37 | pred 0 -> 0 # E-PredZero 38 | pred (succ nv) -> nv # E-PredSucc 39 | pred t1 -> pred t1' { # E-Pred 40 | t1 -> t1' 41 | } 42 | iszero 0 -> true # E-IsZeroZero 43 | iszero (succ nv) -> false # E-IsZeroSucc 44 | iszero t1 -> iszero t1' { # E-IsZero 45 | t1 -> t1' 46 | } 47 | 48 | t1 --> t2 { 49 | t1 -> t3 50 | t3 --> t2 51 | } 52 | t --> t' { 53 | t -> t' 54 | } 55 | t --> t 56 | 57 | main { 58 | if iszero (pred (succ 0)) then (succ 0) else 0 --> v 59 | # v = succ 0 60 | } -------------------------------------------------------------------------------- /example/dcont.ron: -------------------------------------------------------------------------------- 1 | op 99 : _ _ 2 | op 90 : integer _ 3 | op 90 : cont _ 4 | op 60 : _ * _ 5 | op 50 : _ + _ 6 | op 40 : [ _ |- _ ] 7 | op 40 : [ _ ] 8 | op 30 : _ \= _ 9 | op 30 : _ = _ 10 | op 20 : _ , _ 11 | op 20 : reset _ 12 | op 20 : shift _ in _ 13 | op 20 : letcc _ in _ 14 | op 20 : _ is _ 15 | op 18 : _ >> _ 16 | op 15 : _ >>> _ 17 | op 10 : _ => _ >>> _ evalto _ 18 | op 10 : _ |- _ >> _ >>> _ evalto _ 19 | op 10 : _ |- _ => _ 20 | op 10 : _ ~> _ 21 | 22 | e ~> v { 23 | 0 |- e >> 0 >>> 0 evalto v 24 | } 25 | v => 0 >>> 0 evalto v { 26 | 27 | } 28 | c |- i >> k >>> k2 evalto v { 29 | 30 | i => k >>> k2 evalto v 31 | } 32 | c |- e1 + e2 >> k >>> k2 evalto v { 33 | c |- e1 >> ( [ c |- H + e2 ] >> k ) >>> k2 evalto v 34 | } 35 | v1 => [ c |- H + e ] >> k >>> k2 evalto v2 { 36 | c |- e >> ( [ v1 + H ] >> k ) >>> k2 evalto v2 37 | } 38 | v1 => [ v2 + H ] >> k >>> k2 evalto v { 39 | 40 | v3 => k >>> k2 evalto v 41 | } 42 | 43 | c |- e1 * e2 >> k >>> k2 evalto v { 44 | c |- e1 >> ( [ c |- H * e2 ] >> k ) >>> k2 evalto v 45 | } 46 | v1 => [ c |- H * e ] >> k >>> k2 evalto v2 { 47 | c |- e >> ( [ v1 * H ] >> k ) >>> k2 evalto v2 48 | } 49 | v1 => [ v2 * H ] >> k >>> k2 evalto v { 50 | 51 | v3 => k >>> k2 evalto v 52 | } 53 | 54 | c |- shift x in e >> k >>> k2 evalto v { 55 | c, x = cont k |- e >> 0 >>> k2 evalto v 56 | } 57 | c |- reset e >> k >>> k2 evalto v { 58 | c |- e >> 0 >>> (k >>> k2) evalto v 59 | } 60 | v1 => 0 >>> (k >>> k2) evalto v { 61 | v1 => k >>> k2 evalto v 62 | } 63 | 64 | c |- e1 e2 >> k >>> k2 evalto v { 65 | c |- e1 >> ( [ c |- H e2 ] >> k ) >>> k2 evalto v 66 | } 67 | v1 => [ c |- H e ] >> k >>> k2 evalto v2 { 68 | c |- e >> ( [ v1 H ] >> k ) >>> k2 evalto v2 69 | } 70 | v1 => [ (cont k1) H ] >> k2 >>> k3 evalto v2 { 71 | v1 => k1 >>> (k2 >>> k3) evalto v2 72 | } 73 | 74 | c |- x >> k >>> k2 evalto v { 75 | c |- x => v1 76 | v1 => k >>> k2 evalto v 77 | } 78 | 79 | x = v |- x => v 80 | c, x = v |- x => v 81 | c, y = v' |- x => v { 82 | 83 | c |- x => v 84 | } 85 | 86 | main { 87 | 2 * reset (3 + shift k in k 4) ~> v 88 | } 89 | -------------------------------------------------------------------------------- /example/lambda-full.ron: -------------------------------------------------------------------------------- 1 | # untyped lambda calculus : full beta reduction 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : & _ . _ 7 | op 50 : [ _ -> _ ] _ 8 | op 30 : _ \= _ 9 | op 10 : _ => _ 10 | op 10 : _ -> _ 11 | op 10 : _ --> _ 12 | op 10 : free _ in _ 13 | 14 | syntax { 15 | t ::= # terms 16 | x # variables 17 | | & x . t # abstraction 18 | | t t # application 19 | v ::= # values 20 | & x . t # abstraction value 21 | 22 | s ::= t # term 23 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 24 | y ::= x # variable 25 | z ::= x # variable 26 | } 27 | 28 | t s -> t' s { 29 | t -> t' 30 | } 31 | 32 | v t -> v t' { 33 | t -> t' 34 | } 35 | 36 | & x . t -> & x . t' { 37 | t -> t' 38 | } 39 | 40 | (& x . t) s -> s' { 41 | [x -> s] t => s' 42 | } 43 | 44 | t1 --> t2 { 45 | t1 -> t3 46 | t3 --> t2 47 | } 48 | t1 --> t2 { 49 | t1 -> t2 50 | } 51 | t1 --> t1 52 | 53 | [x -> s] x => s 54 | [x -> s] y => y { 55 | 56 | } 57 | [x -> s] (t1 t2) => t1' t2' { 58 | [x -> s] t1 => t1' 59 | [x -> s] t2 => t2' 60 | } 61 | [x -> s] (& x . t1) => & x . t1 62 | [x -> s] (& y . t1) => & y . t2 { 63 | 64 | 65 | [x -> s] t1 => t2 66 | } 67 | [x -> s] (& y . t1) => & z . t2 { 68 | 69 | free y in s 70 | X z # 新しい変数 z を、以下を満たすように 71 | # バックトラックを繰り返して探す 72 | 73 | 74 | # z の条件ここまで 75 | [y -> z] t1 => t3 76 | [x -> s] t3 => t2 77 | } 78 | 79 | # free x in t : 項 t に x が自由変数として出現する 80 | free x in x 81 | free x in t1 t2 { 82 | free x in t1 83 | } 84 | free x in t1 t2 { 85 | free x in t2 86 | } 87 | free x in & y . t { 88 | 89 | free x in t 90 | } 91 | 92 | main { 93 | (&a.a) ((&a.a) (&b. (&a.a) b)) --> w 94 | # w = & b . b 95 | 96 | # [a -> b] (& a. c) => w 97 | # w = & a . c 98 | # [a -> b] (& b . a) => w 99 | # w = & c . b 100 | # (& a . a a) b -> w 101 | # w = b b 102 | } -------------------------------------------------------------------------------- /example/lambda-call-by-name.ron: -------------------------------------------------------------------------------- 1 | # untyped lambda calculus : full beta reduction using evaluation context 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : & _ . _ 7 | op 50 : [ _ -> _ ] _ 8 | op 30 : _ \= _ 9 | op 10 : _ => _ 10 | op 10 : _ -> _ 11 | op 10 : _ --> _ 12 | op 10 : free _ in _ 13 | 14 | syntax { 15 | t ::= # terms 16 | x # variables 17 | | & x . t # abstraction 18 | | t t # application 19 | v ::= # values 20 | & x . t # abstraction value 21 | 22 | s ::= t # term 23 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 24 | y ::= x # variable 25 | z ::= x # variable 26 | } 27 | 28 | context syntax { 29 | T ::= _ t 30 | } 31 | 32 | context rule { 33 | T [t1] -> T [t2] { 34 | t1 -> t2 35 | } 36 | } 37 | 38 | (& x . t) s -> s' { 39 | [x -> s] t => s' 40 | } 41 | 42 | t1 --> t2 { 43 | t1 -> t3 44 | t3 --> t2 45 | } 46 | t1 --> t2 { 47 | t1 -> t2 48 | } 49 | t1 --> t1 50 | 51 | [x -> s] x => s 52 | [x -> s] y => y { 53 | 54 | } 55 | [x -> s] (t1 t2) => t1' t2' { 56 | [x -> s] t1 => t1' 57 | [x -> s] t2 => t2' 58 | } 59 | [x -> s] (& x . t1) => & x . t1 60 | [x -> s] (& y . t1) => & y . t2 { 61 | 62 | 63 | [x -> s] t1 => t2 64 | } 65 | [x -> s] (& y . t1) => & z . t2 { 66 | 67 | free y in s 68 | X z # 新しい変数 z を、以下を満たすように 69 | # バックトラックを繰り返して探す 70 | 71 | 72 | # z の条件ここまで 73 | [y -> z] t1 => t3 74 | [x -> s] t3 => t2 75 | } 76 | 77 | # free x in t : 項 t に x が自由変数として出現する 78 | free x in x 79 | free x in t1 t2 { 80 | free x in t1 81 | } 82 | free x in t1 t2 { 83 | free x in t2 84 | } 85 | free x in & y . t { 86 | 87 | free x in t 88 | } 89 | 90 | main { 91 | (&a.a) ((&a.a) (&b. (&a.a) b)) --> v 92 | # v = & b . (& a . a) b 93 | 94 | # [a -> b] (& a. c) => w 95 | # w = & a . c 96 | # [a -> b] (& b . a) => w 97 | # w = & c . b 98 | # (& a . a a) b -> w 99 | # w = b b 100 | } -------------------------------------------------------------------------------- /example/lambda-call-by-value.ron: -------------------------------------------------------------------------------- 1 | # untyped lambda calculus : full beta reduction using evaluation context 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : & _ . _ 7 | op 50 : [ _ -> _ ] _ 8 | op 30 : _ \= _ 9 | op 10 : _ => _ 10 | op 10 : _ -> _ 11 | op 10 : _ --> _ 12 | op 10 : free _ in _ 13 | 14 | syntax { 15 | t ::= # terms 16 | x # variables 17 | | & x . t # abstraction 18 | | t t # application 19 | v ::= # values 20 | & x . t # abstraction value 21 | 22 | s ::= t # term 23 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 24 | y ::= x # variable 25 | z ::= x # variable 26 | } 27 | 28 | context syntax { 29 | T ::= _ t | v _ 30 | } 31 | 32 | context rule { 33 | T [t1] -> T [t2] { 34 | t1 -> t2 35 | } 36 | } 37 | 38 | (& x . t) v -> v' { 39 | [x -> v] t => v' 40 | } 41 | 42 | t1 --> t2 { 43 | t1 -> t3 44 | t3 --> t2 45 | } 46 | t1 --> t2 { 47 | t1 -> t2 48 | } 49 | t1 --> t1 50 | 51 | [x -> s] x => s 52 | [x -> s] y => y { 53 | 54 | } 55 | [x -> s] (t1 t2) => t1' t2' { 56 | [x -> s] t1 => t1' 57 | [x -> s] t2 => t2' 58 | } 59 | [x -> s] (& x . t1) => & x . t1 60 | [x -> s] (& y . t1) => & y . t2 { 61 | 62 | 63 | [x -> s] t1 => t2 64 | } 65 | [x -> s] (& y . t1) => & z . t2 { 66 | 67 | free y in s 68 | X z # 新しい変数 z を、以下を満たすように 69 | # バックトラックを繰り返して探す 70 | 71 | 72 | # z の条件ここまで 73 | [y -> z] t1 => t3 74 | [x -> s] t3 => t2 75 | } 76 | 77 | # free x in t : 項 t に x が自由変数として出現する 78 | free x in x 79 | free x in t1 t2 { 80 | free x in t1 81 | } 82 | free x in t1 t2 { 83 | free x in t2 84 | } 85 | free x in & y . t { 86 | 87 | free x in t 88 | } 89 | 90 | main { 91 | (&a.a) ((&a.a) (&b. (&a.a) b)) --> v 92 | # v = & b . (& a . a) b 93 | 94 | # [a -> b] (& a. c) => w 95 | # w = & a . c 96 | # [a -> b] (& b . a) => w 97 | # w = & c . b 98 | # (& a . a a) b -> w 99 | # w = b b 100 | } -------------------------------------------------------------------------------- /example/lambda-full-context.ron: -------------------------------------------------------------------------------- 1 | # untyped lambda calculus : full beta reduction using evaluation context 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : & _ . _ 7 | op 50 : [ _ -> _ ] _ 8 | op 30 : _ \= _ 9 | op 10 : _ => _ 10 | op 10 : _ -> _ 11 | op 10 : _ --> _ 12 | op 10 : free _ in _ 13 | 14 | syntax { 15 | t ::= # terms 16 | x # variables 17 | | & x . t # abstraction 18 | | t t # application 19 | v ::= # values 20 | & x . t # abstraction value 21 | 22 | s ::= t # term 23 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 24 | y ::= x # variable 25 | z ::= x # variable 26 | } 27 | 28 | context syntax { 29 | T ::= _ t | t _ | & x . _ 30 | } 31 | 32 | context rule { 33 | T [t1] -> T [t2] { 34 | t1 -> t2 35 | } 36 | } 37 | 38 | (& x . t) s -> s' { 39 | [x -> s] t => s' 40 | } 41 | 42 | t1 --> t2 { 43 | t1 -> t3 44 | t3 --> t2 45 | } 46 | t1 --> t2 { 47 | t1 -> t2 48 | } 49 | t1 --> t1 50 | 51 | [x -> s] x => s 52 | [x -> s] y => y { 53 | 54 | } 55 | [x -> s] (t1 t2) => t1' t2' { 56 | [x -> s] t1 => t1' 57 | [x -> s] t2 => t2' 58 | } 59 | [x -> s] (& x . t1) => & x . t1 60 | [x -> s] (& y . t1) => & y . t2 { 61 | 62 | 63 | [x -> s] t1 => t2 64 | } 65 | [x -> s] (& y . t1) => & z . t2 { 66 | 67 | free y in s 68 | X z # 新しい変数 z を、以下を満たすように 69 | # バックトラックを繰り返して探す 70 | 71 | 72 | # z の条件ここまで 73 | [y -> z] t1 => t3 74 | [x -> s] t3 => t2 75 | } 76 | 77 | # free x in t : 項 t に x が自由変数として出現する 78 | free x in x 79 | free x in t1 t2 { 80 | free x in t1 81 | } 82 | free x in t1 t2 { 83 | free x in t2 84 | } 85 | free x in & y . t { 86 | 87 | free x in t 88 | } 89 | 90 | main { 91 | (&a.a) ((&a.a) (&b. (&a.a) b)) --> w 92 | # w = & b . b 93 | 94 | # [a -> b] (& a. c) => w 95 | # w = & a . c 96 | # [a -> b] (& b . a) => w 97 | # w = & c . b 98 | # (& a . a a) b -> w 99 | # w = b b 100 | } -------------------------------------------------------------------------------- /example/tapl.typed-arithmetic.ron: -------------------------------------------------------------------------------- 1 | op 30 : _ -> _ # one step evaluation 2 | op 30 : _ --> _ # multi step evaluation 3 | op 30 : _ : _ # typing relation 4 | op 50 : if _ then _ else _ # conditional 5 | op 80 : succ _ # successor 6 | op 80 : pred _ # predecessor 7 | op 80 : iszero _ # zero test 8 | 9 | syntax { 10 | t ::= # terms: 11 | true # constant true 12 | | false # constant false 13 | | if t then t else t # conditional 14 | | 0 # constant zero 15 | | succ t # successor 16 | | pred t # predecessor 17 | | iszero t # zero test 18 | 19 | v ::= # values: 20 | true # true value 21 | | false # false value 22 | | nv # numeric value 23 | 24 | nv ::= # numeric values: 25 | 0 # zero 26 | | succ nv # successor value 27 | 28 | T ::= # types 29 | Bool # type of booleans 30 | | Nat # type of natural numbers 31 | } 32 | 33 | true : Bool 34 | false : Bool 35 | 36 | if t1 then t2 else t3 : T { 37 | t1 : Bool 38 | t2 : T 39 | t3 : T 40 | } 41 | 42 | 0 : Nat 43 | succ t1 : Nat { 44 | t1 : Nat 45 | } 46 | pred t1 : Nat { 47 | t1 : Nat 48 | } 49 | iszero t1 : Bool { 50 | t1 : Nat 51 | } 52 | 53 | if true then t2 else t3 -> t2 # E-IfTrue 54 | if false then t2 else t3 -> t3 # E-IfFalse 55 | if t1 then t2 else t3 -> if t1' then t2 else t3 { 56 | t1 -> t1' # E-If 57 | } 58 | 59 | succ t1 -> succ t2 { # E-Succ 60 | t1 -> t2 61 | } 62 | pred 0 -> 0 # E-PredZero 63 | pred (succ nv) -> nv # E-PredSucc 64 | pred t1 -> pred t1' { # E-Pred 65 | t1 -> t1' 66 | } 67 | iszero 0 -> true # E-IsZeroZero 68 | iszero (succ nv) -> false # E-IsZeroSucc 69 | iszero t1 -> iszero t1' { # E-IsZero 70 | t1 -> t1' 71 | } 72 | 73 | t1 --> t2 { 74 | t1 -> t3 75 | t3 --> t2 76 | } 77 | t --> t' { 78 | t -> t' 79 | } 80 | t --> t 81 | 82 | main { 83 | if iszero 0 then 0 else pred 0 : T 84 | } -------------------------------------------------------------------------------- /test-errors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # エラー表示のテストスクリプト 4 | 5 | echo "======================================" 6 | echo "エラー表示の改善テスト" 7 | echo "======================================" 8 | echo "" 9 | 10 | # エラーケース1 11 | echo "【1】演算子定義で : が欠けている" 12 | echo "--------------------------------------" 13 | swipl ron.pl example/error-op-missing-colon.ron 2>&1 | head -5 14 | echo "" 15 | 16 | # エラーケース2 17 | echo "【2】syntaxブロック内で未定義の演算子を使用" 18 | echo "--------------------------------------" 19 | swipl ron.pl example/error-syntax-undefined-operator.ron 2>&1 | head -5 20 | echo "" 21 | 22 | # エラーケース3 23 | echo "【3】ルールヘッドの構文エラー" 24 | echo "--------------------------------------" 25 | swipl ron.pl example/error-rule-head.ron 2>&1 | head -5 26 | echo "" 27 | 28 | # エラーケース4 29 | echo "【4】ルールボディの構文エラー" 30 | echo "--------------------------------------" 31 | swipl ron.pl example/error-rule-body.ron 2>&1 | head -5 32 | echo "" 33 | 34 | # エラーケース5 35 | echo "【5】評価時のエラー(ルールが見つからない)" 36 | echo "--------------------------------------" 37 | swipl ron.pl example/error-evaluation-simple.ron 2>&1 | head -15 38 | echo "" 39 | 40 | # エラーケース6 41 | echo "【6】閉じ括弧が欠けている" 42 | echo "--------------------------------------" 43 | swipl ron.pl example/error-unclosed-brace.ron 2>&1 | head -5 44 | echo "" 45 | 46 | # エラーケース7 47 | echo "【7】未定義の非終端記号を参照" 48 | echo "--------------------------------------" 49 | swipl ron.pl example/error-undefined-nonterminal.ron 2>&1 | head -10 50 | echo "" 51 | 52 | echo "======================================" 53 | echo "曖昧性チェックのテスト (--check)" 54 | echo "======================================" 55 | echo "" 56 | 57 | # 曖昧性チェック1 58 | echo "【1】カンマ演算子の競合" 59 | echo "--------------------------------------" 60 | swipl ron.pl --check example/test_ambiguity.ron 2>&1 | grep -A 1 "warning" 61 | echo "" 62 | 63 | # 曖昧性チェック2 64 | echo "【2】if-then と if-then-else の競合" 65 | echo "--------------------------------------" 66 | swipl ron.pl --check example/test_ambiguity2.ron 2>&1 | grep -A 1 "warning" 67 | echo "" 68 | 69 | # 曖昧性チェック3 70 | echo "【3】関数適用と他の演算子の競合" 71 | echo "--------------------------------------" 72 | swipl ron.pl --check example/test_ambiguity3.ron 2>&1 | grep -A 1 "warning" 73 | echo "" 74 | 75 | # 曖昧性チェック4 76 | echo "【4】曖昧性なし(正常ケース)" 77 | echo "--------------------------------------" 78 | echo "期待: 警告なしで実行" 79 | swipl ron.pl --check example/arrow1.ron 2>&1 | head -3 80 | echo "" 81 | 82 | echo "======================================" 83 | echo "すべてのテストケースを表示しました" 84 | echo "======================================" 85 | 86 | -------------------------------------------------------------------------------- /example/lambda.ron: -------------------------------------------------------------------------------- 1 | # untyped lambda calculus : call by value 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : λ _ . _ 7 | op 50 : [ _ -> _ ] _ 8 | op 30 : _ \= _ 9 | op 10 : _ => _ 10 | op 10 : _ -> _ 11 | op 10 : _ --> _ 12 | op 10 : free _ in _ 13 | 14 | syntax { 15 | t ::= # terms 16 | x # variables 17 | | λ x . t # abstraction 18 | | t t # application 19 | v ::= # values 20 | λ x . t # abstraction value 21 | 22 | s ::= t # term 23 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 24 | y ::= x # variable 25 | z ::= x # variable 26 | 27 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 28 | # t, s : 項を表すメタ変数 29 | } 30 | 31 | # 適用 t s の形はまず左側の t を簡約する 32 | t s -> t' s { 33 | t -> t' 34 | } 35 | 36 | # 左側が値になったら右側を簡約する 37 | v t -> v t' { 38 | t -> t' 39 | } 40 | 41 | # 右側が値になったらベータ簡約する 42 | (λx. t) v -> s' { 43 | [x -> v] t => s' 44 | } 45 | 46 | # 簡約の反射推移閉包 47 | t1 --> t2 { 48 | t1 -> t3 49 | t3 --> t2 50 | } 51 | t1 --> t2 { 52 | t1 -> t2 53 | } 54 | t1 --> t1 55 | 56 | # ベータ簡約 57 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 58 | 59 | # x は x の中で自由なので s に置き換える 60 | [x -> s] x => s 61 | # x と異なる変数 y の中に x はないので y のまま 62 | [x -> s] y => y { 63 | 64 | } 65 | # t1 t2 は、それぞれの項の中で置き換える 66 | [x -> s] (t1 t2) => t1' t2' { 67 | [x -> s] t1 => t1' 68 | [x -> s] t2 => t2' 69 | } 70 | # λx. t1 の中に自由な x はないのでそのまま 71 | [x -> s] (λx . t1) => λx . t1 72 | 73 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 74 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 75 | # そんな y がないという条件でそうする 76 | [x -> s] (λy. t1) => λy. t2 { 77 | 78 | 79 | [x -> s] t1 => t2 80 | } 81 | 82 | # λy. t1 で s の中に自由な y があるときは、 83 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 84 | # その際は仮引数の y と t1 の中の自由な y を z に変える 85 | [x -> s] (λy. t1) => λz. t2 { 86 | 87 | free y in s 88 | X z # 新しい変数 z を、以下を満たすように 89 | # バックトラックを繰り返して探す 90 | # つまり z は x, y や s, t1 の中の自由変数の 91 | # どれとも異なる 92 | # z の条件ここまで 93 | [y -> z] t1 => t3 94 | [x -> s] t3 => t2 95 | } 96 | 97 | # free x in t : 項 t に x が自由変数として出現する 98 | free x in x 99 | free x in t1 t2 { 100 | free x in t1 101 | } 102 | free x in t1 t2 { 103 | free x in t2 104 | } 105 | free x in λy. t { 106 | 107 | free x in t 108 | } 109 | 110 | main { 111 | (λa. a) ((λa. a) (λb. (λa. a) b)) --> w 112 | # w = λb. (λa. a) b 113 | } -------------------------------------------------------------------------------- /example/ml-peano.ron: -------------------------------------------------------------------------------- 1 | op 90 : S _ 2 | op 80 : _ * _ 3 | op 60 : _ + _ 4 | op 60 : _ - _ 5 | op 50 : _ < _ 6 | op 40 : _ = _ 7 | op 40 : _ \= _ 8 | op 30 : _ , _ 9 | op 25 : [ _ , _ ] 10 | op 20 : _ less than _ is _ 11 | op 20 : if _ then _ else _ 12 | op 20 : let _ = _ in _ 13 | op 20 : letrec _ = _ in _ 14 | op 20 : fun _ -> _ 15 | op 10 : _ |- _ => _ 16 | 17 | syntax { 18 | constants ::= Z 19 | } 20 | 21 | c |- Z => Z 22 | c |- S n => S v { 23 | c |- n => v 24 | } 25 | 26 | c |- true => true 27 | c |- false => false 28 | 29 | c |- Z + n => v { 30 | c |- n => v 31 | } 32 | c |- (S n1) + n2 => S n { 33 | c |- n1 + n2 => n 34 | } 35 | c |- e1 + e2 => v { 36 | c |- e1 => v1 37 | c |- e2 => v2 38 | c |- v1 + v2 => v 39 | } 40 | 41 | c |- n - Z => v { 42 | c |- n => v 43 | } 44 | c |- n - (S m) => l { 45 | c |- n - m => S l 46 | } 47 | c |- e1 - e2 => v { 48 | c |- e1 => v1 49 | c |- e2 => v2 50 | c |- v1 - v2 => v 51 | } 52 | 53 | Z less than (S n) is true 54 | S n1 less than S n2 is true { 55 | n1 less than n2 is true 56 | } 57 | n less than Z is false 58 | S n1 less than S n2 is false { 59 | n1 less than n2 is false 60 | } 61 | c |- e1 < e2 => v { 62 | c |- e1 => v1 63 | c |- e2 => v2 64 | v1 less than v2 is v 65 | } 66 | 67 | c |- if e1 then e2 else e3 => v { 68 | c |- e1 => true 69 | c |- e2 => v 70 | } 71 | c |- if e1 then e2 else e3 => v { 72 | c |- e1 => false 73 | c |- e3 => v 74 | } 75 | 76 | x = v |- x => v 77 | c, x = v |- x => v 78 | c, y = v' |- x => v { 79 | 80 | c |- x => v 81 | } 82 | 83 | c |- let x = e1 in e2 => v { 84 | c |- e1 => v1 85 | c, x = v1 |- e2 => v 86 | } 87 | c |- letrec x = fun y -> e1 in e2 => v { 88 | c, x = [c, x = fun y -> e1] |- e2 => v 89 | } 90 | 91 | c |- fun x -> e => [c, fun x -> e] 92 | c |- e1 * e2 => v { 93 | c |- e1 => [c2, fun x -> e0] 94 | c |- e2 => v2 95 | c2, x = v2 |- e0 => v 96 | } 97 | c |- e1 * e2 => v { 98 | c |- e1 => [c2, x = fun y -> e0] 99 | c |- e2 => v2 100 | c2, x = [c2, x = fun y -> e0] , y = v2 |- e0 => v 101 | } 102 | 103 | main { 104 | 0 |- letrec fib = fun n -> if n < S S Z then n else fib * (n - S Z) + fib * (n - S S Z) in fib * (S S S S S S S Z) => v 105 | } 106 | -------------------------------------------------------------------------------- /example/tapl.base-type.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus over base types 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 60 r : _ -> _ 7 | op 50 : λ _ : _ . _ 8 | op 50 : [ _ -> _ ] _ 9 | op 30 : _ : _ 10 | op 30 : _ \= _ 11 | op 20 : _ , _ 12 | op 15 : _ : _ ∈ _ 13 | op 10 : _ ⊢ _ : _ 14 | op 10 : _ = _ 15 | op 10 : _ => _ 16 | op 10 : _ --> _ 17 | op 10 : free _ in _ 18 | 19 | syntax { 20 | t ::= # terms 21 | x # variables 22 | | λ x : T . t # abstraction value 23 | | t t # application 24 | 25 | v ::= # values 26 | λ x : T . t # abstraction value 27 | 28 | # variables 29 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 30 | 31 | T ::= # types 32 | A # base type 33 | | T -> T # type of functions 34 | 35 | Γ ::= # contexts 36 | φ # empty context 37 | | Γ, x : T # term variable binding 38 | 39 | s ::= t # term 40 | y ::= x # variable 41 | z ::= x # variable 42 | 43 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 44 | # t, s : 項を表すメタ変数 45 | } 46 | 47 | # T-Abs 48 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 49 | Γ, x : T1 ⊢ t : T2 50 | } 51 | 52 | # T-App 53 | Γ ⊢ t1 t2 : T2 { 54 | Γ ⊢ t1 : T1 -> T2 55 | Γ ⊢ t2 : T1 56 | } 57 | 58 | # T-Var 59 | Γ ⊢ x : T { 60 | x : T ∈ Γ 61 | } 62 | 63 | # type for x in Γ is T <=> x : T ∈ Γ 64 | x : T ∈ (Γ, x : T) 65 | x : T1 ∈ (Γ, y : T2) { 66 | 67 | x : T1 ∈ Γ 68 | } 69 | 70 | # 適用 t s の形はまず左側の t を簡約する 71 | t s -> t' s { 72 | t -> t' 73 | } 74 | # 左側が値になったら右側を簡約する 75 | v t -> v t' { 76 | t -> t' 77 | } 78 | 79 | # 右側が値になったらベータ簡約する 80 | (λ x : T . t) v -> s' { 81 | [x -> v] t => s' 82 | } 83 | 84 | # 簡約の反射推移閉包 85 | t1 --> t2 { 86 | t1 -> t3 87 | t3 --> t2 88 | } 89 | t1 --> t2 { 90 | t1 -> t2 91 | } 92 | t1 --> t1 93 | 94 | # ベータ簡約 95 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 96 | 97 | # x は x の中で自由なので s に置き換える 98 | [x -> s] x => s 99 | # x と異なる変数 y の中に x はないので y のまま 100 | [x -> s] y => y { 101 | 102 | } 103 | # t1 t2 は、それぞれの項の中で置き換える 104 | [x -> s] (t1 t2) => t1' t2' { 105 | [x -> s] t1 => t1' 106 | [x -> s] t2 => t2' 107 | } 108 | # λx. t1 の中に自由な x はないのでそのまま 109 | [x -> s] (λx : T. t1) => λx : T. t1 110 | 111 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 112 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 113 | # そんな y がないという条件でそうする 114 | [x -> s] (λy : T. t1) => λy : T. t2 { 115 | 116 | 117 | [x -> s] t1 => t2 118 | } 119 | 120 | # λy. t1 で s の中に自由な y があるときは、 121 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 122 | # その際は仮引数の y と t1 の中の自由な y を z に変える 123 | [x -> s] (λy : T. t1) => λz : T. t2 { 124 | 125 | free y in s 126 | X z # 新しい変数 z を、以下を満たすように 127 | # バックトラックを繰り返して探す 128 | # つまり z は x, y や s, t1 の中の自由変数の 129 | # どれとも異なる 130 | # z の条件ここまで 131 | [y -> z] t1 => t3 132 | [x -> s] t3 => t2 133 | } 134 | 135 | # free x in t : 項 t に x が自由変数として出現する 136 | free x in x 137 | free x in t1 t2 { 138 | free x in t1 139 | } 140 | free x in t1 t2 { 141 | free x in t2 142 | } 143 | free x in λy : T. t { 144 | 145 | free x in t 146 | } 147 | 148 | main { 149 | φ ⊢ λf:A->A. λa:A. f (f a) : T 150 | # T = A -> A -> (A -> A) 151 | } -------------------------------------------------------------------------------- /example/fspl.imp.ron: -------------------------------------------------------------------------------- 1 | # IMP from the book "The Formal Semantics of Programming Languages" 2 | use % for newline 3 | 4 | op 80 : atom _ 5 | op 80 : integer _ 6 | op 70 : _ * _ 7 | op 60 : _ + _ 8 | op 60 : _ - _ 9 | op 60 : _ < _ 10 | op 40 : _ = _ 11 | op 40 : _ := _ # assignment 12 | op 40 : _ >= _ 13 | op 40 : _ \= _ # not equal 14 | op 40 : _ is _ 15 | op 40 : ~ _ 16 | op 30 : _ ∧ _ # logical AND 17 | op 35 : _ : _ # state separator 18 | op 30 : _ , _ 19 | op 20 : _ ∨ _ # logical OR 20 | op 18 : if _ then _ else _ 21 | op 16 : while _ do _ 22 | op 14 : _ ; _ # sequencing 23 | op 10 : _ [ _ / _ ] => _ # state update relation 24 | op 10 : < _ , _ > -> _ # evaluation relation 25 | 26 | syntax { 27 | a ::= n | X | a + a | a - a | a * a 28 | b ::= true | false | a = a | a < a | ~ b | b ∧ b | b ∨ b 29 | c ::= skip | X := a | c ; c | if b then c else c | while b do c 30 | n ::= 31 | X ::= 32 | constants ::= φ # empty state 33 | } 34 | 35 | # evaluation of numerals 36 | -> n 37 | 38 | # evaluation of addition 39 | -> n { 40 | -> n0 41 | -> n1 42 | 43 | } 44 | 45 | # evaluation of subtraction 46 | -> n { 47 | -> n0 48 | -> n1 49 | 50 | } 51 | 52 | # evaluation of multiplication 53 | -> n { 54 | -> n0 55 | -> n1 56 | 57 | } 58 | 59 | # evaluation of boolean expressions 60 | -> true 61 | -> false 62 | 63 | -> true { 64 | -> n0 65 | -> n1 66 | 67 | } 68 | -> false { 69 | -> n0 70 | -> n1 71 | 72 | } 73 | -> true { 74 | -> n0 75 | -> n1 76 | 77 | } 78 | -> false { 79 | -> n0 80 | -> n1 81 | = n1> 82 | } 83 | < ~ b, s> -> true { 84 | -> false 85 | } 86 | < ~ b, s> -> false { 87 | -> true 88 | } 89 | -> b { 90 | -> b0' 91 | -> b1' 92 | b0' ∧ b1' is b 93 | 94 | } 95 | false ∧ false is false 96 | false ∧ true is false 97 | true ∧ false is false 98 | true ∧ true is true 99 | 100 | -> b { 101 | -> b0' 102 | -> b1' 103 | b0' ∨ b1' is b 104 | } 105 | false ∨ false is false 106 | false ∨ true is true 107 | true ∨ false is true 108 | true ∨ true is true 109 | 110 | # variables and state 111 | -> v 112 | -> v 113 | -> v { 114 | 115 | 116 | -> v 117 | } 118 | 119 | # evaluation rules for commands 120 | -> s 121 | 122 | -> s2 { 123 | -> m 124 | s1 [m / X] => s2 125 | } 126 | 127 | # state update rules 128 | φ [m / X] => φ 129 | s : X = n [m / X] => s : X = m 130 | s1 : X = n [m / y] => s2 : X = n { 131 | 132 | s1 [m / y] => s2 133 | } 134 | 135 | # sequencing 136 | -> s2 { 137 | -> s3 138 | -> s2 139 | } 140 | 141 | # conditionals 142 | -> s' { 143 | -> true 144 | -> s' 145 | } 146 | -> s' { 147 | -> false 148 | -> s' 149 | } 150 | 151 | # while loops 152 | -> s { 153 | -> false 154 | } 155 | 156 | -> s1 { 157 | -> true 158 | -> s2 159 | -> s1 160 | } 161 | 162 | main { 163 | -> v 164 | # v = φ : p = 0 : q = 55 165 | 166 | # の s の部分は変数の状態を表していて 167 | # φ なら空の状態 168 | # φ : p = 0 : q = 55 なら変数 p が 0, q が 55 である状態 169 | } -------------------------------------------------------------------------------- /example/tapl.unit.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : the unit type 2 | use % for newline 3 | 4 | op 99 : _ _ 5 | op 90 : not _ 6 | op 90 : X _ 7 | op 60 r : _ -> _ 8 | op 50 : λ _ : _ . _ 9 | op 50 : [ _ -> _ ] _ 10 | op 30 : _ : _ 11 | op 30 : _ \= _ 12 | op 25 : _ ; _ 13 | op 20 : _ , _ 14 | op 15 : _ : _ ∈ _ 15 | op 10 : _ ⊢ _ : _ 16 | op 10 : _ = _ 17 | op 10 : _ => _ 18 | op 10 : _ >> _ 19 | op 10 : _ --> _ 20 | op 10 : free _ in _ 21 | 22 | syntax { 23 | t ::= # terms 24 | x # variables 25 | | λ x : T . t # abstraction value 26 | | t t # application 27 | | unit 28 | 29 | v ::= # values 30 | λ x : T . t # abstraction value 31 | | unit 32 | 33 | # variables 34 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 35 | 36 | T ::= # types 37 | T -> T # type of functions 38 | | Unit # unit type 39 | 40 | Γ ::= # contexts 41 | φ # empty context 42 | | Γ, x : T # term variable binding 43 | 44 | s ::= t # term 45 | y ::= x # variable 46 | z ::= x # variable 47 | 48 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 49 | # t, s : 項を表すメタ変数 50 | } 51 | 52 | # derived form 53 | # t1 ; t2 は (λ x : Unit. t2) t1 の糖衣構文 54 | # ただし x は t2 の中に自由変数として現れない 55 | (t1 ; t2) --> t3 { 56 | 57 | (λ x : Unit. t2) t1 --> t3 58 | } 59 | 60 | # T-Unit 61 | Γ ⊢ unit : Unit 62 | 63 | # T-Abs 64 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 65 | Γ, x : T1 ⊢ t : T2 66 | } 67 | 68 | # T-App 69 | Γ ⊢ t1 t2 : T2 { 70 | Γ ⊢ t1 : T1 -> T2 71 | Γ ⊢ t2 : T1 72 | } 73 | 74 | # T-Var 75 | Γ ⊢ x : T { 76 | x : T ∈ Γ 77 | } 78 | 79 | # type for x in Γ is T <=> x : T ∈ Γ 80 | x : T ∈ (Γ, x : T) 81 | x : T1 ∈ (Γ, y : T2) { 82 | 83 | x : T1 ∈ Γ 84 | } 85 | 86 | # unit は値なので簡約しない(このルールは不要だが明示的に) 87 | 88 | # 適用 t s の形はまず左側の t を簡約する 89 | t s >> t' s { 90 | t >> t' 91 | } 92 | # 左側が値になったら右側を簡約する 93 | v t >> v t' { 94 | t >> t' 95 | } 96 | 97 | # 右側が値になったらベータ簡約する 98 | (λ x : T . t) v >> s' { 99 | [x -> v] t => s' 100 | } 101 | 102 | # 簡約の反射推移閉包 103 | t1 --> t2 { 104 | t1 >> t3 105 | t3 --> t2 106 | } 107 | t1 --> t2 { 108 | t1 >> t2 109 | } 110 | t1 --> t1 111 | 112 | # ベータ簡約 113 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 114 | 115 | # unit は変数を含まないのでそのまま 116 | [x -> s] unit => unit 117 | 118 | # x は x の中で自由なので s に置き換える 119 | [x -> s] x => s 120 | # x と異なる変数 y の中に x はないので y のまま 121 | [x -> s] y => y { 122 | 123 | } 124 | # t1 t2 は、それぞれの項の中で置き換える 125 | [x -> s] (t1 t2) => t1' t2' { 126 | [x -> s] t1 => t1' 127 | [x -> s] t2 => t2' 128 | } 129 | # λx. t1 の中に自由な x はないのでそのまま 130 | [x -> s] (λx : T. t1) => λx : T. t1 131 | 132 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 133 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 134 | # そんな y がないという条件でそうする 135 | [x -> s] (λy : T. t1) => λy : T. t2 { 136 | 137 | 138 | [x -> s] t1 => t2 139 | } 140 | 141 | # λy. t1 で s の中に自由な y があるときは、 142 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 143 | # その際は仮引数の y と t1 の中の自由な y を z に変える 144 | [x -> s] (λy : T. t1) => λz : T. t2 { 145 | 146 | free y in s 147 | X z # 新しい変数 z を、以下を満たすように 148 | # バックトラックを繰り返して探す 149 | # つまり z は x, y や s, t1 の中の自由変数の 150 | # どれとも異なる 151 | # z の条件ここまで 152 | [y -> z] t1 => t3 153 | [x -> s] t3 => t2 154 | } 155 | 156 | # free x in t : 項 t に x が自由変数として出現する 157 | free x in x 158 | free x in t1 t2 { 159 | free x in t1 160 | } 161 | free x in t1 t2 { 162 | free x in t2 163 | } 164 | free x in λy : T. t { 165 | 166 | free x in t 167 | } 168 | 169 | main { 170 | (λa: Unit. a) unit ; (λc: Unit. c) (λd: Unit. d) --> w 171 | # w = λ d : Unit . d 172 | } -------------------------------------------------------------------------------- /example/tapl.simply-typed-lambda.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus over booleans 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : λ _ : _ . _ 7 | op 50 : if _ then _ else _ 8 | op 50 : [ _ -> _ ] _ 9 | op 40 r : _ -> _ 10 | op 30 : _ : _ 11 | op 30 : _ \= _ 12 | op 20 : _ , _ 13 | op 15 : _ : _ ∈ _ 14 | op 10 : _ ⊢ _ : _ 15 | op 10 : _ => _ 16 | op 10 : _ --> _ 17 | op 10 : free _ in _ 18 | 19 | syntax { 20 | t ::= # terms 21 | true # constant true 22 | | false # constant false 23 | | x # variables 24 | | λ x : T . t # abstraction value 25 | | t t # application 26 | | if t then t else t # conditional 27 | 28 | v ::= # values 29 | λ x : T . t # abstraction value 30 | 31 | # variables 32 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 33 | 34 | T ::= # types 35 | Bool # type of booleans 36 | | T -> T # type of functions 37 | 38 | Γ ::= # contexts 39 | φ # empty context 40 | | Γ, x : T # term variable binding 41 | 42 | s ::= t # term 43 | y ::= x # variable 44 | z ::= x # variable 45 | 46 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 47 | # t, s : 項を表すメタ変数 48 | } 49 | 50 | # T-Abs 51 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 52 | Γ, x : T1 ⊢ t : T2 53 | } 54 | 55 | # T-App 56 | Γ ⊢ t1 t2 : T2 { 57 | Γ ⊢ t1 : T1 -> T2 58 | Γ ⊢ t2 : T1 59 | } 60 | 61 | # T-Var 62 | Γ ⊢ x : T { 63 | x : T ∈ Γ 64 | } 65 | 66 | # type for x in Γ is T <=> x : T ∈ Γ 67 | x : T ∈ (Γ, x : T) 68 | x : T1 ∈ (Γ, y : T2) { 69 | 70 | x : T1 ∈ Γ 71 | } 72 | 73 | # T-True, T-False 74 | Γ ⊢ true : Bool 75 | Γ ⊢ false : Bool 76 | 77 | # T-If 78 | Γ ⊢ if t1 then t2 else t3 : T { 79 | Γ ⊢ t1 : Bool 80 | Γ ⊢ t2 : T 81 | Γ ⊢ t3 : T 82 | } 83 | 84 | # 適用 t s の形はまず左側の t を簡約する 85 | t s -> t' s { 86 | t -> t' 87 | } 88 | # 左側が値になったら右側を簡約する 89 | v t -> v t' { 90 | t -> t' 91 | } 92 | 93 | # 右側が値になったらベータ簡約する 94 | (λ x : T . t) v -> s' { 95 | [x -> v] t => s' 96 | } 97 | 98 | # 簡約の反射推移閉包 99 | t1 --> t2 { 100 | t1 -> t3 101 | t3 --> t2 102 | } 103 | t1 --> t2 { 104 | t1 -> t2 105 | } 106 | t1 --> t1 107 | 108 | # ベータ簡約 109 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 110 | 111 | # x は x の中で自由なので s に置き換える 112 | [x -> s] x => s 113 | # x と異なる変数 y の中に x はないので y のまま 114 | [x -> s] y => y { 115 | 116 | } 117 | # t1 t2 は、それぞれの項の中で置き換える 118 | [x -> s] (t1 t2) => t1' t2' { 119 | [x -> s] t1 => t1' 120 | [x -> s] t2 => t2' 121 | } 122 | # λx. t1 の中に自由な x はないのでそのまま 123 | [x -> s] (λx : T. t1) => λx : T. t1 124 | 125 | 126 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 127 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 128 | # そんな y がないという条件でそうする 129 | [x -> s] (λy : T. t1) => λy : T. t2 { 130 | 131 | 132 | [x -> s] t1 => t2 133 | } 134 | 135 | 136 | # λy. t1 で s の中に自由な y があるときは、 137 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 138 | # その際は仮引数の y と t1 の中の自由な y を z に変える 139 | [x -> s] (λy : T. t1) => λz : T. t2 { 140 | 141 | free y in s 142 | X z # 新しい変数 z を、以下を満たすように 143 | # バックトラックを繰り返して探す 144 | # つまり z は x, y や s, t1 の中の自由変数の 145 | # どれとも異なる 146 | # z の条件ここまで 147 | [y -> z] t1 => t3 148 | [x -> s] t3 => t2 149 | } 150 | 151 | # free x in t : 項 t に x が自由変数として出現する 152 | free x in x 153 | free x in t1 t2 { 154 | free x in t1 155 | } 156 | free x in t1 t2 { 157 | free x in t2 158 | } 159 | free x in λy : T. t { 160 | 161 | free x in t 162 | } 163 | 164 | main { 165 | φ, f : (Bool -> Bool) ⊢ λa : Bool. f (if a then false else a) : T 166 | # T = Bool -> Bool 167 | 168 | # (λa : Bool. a) ((λa : Bool. a) (λb : Bool. (λa : Bool. a) b)) --> w 169 | # w = λ b : Bool . (λ a : Bool . a) b 170 | } -------------------------------------------------------------------------------- /example/tapl.ascription.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : ascription 2 | use % for newline 3 | 4 | op 99 : _ _ 5 | op 90 : not _ 6 | op 90 : X _ 7 | op 60 r : _ -> _ 8 | op 55 : _ as _ 9 | op 50 : λ _ : _ . _ 10 | op 50 : [ _ -> _ ] _ 11 | op 30 : _ : _ 12 | op 30 : _ \= _ 13 | op 25 : _ ; _ 14 | op 20 : _ , _ 15 | op 15 : _ : _ ∈ _ 16 | op 10 : _ ⊢ _ : _ 17 | op 10 : _ = _ 18 | op 10 : _ => _ 19 | op 10 : _ >> _ 20 | op 10 : _ --> _ 21 | op 10 : free _ in _ 22 | 23 | syntax { 24 | t ::= # terms 25 | x # variables 26 | | λ x : T . t # abstraction value 27 | | t t # application 28 | | unit # unit value 29 | | t as T # ascription 30 | 31 | v ::= # values 32 | λ x : T . t # abstraction value 33 | | unit 34 | 35 | # variables 36 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 37 | 38 | T ::= # types 39 | T -> T # type of functions 40 | | Unit # unit type 41 | 42 | Γ ::= # contexts 43 | φ # empty context 44 | | Γ, x : T # term variable binding 45 | 46 | s ::= t # term 47 | y ::= x # variable 48 | z ::= x # variable 49 | 50 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 51 | # t, s : 項を表すメタ変数 52 | } 53 | 54 | # E-Ascribe 55 | v as T >> v 56 | 57 | # E-Ascribe1 58 | t as T >> t' as T { 59 | t >> t' 60 | } 61 | 62 | # T-Ascribe 63 | Γ ⊢ t as T : T { 64 | Γ ⊢ t : T 65 | } 66 | 67 | # derived form 68 | # t1 ; t2 は (λ x : Unit. t2) t1 の糖衣構文 69 | # ただし x は t2 の中に自由変数として現れない 70 | (t1 ; t2) --> t3 { 71 | 72 | (λ x : Unit. t2) t1 --> t3 73 | } 74 | 75 | # T-Unit 76 | Γ ⊢ unit : Unit 77 | 78 | # T-Abs 79 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 80 | Γ, x : T1 ⊢ t : T2 81 | } 82 | 83 | # T-App 84 | Γ ⊢ t1 t2 : T2 { 85 | Γ ⊢ t1 : T1 -> T2 86 | Γ ⊢ t2 : T1 87 | } 88 | 89 | # T-Var 90 | Γ ⊢ x : T { 91 | x : T ∈ Γ 92 | } 93 | 94 | # type for x in Γ is T <=> x : T ∈ Γ 95 | x : T ∈ (Γ, x : T) 96 | x : T1 ∈ (Γ, y : T2) { 97 | 98 | x : T1 ∈ Γ 99 | } 100 | 101 | # unit は値なので簡約しない(このルールは不要だが明示的に) 102 | 103 | # 適用 t s の形はまず左側の t を簡約する 104 | t s >> t' s { 105 | t >> t' 106 | } 107 | # 左側が値になったら右側を簡約する 108 | v t >> v t' { 109 | t >> t' 110 | } 111 | 112 | # 右側が値になったらベータ簡約する 113 | (λ x : T . t) v >> s' { 114 | [x -> v] t => s' 115 | } 116 | 117 | # 簡約の反射推移閉包 118 | t1 --> t2 { 119 | t1 >> t3 120 | t3 --> t2 121 | } 122 | t1 --> t2 { 123 | t1 >> t2 124 | } 125 | t1 --> t1 126 | 127 | # ベータ簡約 128 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 129 | 130 | # unit は変数を含まないのでそのまま 131 | [x -> s] unit => unit 132 | 133 | # x は x の中で自由なので s に置き換える 134 | [x -> s] x => s 135 | # x と異なる変数 y の中に x はないので y のまま 136 | [x -> s] y => y { 137 | 138 | } 139 | # t1 t2 は、それぞれの項の中で置き換える 140 | [x -> s] (t1 t2) => t1' t2' { 141 | [x -> s] t1 => t1' 142 | [x -> s] t2 => t2' 143 | } 144 | # λx. t1 の中に自由な x はないのでそのまま 145 | [x -> s] (λx : T. t1) => λx : T. t1 146 | 147 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 148 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 149 | # そんな y がないという条件でそうする 150 | [x -> s] (λy : T. t1) => λy : T. t2 { 151 | 152 | 153 | [x -> s] t1 => t2 154 | } 155 | 156 | # λy. t1 で s の中に自由な y があるときは、 157 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 158 | # その際は仮引数の y と t1 の中の自由な y を z に変える 159 | [x -> s] (λy : T. t1) => λz : T. t2 { 160 | 161 | free y in s 162 | X z # 新しい変数 z を、以下を満たすように 163 | # バックトラックを繰り返して探す 164 | # つまり z は x, y や s, t1 の中の自由変数の 165 | # どれとも異なる 166 | # z の条件ここまで 167 | [y -> z] t1 => t3 168 | [x -> s] t3 => t2 169 | } 170 | 171 | # free x in t : 項 t に x が自由変数として出現する 172 | free x in x 173 | free x in t1 t2 { 174 | free x in t1 175 | } 176 | free x in t1 t2 { 177 | free x in t2 178 | } 179 | free x in λy : T. t { 180 | 181 | free x in t 182 | } 183 | 184 | main { 185 | (λa: Unit. a) unit as Unit --> w 186 | # w = unit 187 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ron 2 | 3 | 小さい計算体系をなるべくシンプルに定義できるような言語を作ってみたいと思って作りちゅう。 4 | 5 | 例:ペアノ自然数の足し算 6 | 7 | ``` 8 | # 演算子を宣言 9 | op 50 : S _ 10 | op 50 : _ plus _ is _ 11 | 12 | # 規則1 13 | Z plus n is n 14 | 15 | # 規則2 16 | (S n1) plus n2 is (S n) { 17 | n1 plus n2 is n 18 | } 19 | 20 | # 問い合わせ 21 | main { 22 | (S Z) plus (S Z) is x 23 | } 24 | ``` 25 | 26 | 27 | 28 | 例:SKIコンビネータ計算 29 | ``` 30 | # 演算子を宣言 31 | op 50 : _ -> _ 32 | op 50 : _ => _ 33 | op 100 : _ _ 34 | 35 | # 規則1 36 | I x -> x 37 | K x y -> x 38 | S x y z -> x z (y z) 39 | 40 | # 規則2 41 | x y -> x' y { x -> x' } 42 | x y -> x y' { y -> y' } 43 | 44 | # 規則3 45 | x => y { x -> y } 46 | x => y { x -> z; z => y } 47 | 48 | # 問い合わせ 49 | main { 50 | S K S K => x 51 | } 52 | ``` 53 | 54 | 例:UTF-8の数学記号を使ってもいい 55 | ``` 56 | # 論理演算の例 57 | op 10 : _ → _ 58 | op 50 : _ ∧ _ 59 | 60 | # AND 演算 61 | true ∧ true → true 62 | true ∧ false → false 63 | false ∧ true → false 64 | false ∧ false → false 65 | 66 | main { 67 | true ∧ false → x 68 | } 69 | ``` 70 | 71 | 例:文法が定義できる 72 | ``` 73 | # TAPL の Booleans 74 | op 30 : _ -> _ 75 | op 30 : _ --> _ 76 | op 50 : if _ then _ else _ 77 | 78 | syntax { 79 | t ::= # terms : 80 | true # constant true 81 | | false # constant false 82 | | if t then t else t # conditional 83 | 84 | v ::= # values : 85 | true # true value 86 | | false # false value 87 | } 88 | 89 | if true then t2 else t3 -> t2 # E-IfTrue 90 | if false then t2 else t3 -> t3 # E-ifFalse 91 | if t1 then t2 else t3 -> if t1' then t2 else t3 { # E-If 92 | t1 -> t1' 93 | } 94 | 95 | t --> t' { 96 | t -> t' 97 | } 98 | t1 --> t2 { 99 | t1 -> t3 100 | t3 --> t2 101 | } 102 | 103 | main { 104 | if (if true then false else true) then false else true --> v 105 | } 106 | ``` 107 | 108 | 例:OCaml 風の構文でフィボナッチ関数 109 | ``` 110 | op 90 : _ _ 111 | op 80 : integer _ 112 | op 60 : _ + _ 113 | op 60 : _ - _ 114 | op 60 : _ < _ 115 | op 60 : _ >= _ 116 | op 50 : _ -> _ 117 | op 40 : _ is _ 118 | op 40 : _ = _ 119 | op 40 : _ \= _ 120 | op 30 : _ , _ 121 | op 25 : [ _ |- _ ] 122 | op 20 : if _ then _ else _ 123 | op 20 : let rec _ _ = _ in _ 124 | op 10 : _ |- _ => _ 125 | 126 | # c |- e => v は、環境 c で式 e を評価すると値 v になるの意味 127 | 128 | # 整数はそのままで値 129 | c |- n => n { 130 | 131 | } 132 | 133 | # 足し算と引き算 134 | c |- e1 + e2 => v { 135 | c |- e1 => v1 136 | c |- e2 => v2 137 | 138 | } 139 | c |- e1 - e2 => v { 140 | c |- e1 => v1 141 | c |- e2 => v2 142 | 143 | } 144 | 145 | # 大小比較 146 | c |- e1 < e2 => true { 147 | c |- e1 => v1 148 | c |- e2 => v2 149 | 150 | } 151 | c |- e1 < e2 => false { 152 | c |- e1 => v1 153 | c |- e2 => v2 154 | = v2> 155 | } 156 | 157 | # if 式 158 | c |- if e1 then e2 else e3 => v { 159 | c |- e1 => true 160 | c |- e2 => v 161 | } 162 | c |- if e1 then e2 else e3 => v { 163 | c |- e1 => false 164 | c |- e3 => v 165 | } 166 | 167 | # 環境と変数 168 | x = v |- x => v 169 | c, x = v |- x => v 170 | c, y = v' |- x => v { 171 | 172 | c |- x => v 173 | } 174 | 175 | # let rec による関数定義 176 | c |- let rec f x = e1 in e2 => v { 177 | c, f = [c |- f = x -> e1] |- e2 => v 178 | } 179 | 180 | # 関数の適用  181 | c |- e1 e2 => v { 182 | c |- e1 => [c2 |- f = x -> e0] 183 | c |- e2 => v2 184 | c2, f = [c2 |- f = x -> e0] , x = v2 |- e0 => v 185 | } 186 | 187 | main { 188 | 0 |- let rec fib n = if n < 2 then n else fib (n - 1) + fib (n - 2) in fib 9 => v 189 | } 190 | ``` 191 | 192 | ## やりたいこと 193 | 194 | - 「プログラミング言語の基礎概念」とか TaPL にあるような計算体系を、なるべく簡単に実装できるような言語を作りたい 195 | - やりたいことは Prolog でほぼできるので、見た目をもうちょっと自分好みにしたい。 196 | - 具体的には、 197 | - mixfix 演算子を定義して自然な文法で書けるようにしたい 198 | - {} で括って ALGOL 風の見た目にしたい 199 | - 変数名に小文字を使いたい 200 | - 変数名の末尾に ' を使って x' みたいに書きたい 201 | - main を定義したらそこが出発点になるようにしたい 202 | 203 | ## やっていること 204 | 205 | - Prolog でパーズして、そのまま1:1で Prolog の述語に変換して、Prolog の処理系で実行させている 206 | 207 | ## できていること 208 | 209 | - 上記の例は動く。 210 | - UTF-8 の数学記号が使える(例:`→`、`⇒`、`∧`、`∨` など) 211 | 212 | ## 使い方 213 | 214 | ``` 215 | $ swipl ron.pl example/if.ron 216 | ``` 217 | 218 | ## テスト 219 | 220 | ``` 221 | $ bash test.sh 222 | ``` -------------------------------------------------------------------------------- /example/tapl.let.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : let binding 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 50 : λ _ : _ . _ 7 | op 50 : if _ then _ else _ 8 | op 50 : [ _ -> _ ] _ 9 | op 50 : let _ = _ in _ 10 | op 40 r : _ -> _ 11 | op 30 : _ : _ 12 | op 30 : _ \= _ 13 | op 20 : _ , _ 14 | op 15 : _ : _ ∈ _ 15 | op 10 : _ ⊢ _ : _ 16 | op 10 : _ => _ 17 | op 10 : _ --> _ 18 | op 10 : free _ in _ 19 | 20 | syntax { 21 | t ::= # terms 22 | true # constant true 23 | | false # constant false 24 | | x # variables 25 | | λ x : T . t # abstraction value 26 | | t t # application 27 | | if t then t else t # conditional 28 | | let x = t in t # let binding 29 | 30 | v ::= # values 31 | true 32 | | false 33 | | λ x : T . t # abstraction value 34 | 35 | # variables 36 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 37 | 38 | T ::= # types 39 | Bool # type of booleans 40 | | T -> T # type of functions 41 | 42 | Γ ::= # contexts 43 | φ # empty context 44 | | Γ, x : T # term variable binding 45 | 46 | s ::= t # term 47 | y ::= x # variable 48 | z ::= x # variable 49 | 50 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 51 | # t, s : 項を表すメタ変数 52 | } 53 | 54 | # E-LetV 55 | let x = v in t -> s { 56 | [x -> v] t => s 57 | } 58 | 59 | # E-Let 60 | (let x = t1 in t2) -> (let x = t1' in t2) { 61 | t1 -> t1' 62 | } 63 | 64 | # T-Let 65 | Γ ⊢ let x = t1 in t2 : T2 { 66 | Γ ⊢ t1 : T1 67 | Γ, x : T1 ⊢ t2 : T2 68 | } 69 | 70 | # T-Abs 71 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 72 | Γ, x : T1 ⊢ t : T2 73 | } 74 | 75 | # T-App 76 | Γ ⊢ t1 t2 : T2 { 77 | Γ ⊢ t1 : T1 -> T2 78 | Γ ⊢ t2 : T1 79 | } 80 | 81 | # T-Var 82 | Γ ⊢ x : T { 83 | x : T ∈ Γ 84 | } 85 | 86 | # type for x in Γ is T <=> x : T ∈ Γ 87 | x : T ∈ (Γ, x : T) 88 | x : T1 ∈ (Γ, y : T2) { 89 | 90 | x : T1 ∈ Γ 91 | } 92 | 93 | # T-True, T-False 94 | Γ ⊢ true : Bool 95 | Γ ⊢ false : Bool 96 | 97 | # T-If 98 | Γ ⊢ if t1 then t2 else t3 : T { 99 | Γ ⊢ t1 : Bool 100 | Γ ⊢ t2 : T 101 | Γ ⊢ t3 : T 102 | } 103 | 104 | # 適用 t s の形はまず左側の t を簡約する 105 | t s -> t' s { 106 | t -> t' 107 | } 108 | # 左側が値になったら右側を簡約する 109 | v t -> v t' { 110 | t -> t' 111 | } 112 | 113 | # 右側が値になったらベータ簡約する 114 | (λ x : T . t) v -> s' { 115 | [x -> v] t => s' 116 | } 117 | 118 | # 簡約の反射推移閉包 119 | t1 --> t2 { 120 | t1 -> t3 121 | t3 --> t2 122 | } 123 | t1 --> t2 { 124 | t1 -> t2 125 | } 126 | t1 --> t1 127 | 128 | # ベータ簡約 129 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 130 | 131 | # x は x の中で自由なので s に置き換える 132 | [x -> s] x => s 133 | # x と異なる変数 y の中に x はないので y のまま 134 | [x -> s] y => y { 135 | 136 | } 137 | 138 | # t1 t2 は、それぞれの項の中で置き換える 139 | [x -> s] (t1 t2) => t1' t2' { 140 | [x -> s] t1 => t1' 141 | [x -> s] t2 => t2' 142 | } 143 | # λx. t1 の中に自由な x はないのでそのまま 144 | [x -> s] (λx : T. t1) => λx : T. t1 145 | 146 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 147 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 148 | # そんな y がないという条件でそうする 149 | [x -> s] (λy : T. t1) => λy : T. t2 { 150 | 151 | 152 | [x -> s] t1 => t2 153 | } 154 | 155 | # λy. t1 で s の中に自由な y があるときは、 156 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 157 | # その際は仮引数の y と t1 の中の自由な y を z に変える 158 | [x -> s] (λy : T. t1) => λz : T. t2 { 159 | 160 | free y in s 161 | X z # 新しい変数 z を、以下を満たすように 162 | # バックトラックを繰り返して探す 163 | # つまり z は x, y や s, t1 の中の自由変数の 164 | # どれとも異なる 165 | # z の条件ここまで 166 | [y -> z] t1 => t3 167 | [x -> s] t3 => t2 168 | } 169 | 170 | # それ以外はそのまま: true と false など 171 | [x -> s] t => t 172 | 173 | # free x in t : 項 t に x が自由変数として出現する 174 | free x in x 175 | free x in t1 t2 { 176 | free x in t1 177 | } 178 | free x in t1 t2 { 179 | free x in t2 180 | } 181 | free x in λy : T. t { 182 | 183 | free x in t 184 | } 185 | 186 | main { 187 | let f = λa : Bool. a in f true --> w 188 | # w = true 189 | } -------------------------------------------------------------------------------- /example/tapl.typed-lambda.arith.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : arithmetic expression 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 80 : succ _ # successor 7 | op 80 : pred _ # predecessor 8 | op 80 : iszero _ # zero test 9 | op 50 : λ _ : _ . _ 10 | op 50 : if _ then _ else _ 11 | op 50 : [ _ -> _ ] _ 12 | op 40 r : _ -> _ 13 | op 30 : _ : _ 14 | op 30 : _ \= _ 15 | op 20 : _ , _ 16 | op 15 : _ : _ ∈ _ 17 | op 10 : _ ⊢ _ : _ 18 | op 10 : _ => _ 19 | op 10 : _ --> _ 20 | op 10 : free _ in _ 21 | 22 | syntax { 23 | t ::= # terms 24 | true # constant true 25 | | false # constant false 26 | | x # variables 27 | | λ x : T . t # abstraction value 28 | | t t # application 29 | | if t then t else t # conditional 30 | | 0 # constant zero 31 | | succ t # successor 32 | | pred t # predecessor 33 | | iszero t # zero test 34 | 35 | v ::= # values 36 | true 37 | | false 38 | | λ x : T . t # abstraction value 39 | | nv # numeric value 40 | 41 | nv ::= # numeric values: 42 | 0 # zero 43 | | succ nv # successor value 44 | 45 | # variables 46 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 47 | 48 | T ::= # types 49 | Bool # type of booleans 50 | | Nat # type of natural numbers 51 | | T -> T # type of functions 52 | 53 | Γ ::= # contexts 54 | φ # empty context 55 | | Γ, x : T # term variable binding 56 | 57 | s ::= t # term 58 | y ::= x # variable 59 | z ::= x # variable 60 | 61 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 62 | # t, s : 項を表すメタ変数 63 | } 64 | 65 | # T-Abs 66 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 67 | Γ, x : T1 ⊢ t : T2 68 | } 69 | 70 | # T-App 71 | Γ ⊢ t1 t2 : T2 { 72 | Γ ⊢ t1 : T1 -> T2 73 | Γ ⊢ t2 : T1 74 | } 75 | 76 | # T-Var 77 | Γ ⊢ x : T { 78 | x : T ∈ Γ 79 | } 80 | 81 | # type for x in Γ is T <=> x : T ∈ Γ 82 | x : T ∈ (Γ, x : T) 83 | x : T1 ∈ (Γ, y : T2) { 84 | 85 | x : T1 ∈ Γ 86 | } 87 | 88 | # 適用 t s の形はまず左側の t を簡約する 89 | t s -> t' s { 90 | t -> t' 91 | } 92 | # 左側が値になったら右側を簡約する 93 | v t -> v t' { 94 | t -> t' 95 | } 96 | 97 | # 右側が値になったらベータ簡約する 98 | (λ x : T . t) v -> s' { 99 | [x -> v] t => s' 100 | } 101 | 102 | # 簡約の反射推移閉包 103 | t1 --> t2 { 104 | t1 -> t3 105 | t3 --> t2 106 | } 107 | t1 --> t2 { 108 | t1 -> t2 109 | } 110 | t1 --> t1 111 | 112 | # ベータ簡約 113 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 114 | 115 | # x は x の中で自由なので s に置き換える 116 | [x -> s] x => s 117 | # x と異なる変数 y の中に x はないので y のまま 118 | [x -> s] y => y { 119 | 120 | } 121 | 122 | # t1 t2 は、それぞれの項の中で置き換える 123 | [x -> s] (t1 t2) => t1' t2' { 124 | [x -> s] t1 => t1' 125 | [x -> s] t2 => t2' 126 | } 127 | 128 | # true と false はそのまま 129 | [x -> s] true => true 130 | [x -> s] false => false 131 | 132 | # succ t は、t の中で置き換える 133 | [x -> s] (succ t1) => succ t1' { 134 | [x -> s] t1 => t1' 135 | } 136 | 137 | # pred t は、t の中で置き換える 138 | [x -> s] (pred t1) => pred t1' { 139 | [x -> s] t1 => t1' 140 | } 141 | 142 | # iszero t は、t の中で置き換える 143 | [x -> s] (iszero t1) => iszero t1' { 144 | [x -> s] t1 => t1' 145 | } 146 | 147 | # if t1 then t2 else t3 は、各項の中で置き換える 148 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' { 149 | [x -> s] t1 => t1' 150 | [x -> s] t2 => t2' 151 | [x -> s] t3 => t3' 152 | } 153 | # λx. t1 の中に自由な x はないのでそのまま 154 | [x -> s] (λx : T. t1) => λx : T. t1 155 | 156 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 157 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 158 | # そんな y がないという条件でそうする 159 | [x -> s] (λy : T. t1) => λy : T. t2 { 160 | 161 | 162 | [x -> s] t1 => t2 163 | } 164 | 165 | # λy. t1 で s の中に自由な y があるときは、 166 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 167 | # その際は仮引数の y と t1 の中の自由な y を z に変える 168 | [x -> s] (λy : T. t1) => λz : T. t2 { 169 | 170 | free y in s 171 | X z # 新しい変数 z を、以下を満たすように 172 | # バックトラックを繰り返して探す 173 | # つまり z は x, y や s, t1 の中の自由変数の 174 | # どれとも異なる 175 | # z の条件ここまで 176 | [y -> z] t1 => t3 177 | [x -> s] t3 => t2 178 | } 179 | 180 | # free x in t : 項 t に x が自由変数として出現する 181 | free x in x 182 | free x in t1 t2 { 183 | free x in t1 184 | } 185 | free x in t1 t2 { 186 | free x in t2 187 | } 188 | free x in λy : T. t { 189 | 190 | free x in t 191 | } 192 | 193 | # Nat 194 | Γ ⊢ 0 : Nat 195 | Γ ⊢ succ t1 : Nat { 196 | Γ ⊢ t1 : Nat 197 | } 198 | Γ ⊢ pred t1 : Nat { 199 | Γ ⊢ t1 : Nat 200 | } 201 | Γ ⊢ iszero t1 : Bool { 202 | Γ ⊢ t1 : Nat 203 | } 204 | 205 | succ t1 -> succ t2 { # E-Succ 206 | t1 -> t2 207 | } 208 | pred 0 -> 0 # E-PredZero 209 | pred (succ nv) -> nv # E-PredSucc 210 | pred t1 -> pred t1' { # E-Pred 211 | t1 -> t1' 212 | } 213 | iszero 0 -> true # E-IsZeroZero 214 | iszero (succ nv) -> false # E-IsZeroSucc 215 | iszero t1 -> iszero t1' { # E-IsZero 216 | t1 -> t1' 217 | } 218 | 219 | # Bool 220 | 221 | # T-True, T-False 222 | Γ ⊢ true : Bool 223 | Γ ⊢ false : Bool 224 | 225 | # T-If 226 | Γ ⊢ if t1 then t2 else t3 : T { 227 | Γ ⊢ t1 : Bool 228 | Γ ⊢ t2 : T 229 | Γ ⊢ t3 : T 230 | } 231 | 232 | if true then t2 else t3 -> t2 # E-IfTrue 233 | if false then t2 else t3 -> t3 # E-ifFalse 234 | # E-If 235 | if t1 then t2 else t3 -> if t1' then t2 else t3 { 236 | t1 -> t1' 237 | } 238 | 239 | main { 240 | (λa : Nat. succ a) (succ (succ 0)) --> w 241 | # w = succ succ succ 0 242 | } -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 単一ファイルのテスト関数 4 | test_ron_file() { 5 | local file="$1" 6 | local expected_output="$2" 7 | 8 | echo "Testing $file..." 9 | 10 | # swipl で実行し、出力をキャプチャ 11 | local output=$(swipl ron.pl "$file" 2>/dev/null) 12 | 13 | # 期待する出力が含まれているかチェック 14 | if echo "$output" | grep -q "$expected_output"; then 15 | echo "✓ PASS: $file" 16 | return 0 17 | else 18 | echo "✗ FAIL: $file" 19 | echo " Expected: $expected_output" 20 | echo " Got: $output" 21 | return 1 22 | fi 23 | } 24 | 25 | # 複数行の出力をテストする関数 26 | test_ron_file_multiline() { 27 | local file="$1" 28 | shift 29 | local expected_outputs=("$@") 30 | 31 | echo "Testing $file..." 32 | 33 | # swipl で実行し、出力をキャプチャ 34 | local output=$(swipl ron.pl "$file" 2>/dev/null) 35 | 36 | # すべての期待する出力が含まれているかチェック 37 | local all_found=true 38 | for expected in "${expected_outputs[@]}"; do 39 | if ! echo "$output" | grep -q "$expected"; then 40 | echo "✗ FAIL: $file" 41 | echo " Missing expected output: $expected" 42 | echo " Got: $output" 43 | all_found=false 44 | break 45 | fi 46 | done 47 | 48 | if [ "$all_found" = true ]; then 49 | echo "✓ PASS: $file" 50 | return 0 51 | else 52 | return 1 53 | fi 54 | } 55 | 56 | # グローバル変数 57 | PASS=0 58 | FAIL=0 59 | 60 | # テスト用のヘルパー関数 61 | run_test() { 62 | if test_ron_file "$1" "$2"; then 63 | ((PASS++)) 64 | else 65 | ((FAIL++)) 66 | fi 67 | } 68 | 69 | # 複数行テスト用のヘルパー関数 70 | run_test_multiline() { 71 | if test_ron_file_multiline "$@"; then 72 | ((PASS++)) 73 | else 74 | ((FAIL++)) 75 | fi 76 | } 77 | 78 | # 全ファイルのテスト 79 | test_all() { 80 | echo "Running tests on example/*.ron files..." 81 | echo "========================================" 82 | 83 | # 各ファイルをテスト 84 | run_test "example/add.ron" "x = 10" 85 | run_test "example/and.ron" "v = false" 86 | run_test "example/arrow1.ron" "x = 2" 87 | run_test "example/arrow2.ron" "x = 3" 88 | run_test "example/arrow3.ron" "x = 3" 89 | run_test "example/cont.ron" "v = 111" 90 | run_test "example/dcont.ron" "v = 14" 91 | run_test "example/if.ron" "v = 0" 92 | run_test "example/letcc.ron" "v = 101" 93 | run_test "example/logic.utf8.ron" "x = false" 94 | run_test "example/ml-peano.ron" "v = S S S S S S S S S S S S S Z" 95 | run_test "example/ocaml.ron" "v = 34" 96 | run_test "example/or.ron" "x = false" 97 | run_test "example/plus.ron" "x = S S Z" 98 | run_test_multiline "example/plus10.ron" "x = 30" "y = 60" 99 | run_test "example/plus2.ron" "x = S S S 0" 100 | run_test "example/ski.ron" "x = K" 101 | run_test "example/ski.utf8.ron" "x = K" 102 | run_test "example/succ.ron" "x = succ succ 0" 103 | run_test "example/syntax-without-macro.ron" "v = true" 104 | run_test "example/syntax.ron" "v = true" 105 | run_test "example/tapl.arithmetic.ron" "v = succ 0" 106 | run_test "example/tapl.booleans.ron" "v = true" 107 | run_test "example/tapl.booleans.utf8.ron" "v = true" 108 | run_test "example/type.ron" "t = int" 109 | run_test "example/fspl.imp.ron" "v = φ : p = 0 : q = 55" 110 | run_test "example/evaluation-context.add.ron" "x = 10" 111 | run_test "example/evaluation-context.add.left-first.ron" "x = 3 + (3 + 4)" 112 | run_test "example/evaluation-context.add.right-first.ron" "x = 1 + 2 + 7" 113 | run_test "example/evaluation-context.add.recursive.ron" "x = 10" 114 | run_test "example/lambda-full.ron" "w = & b . b" 115 | run_test "example/lambda-full-context.ron" "w = & b . b" 116 | run_test "example/lambda-call-by-value.ron" "v = & b . (& a . a) b" 117 | run_test "example/lambda-call-by-name.ron" "v = & b . (& a . a) b" 118 | run_test "example/lambda.ron" "w = λ b . (λ a . a) b" 119 | run_test "example/tapl.typed-booleans.ron" "T = Bool" 120 | run_test "example/tapl.typed-arithmetic.ron" "T = Nat" 121 | run_test "example/tapl.simply-typed-lambda.ron" "T = Bool -> Bool" 122 | run_test "example/tapl.base-type.ron" "T = (A -> A) -> A -> A" 123 | run_test "example/tapl.unit.ron" "w = λ d : Unit . d" 124 | run_test "example/use-percent-for-newline.ron" "x = 2" 125 | run_test "example/tapl.ascription.ron" "w = unit" 126 | run_test "example/tapl.let.ron" "w = true" 127 | run_test "example/use-do-end-for-block.ron" "x = 2" 128 | run_test "example/multiple_use.ron" "x = 2" 129 | run_test "example/tapl.typed-lambda.arith.ron" "w = succ succ succ 0" 130 | run_test "example/tapl.pair.ron" "v = succ 0" 131 | run_test "example/tapl.tuple.ron" "v = succ 0" 132 | run_test "example/tapl.record.ron" "T = Nat" 133 | run_test "example/tapl.record.pattern.ron" "v = { succ 0 , true }" 134 | run_test "example/parse.test.ron" "" 135 | run_test_multiline "example/tapl.simple.full.ron" \ 136 | "v1 = succ succ succ 0" \ 137 | "v2 = 0" \ 138 | "v3 = succ 0" \ 139 | "v4 = λ d : Unit . d" \ 140 | "v5 = true" \ 141 | "v6 = succ 0" \ 142 | "v7 = succ 0" \ 143 | "T1 = Nat" \ 144 | "v8 = true" 145 | 146 | echo "========================================" 147 | echo "Results: $PASS passed, $FAIL failed" 148 | 149 | if [ $FAIL -eq 0 ]; then 150 | echo "All tests passed!" 151 | return 0 152 | else 153 | echo "Some tests failed!" 154 | return 1 155 | fi 156 | } 157 | 158 | # メイン実行 159 | case "${1:-all}" in 160 | "and") 161 | test_and 162 | ;; 163 | "all") 164 | test_all 165 | ;; 166 | *) 167 | echo "Usage: $0 [and|all]" 168 | echo " and: Test only example/and.ron" 169 | echo " all: Test all example/*.ron files" 170 | exit 1 171 | ;; 172 | esac -------------------------------------------------------------------------------- /example/tapl.sum.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : sums 2 | 3 | op 99 : _ _ 4 | op 90 : not _ 5 | op 90 : X _ 6 | op 80 : succ _ # successor 7 | op 80 : pred _ # predecessor 8 | op 80 : iszero _ # zero test 9 | op 50 : λ _ : _ . _ 10 | op 50 : if _ then _ else _ 11 | op 50 : left _ 12 | op 50 : right _ 13 | op 50 : case _ of left _ => _ / right _ => _ 14 | op 50 : [ _ -> _ ] _ 15 | op 40 r : _ -> _ 16 | op 30 : _ : _ 17 | op 30 : _ \= _ 18 | op 20 : _ , _ 19 | op 15 : _ : _ ∈ _ 20 | op 10 : _ ⊢ _ : _ 21 | op 10 : _ => _ 22 | op 10 : _ --> _ 23 | op 10 : free _ in _ 24 | 25 | syntax { 26 | t ::= # terms 27 | true # constant true 28 | | false # constant false 29 | | x # variables 30 | | λ x : T . t # abstraction value 31 | | t t # application 32 | | if t then t else t # conditional 33 | | 0 # constant zero 34 | | succ t # successor 35 | | pred t # predecessor 36 | | iszero t # zero test 37 | | left t # tagging left 38 | | right t # tagging right 39 | | case t of left x => t / right x => t 40 | 41 | v ::= # values 42 | true 43 | | false 44 | | λ x : T . t # abstraction value 45 | | nv # numeric value 46 | 47 | nv ::= # numeric values: 48 | 0 # zero 49 | | succ nv # successor value 50 | 51 | # variables 52 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 53 | 54 | T ::= # types 55 | Bool # type of booleans 56 | | Nat # type of natural numbers 57 | | T -> T # type of functions 58 | 59 | Γ ::= # contexts 60 | φ # empty context 61 | | Γ, x : T # term variable binding 62 | 63 | s ::= t # term 64 | y ::= x # variable 65 | z ::= x # variable 66 | 67 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 68 | # t, s : 項を表すメタ変数 69 | } 70 | 71 | # T-Abs 72 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 73 | Γ, x : T1 ⊢ t : T2 74 | } 75 | 76 | # T-App 77 | Γ ⊢ t1 t2 : T2 { 78 | Γ ⊢ t1 : T1 -> T2 79 | Γ ⊢ t2 : T1 80 | } 81 | 82 | # T-Var 83 | Γ ⊢ x : T { 84 | x : T ∈ Γ 85 | } 86 | 87 | # type for x in Γ is T <=> x : T ∈ Γ 88 | x : T ∈ (Γ, x : T) 89 | x : T1 ∈ (Γ, y : T2) { 90 | 91 | x : T1 ∈ Γ 92 | } 93 | 94 | # 適用 t s の形はまず左側の t を簡約する 95 | t s -> t' s { 96 | t -> t' 97 | } 98 | # 左側が値になったら右側を簡約する 99 | v t -> v t' { 100 | t -> t' 101 | } 102 | 103 | # 右側が値になったらベータ簡約する 104 | (λ x : T . t) v -> s' { 105 | [x -> v] t => s' 106 | } 107 | 108 | # 簡約の反射推移閉包 109 | t1 --> t2 { 110 | t1 -> t3 111 | t3 --> t2 112 | } 113 | t1 --> t2 { 114 | t1 -> t2 115 | } 116 | t1 --> t1 117 | 118 | # ベータ簡約 119 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 120 | 121 | # x は x の中で自由なので s に置き換える 122 | [x -> s] x => s 123 | # x と異なる変数 y の中に x はないので y のまま 124 | [x -> s] y => y { 125 | 126 | } 127 | 128 | # t1 t2 は、それぞれの項の中で置き換える 129 | [x -> s] (t1 t2) => t1' t2' { 130 | [x -> s] t1 => t1' 131 | [x -> s] t2 => t2' 132 | } 133 | 134 | # true と false はそのまま 135 | [x -> s] true => true 136 | [x -> s] false => false 137 | 138 | # succ t は、t の中で置き換える 139 | [x -> s] (succ t1) => succ t1' { 140 | [x -> s] t1 => t1' 141 | } 142 | 143 | # pred t は、t の中で置き換える 144 | [x -> s] (pred t1) => pred t1' { 145 | [x -> s] t1 => t1' 146 | } 147 | 148 | # iszero t は、t の中で置き換える 149 | [x -> s] (iszero t1) => iszero t1' { 150 | [x -> s] t1 => t1' 151 | } 152 | 153 | # if t1 then t2 else t3 は、各項の中で置き換える 154 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' { 155 | [x -> s] t1 => t1' 156 | [x -> s] t2 => t2' 157 | [x -> s] t3 => t3' 158 | } 159 | # λx. t1 の中に自由な x はないのでそのまま 160 | [x -> s] (λx : T. t1) => λx : T. t1 161 | 162 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 163 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 164 | # そんな y がないという条件でそうする 165 | [x -> s] (λy : T. t1) => λy : T. t2 { 166 | 167 | 168 | [x -> s] t1 => t2 169 | } 170 | 171 | # λy. t1 で s の中に自由な y があるときは、 172 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 173 | # その際は仮引数の y と t1 の中の自由な y を z に変える 174 | [x -> s] (λy : T. t1) => λz : T. t2 { 175 | 176 | free y in s 177 | X z # 新しい変数 z を、以下を満たすように 178 | # バックトラックを繰り返して探す 179 | # つまり z は x, y や s, t1 の中の自由変数の 180 | # どれとも異なる 181 | # z の条件ここまで 182 | [y -> z] t1 => t3 183 | [x -> s] t3 => t2 184 | } 185 | 186 | # free x in t : 項 t に x が自由変数として出現する 187 | free x in x 188 | free x in t1 t2 { 189 | free x in t1 190 | } 191 | free x in t1 t2 { 192 | free x in t2 193 | } 194 | free x in λy : T. t { 195 | 196 | free x in t 197 | } 198 | 199 | # Nat 200 | Γ ⊢ 0 : Nat 201 | Γ ⊢ succ t1 : Nat { 202 | Γ ⊢ t1 : Nat 203 | } 204 | Γ ⊢ pred t1 : Nat { 205 | Γ ⊢ t1 : Nat 206 | } 207 | Γ ⊢ iszero t1 : Bool { 208 | Γ ⊢ t1 : Nat 209 | } 210 | 211 | succ t1 -> succ t2 { # E-Succ 212 | t1 -> t2 213 | } 214 | pred 0 -> 0 # E-PredZero 215 | pred (succ nv) -> nv # E-PredSucc 216 | pred t1 -> pred t1' { # E-Pred 217 | t1 -> t1' 218 | } 219 | iszero 0 -> true # E-IsZeroZero 220 | iszero (succ nv) -> false # E-IsZeroSucc 221 | iszero t1 -> iszero t1' { # E-IsZero 222 | t1 -> t1' 223 | } 224 | 225 | # Bool 226 | 227 | # T-True, T-False 228 | Γ ⊢ true : Bool 229 | Γ ⊢ false : Bool 230 | 231 | # T-If 232 | Γ ⊢ if t1 then t2 else t3 : T { 233 | Γ ⊢ t1 : Bool 234 | Γ ⊢ t2 : T 235 | Γ ⊢ t3 : T 236 | } 237 | 238 | if true then t2 else t3 -> t2 # E-IfTrue 239 | if false then t2 else t3 -> t3 # E-ifFalse 240 | # E-If 241 | if t1 then t2 else t3 -> if t1' then t2 else t3 { 242 | t1 -> t1' 243 | } 244 | 245 | main { 246 | t? left succ 0 247 | } -------------------------------------------------------------------------------- /example/tapl.pair.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : pair 2 | use do end for block 3 | 4 | op 99 : _ _ 5 | op 90 : not _ 6 | op 90 : X _ 7 | op 80 : succ _ # successor 8 | op 80 : pred _ # predecessor 9 | op 80 : iszero _ # zero test 10 | op 75 : _ * _ 11 | op 70 : { _ , _ } # pair 12 | op 60 : _ . _ # projection 13 | op 50 : λ _ : _ . _ 14 | op 50 : if _ then _ else _ 15 | op 50 : [ _ -> _ ] _ 16 | op 40 r : _ -> _ 17 | op 30 : _ : _ 18 | op 30 : _ \= _ 19 | op 20 : _ , _ 20 | op 15 : _ : _ ∈ _ 21 | op 10 : _ ⊢ _ : _ 22 | op 10 : _ => _ 23 | op 10 : _ --> _ 24 | op 10 : free _ in _ 25 | 26 | syntax do 27 | t ::= # terms 28 | true # constant true 29 | | false # constant false 30 | | x # variables 31 | | λ x : T . t # abstraction value 32 | | t t # application 33 | | if t then t else t # conditional 34 | | 0 # constant zero 35 | | succ t # successor 36 | | pred t # predecessor 37 | | iszero t # zero test 38 | | { t , t } # pair 39 | | t . 1 # 1st projection 40 | | t . 2 # 2nd projection 41 | 42 | v ::= # values 43 | true 44 | | false 45 | | λ x : T . t # abstraction value 46 | | nv # numeric value 47 | | { v , v } 48 | 49 | nv ::= # numeric values: 50 | 0 # zero 51 | | succ nv # successor value 52 | 53 | # variables 54 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 55 | 56 | T ::= # types 57 | Bool # type of booleans 58 | | Nat # type of natural numbers 59 | | T -> T # type of functions 60 | | T * T 61 | 62 | Γ ::= # contexts 63 | φ # empty context 64 | | Γ, x : T # term variable binding 65 | 66 | s ::= t # term 67 | y ::= x # variable 68 | z ::= x # variable 69 | 70 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 71 | # t, s : 項を表すメタ変数 72 | end 73 | 74 | # T-Abs 75 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 do 76 | Γ, x : T1 ⊢ t : T2 77 | end 78 | 79 | # T-App 80 | Γ ⊢ t1 t2 : T2 do 81 | Γ ⊢ t1 : T1 -> T2 82 | Γ ⊢ t2 : T1 83 | end 84 | 85 | # T-Var 86 | Γ ⊢ x : T do 87 | x : T ∈ Γ 88 | end 89 | 90 | # type for x in Γ is T <=> x : T ∈ Γ 91 | x : T ∈ (Γ, x : T) 92 | x : T1 ∈ (Γ, y : T2) do 93 | 94 | x : T1 ∈ Γ 95 | end 96 | 97 | # 適用 t s の形はまず左側の t を簡約する 98 | t s -> t' s do 99 | t -> t' 100 | end 101 | # 左側が値になったら右側を簡約する 102 | v t -> v t' do 103 | t -> t' 104 | end 105 | 106 | # 右側が値になったらベータ簡約する 107 | (λ x : T . t) v -> s' do 108 | [x -> v] t => s' 109 | end 110 | 111 | # 簡約の反射推移閉包 112 | t1 --> t2 do 113 | t1 -> t3 114 | t3 --> t2 115 | end 116 | t1 --> t2 do 117 | t1 -> t2 118 | end 119 | t1 --> t1 120 | 121 | # ベータ簡約 122 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 123 | 124 | # true と false はそのまま 125 | [x -> s] true => true 126 | [x -> s] false => false 127 | 128 | # succ t は、t の中で置き換える 129 | [x -> s] (succ t1) => succ t1' do 130 | [x -> s] t1 => t1' 131 | end 132 | 133 | # pred t は、t の中で置き換える 134 | [x -> s] (pred t1) => pred t1' do 135 | [x -> s] t1 => t1' 136 | end 137 | 138 | # iszero t は、t の中で置き換える 139 | [x -> s] (iszero t1) => iszero t1' do 140 | [x -> s] t1 => t1' 141 | end 142 | 143 | # if t1 then t2 else t3 は、各項の中で置き換える 144 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' do 145 | [x -> s] t1 => t1' 146 | [x -> s] t2 => t2' 147 | [x -> s] t3 => t3' 148 | end 149 | 150 | # x は x の中で自由なので s に置き換える 151 | [x -> s] x => s 152 | # x と異なる変数 y の中に x はないので y のまま 153 | [x -> s] y => y do 154 | 155 | end 156 | 157 | # t1 t2 は、それぞれの項の中で置き換える 158 | [x -> s] (t1 t2) => t1' t2' do 159 | [x -> s] t1 => t1' 160 | [x -> s] t2 => t2' 161 | end 162 | 163 | # λx. t1 の中に自由な x はないのでそのまま 164 | [x -> s] (λx : T. t1) => λx : T. t1 165 | 166 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 167 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 168 | # そんな y がないという条件でそうする 169 | [x -> s] (λy : T. t1) => λy : T. t2 do 170 | 171 | 172 | [x -> s] t1 => t2 173 | end 174 | 175 | # λy. t1 で s の中に自由な y があるときは、 176 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 177 | # その際は仮引数の y と t1 の中の自由な y を z に変える 178 | [x -> s] (λy : T. t1) => λz : T. t2 do 179 | 180 | free y in s 181 | X z # 新しい変数 z を、以下を満たすように 182 | # バックトラックを繰り返して探す 183 | # つまり z は x, y や s, t1 の中の自由変数の 184 | # どれとも異なる 185 | # z の条件ここまで 186 | [y -> z] t1 => t3 187 | [x -> s] t3 => t2 188 | end 189 | 190 | # free x in t : 項 t に x が自由変数として出現する 191 | free x in x 192 | free x in t1 t2 do 193 | free x in t1 194 | end 195 | free x in t1 t2 do 196 | free x in t2 197 | end 198 | free x in λy : T. t do 199 | 200 | free x in t 201 | end 202 | 203 | # Nat 204 | Γ ⊢ 0 : Nat 205 | Γ ⊢ succ t1 : Nat do 206 | Γ ⊢ t1 : Nat 207 | end 208 | Γ ⊢ pred t1 : Nat do 209 | Γ ⊢ t1 : Nat 210 | end 211 | Γ ⊢ iszero t1 : Bool do 212 | Γ ⊢ t1 : Nat 213 | end 214 | 215 | succ t1 -> succ t2 do # E-Succ 216 | t1 -> t2 217 | end 218 | pred 0 -> 0 # E-PredZero 219 | pred (succ nv) -> nv # E-PredSucc 220 | pred t1 -> pred t1' do # E-Pred 221 | t1 -> t1' 222 | end 223 | iszero 0 -> true # E-IsZeroZero 224 | iszero (succ nv) -> false # E-IsZeroSucc 225 | iszero t1 -> iszero t1' do # E-IsZero 226 | t1 -> t1' 227 | end 228 | 229 | # Bool 230 | 231 | # T-True, T-False 232 | Γ ⊢ true : Bool 233 | Γ ⊢ false : Bool 234 | 235 | # T-If 236 | Γ ⊢ if t1 then t2 else t3 : T do 237 | Γ ⊢ t1 : Bool 238 | Γ ⊢ t2 : T 239 | Γ ⊢ t3 : T 240 | end 241 | 242 | if true then t2 else t3 -> t2 # E-IfTrue 243 | if false then t2 else t3 -> t3 # E-ifFalse 244 | # E-If 245 | if t1 then t2 else t3 -> if t1' then t2 else t3 do 246 | t1 -> t1' 247 | end 248 | 249 | # {t1, t2} は、それぞれの項の中で置き換える 250 | [x -> s] {t1, t2} => {t1', t2'} do 251 | [x -> s] t1 => t1' 252 | [x -> s] t2 => t2' 253 | end 254 | 255 | # t . 1 は t の中で置き換える 256 | [x -> s] t . 1 => t' . 1 do 257 | [x -> s] t => t' 258 | end 259 | [x -> s] t . 2 => t' . 2 do 260 | [x -> s] t => t' 261 | end 262 | 263 | # E-PairBeta 264 | {v1, v2} . 1 -> v1 265 | {v1, v2} . 2 -> v2 266 | 267 | # E-Proj 268 | t . 1 -> t' . 1 do 269 | t -> t' 270 | end 271 | t . 2 -> t' . 2 do 272 | t -> t' 273 | end 274 | 275 | # E-Pair 276 | {t1, t2} -> {t1', t2} do 277 | t1 -> t1' 278 | end 279 | {v1, t2} -> {v1, t2'} do 280 | t2 -> t2' 281 | end 282 | 283 | # T-Pair 284 | Γ ⊢ {t1, t2} : T1 * T2 do 285 | Γ ⊢ t1 : T1 286 | Γ ⊢ t2 : T2 287 | end 288 | # T-Proj 289 | Γ ⊢ t . 1 : T1 do 290 | Γ ⊢ {t1, t2} : T1 * T2 291 | end 292 | Γ ⊢ t . 2 : T2 do 293 | Γ ⊢ {t1, t2} : T1 * T2 294 | end 295 | 296 | main do 297 | (λa : (Nat * Nat) . (a . 2)) {pred succ 0, pred succ succ 0} --> v 298 | end -------------------------------------------------------------------------------- /example/tapl.tuple.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : tuple 2 | use do end for block 3 | 4 | op 99 : _ _ 5 | op 90 : not _ 6 | op 90 : X _ 7 | op 80 : succ _ # successor 8 | op 80 : pred _ # predecessor 9 | op 80 : iszero _ # zero test 10 | op 74 : _ - _ 11 | op 73 r : _ , _ 12 | op 70 : { _ } # tuple 13 | op 60 : _ . _ # projection 14 | op 50 : λ _ : _ . _ 15 | op 50 : if _ then _ else _ 16 | op 50 : [ _ -> _ ] _ 17 | op 40 r : _ -> _ 18 | op 30 : _ : _ 19 | op 30 : _ \= _ 20 | op 20 : _ is _ 21 | op 15 : _ : _ ∈ _ 22 | op 10 : _ ⊢ _ : _ 23 | op 10 : _ => _ 24 | op 10 : _ --> _ 25 | op 10 : free _ in _ 26 | 27 | syntax do 28 | t ::= # terms 29 | true # constant true 30 | | false # constant false 31 | | x # variables 32 | | λ x : T . t # abstraction value 33 | | t t # application 34 | | if t then t else t # conditional 35 | | 0 # constant zero 36 | | succ t # successor 37 | | pred t # predecessor 38 | | iszero t # zero test 39 | | { ts } # tuple 40 | | t . n # projection 41 | 42 | ts ::= t | t, ts 43 | 44 | v ::= # values 45 | true 46 | | false 47 | | λ x : T . t # abstraction value 48 | | nv # numeric value 49 | | { vs } # tuple value 50 | 51 | vs ::= v | v, vs 52 | 53 | nv ::= # numeric values: 54 | 0 # zero 55 | | succ nv # successor value 56 | 57 | n ::= 58 | 59 | # variables 60 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 61 | 62 | T ::= # types 63 | Bool # type of booleans 64 | | Nat # type of natural numbers 65 | | T -> T # type of functions 66 | | { Ts } # tuple 67 | 68 | Ts ::= T | T, Ts 69 | 70 | Γ ::= # contexts 71 | φ # empty context 72 | | Γ, x : T # term variable binding 73 | 74 | s ::= t # term 75 | y ::= x # variable 76 | z ::= x # variable 77 | 78 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 79 | # t, s : 項を表すメタ変数 80 | end 81 | 82 | # T-Abs 83 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 do 84 | Γ, x : T1 ⊢ t : T2 85 | end 86 | 87 | # T-App 88 | Γ ⊢ t1 t2 : T2 do 89 | Γ ⊢ t1 : T1 -> T2 90 | Γ ⊢ t2 : T1 91 | end 92 | 93 | # T-Var 94 | Γ ⊢ x : T do 95 | x : T ∈ Γ 96 | end 97 | 98 | # type for x in Γ is T <=> x : T ∈ Γ 99 | x : T ∈ (Γ, x : T) 100 | x : T1 ∈ (Γ, y : T2) do 101 | 102 | x : T1 ∈ Γ 103 | end 104 | 105 | # 適用 t s の形はまず左側の t を簡約する 106 | t s -> t' s do 107 | t -> t' 108 | end 109 | # 左側が値になったら右側を簡約する 110 | v t -> v t' do 111 | t -> t' 112 | end 113 | 114 | # 右側が値になったらベータ簡約する 115 | (λ x : T . t) v -> s' do 116 | [x -> v] t => s' 117 | end 118 | 119 | # 簡約の反射推移閉包 120 | t1 --> t2 do 121 | t1 -> t3 122 | t3 --> t2 123 | end 124 | t1 --> t2 do 125 | t1 -> t2 126 | end 127 | t1 --> t1 128 | 129 | # ベータ簡約 130 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 131 | 132 | # true と false はそのまま 133 | [x -> s] true => true 134 | [x -> s] false => false 135 | 136 | # succ t は、t の中で置き換える 137 | [x -> s] (succ t1) => succ t1' do 138 | [x -> s] t1 => t1' 139 | end 140 | 141 | # pred t は、t の中で置き換える 142 | [x -> s] (pred t1) => pred t1' do 143 | [x -> s] t1 => t1' 144 | end 145 | 146 | # iszero t は、t の中で置き換える 147 | [x -> s] (iszero t1) => iszero t1' do 148 | [x -> s] t1 => t1' 149 | end 150 | 151 | # if t1 then t2 else t3 は、各項の中で置き換える 152 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' do 153 | [x -> s] t1 => t1' 154 | [x -> s] t2 => t2' 155 | [x -> s] t3 => t3' 156 | end 157 | 158 | # x は x の中で自由なので s に置き換える 159 | [x -> s] x => s 160 | # x と異なる変数 y の中に x はないので y のまま 161 | [x -> s] y => y do 162 | 163 | end 164 | 165 | # t1 t2 は、それぞれの項の中で置き換える 166 | [x -> s] (t1 t2) => t1' t2' do 167 | [x -> s] t1 => t1' 168 | [x -> s] t2 => t2' 169 | end 170 | 171 | # λx. t1 の中に自由な x はないのでそのまま 172 | [x -> s] (λx : T. t1) => λx : T. t1 173 | 174 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 175 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 176 | # そんな y がないという条件でそうする 177 | [x -> s] (λy : T. t1) => λy : T. t2 do 178 | 179 | 180 | [x -> s] t1 => t2 181 | end 182 | 183 | # λy. t1 で s の中に自由な y があるときは、 184 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 185 | # その際は仮引数の y と t1 の中の自由な y を z に変える 186 | [x -> s] (λy : T. t1) => λz : T. t2 do 187 | 188 | free y in s 189 | X z # 新しい変数 z を、以下を満たすように 190 | # バックトラックを繰り返して探す 191 | # つまり z は x, y や s, t1 の中の自由変数の 192 | # どれとも異なる 193 | # z の条件ここまで 194 | [y -> z] t1 => t3 195 | [x -> s] t3 => t2 196 | end 197 | 198 | # free x in t : 項 t に x が自由変数として出現する 199 | free x in x 200 | free x in t1 t2 do 201 | free x in t1 202 | end 203 | free x in t1 t2 do 204 | free x in t2 205 | end 206 | free x in λy : T. t do 207 | 208 | free x in t 209 | end 210 | 211 | # Nat 212 | Γ ⊢ 0 : Nat 213 | Γ ⊢ succ t1 : Nat do 214 | Γ ⊢ t1 : Nat 215 | end 216 | Γ ⊢ pred t1 : Nat do 217 | Γ ⊢ t1 : Nat 218 | end 219 | Γ ⊢ iszero t1 : Bool do 220 | Γ ⊢ t1 : Nat 221 | end 222 | 223 | succ t1 -> succ t2 do # E-Succ 224 | t1 -> t2 225 | end 226 | pred 0 -> 0 # E-PredZero 227 | pred (succ nv) -> nv # E-PredSucc 228 | pred t1 -> pred t1' do # E-Pred 229 | t1 -> t1' 230 | end 231 | iszero 0 -> true # E-IsZeroZero 232 | iszero (succ nv) -> false # E-IsZeroSucc 233 | iszero t1 -> iszero t1' do # E-IsZero 234 | t1 -> t1' 235 | end 236 | 237 | # Bool 238 | 239 | # T-True, T-False 240 | Γ ⊢ true : Bool 241 | Γ ⊢ false : Bool 242 | 243 | # T-If 244 | Γ ⊢ if t1 then t2 else t3 : T do 245 | Γ ⊢ t1 : Bool 246 | Γ ⊢ t2 : T 247 | Γ ⊢ t3 : T 248 | end 249 | 250 | if true then t2 else t3 -> t2 # E-IfTrue 251 | if false then t2 else t3 -> t3 # E-ifFalse 252 | # E-If 253 | if t1 then t2 else t3 -> if t1' then t2 else t3 do 254 | t1 -> t1' 255 | end 256 | 257 | {v, vs} . 1 -> v 258 | {v1, vs} . n1 -> v2 do 259 | 260 | {vs} . n2 -> v2 261 | end 262 | {v} . 1 -> v 263 | 264 | t . n -> t' . n do 265 | t -> t' 266 | end 267 | 268 | {v, ts} -> {v, ts'} do 269 | {ts} -> {ts'} 270 | end 271 | 272 | {t, ts} -> {t', ts} do 273 | t -> t' 274 | end 275 | 276 | {t} -> {t'} do 277 | t -> t' 278 | end 279 | 280 | # T-Tuple 281 | Γ ⊢ {t1, ts} : {T1, Ts} do 282 | Γ ⊢ t1 : T1 283 | Γ ⊢ {ts} : {Ts} 284 | end 285 | Γ ⊢ {t} : {T} do 286 | Γ ⊢ t : T 287 | end 288 | 289 | # T-Proj 290 | Γ ⊢ {t} . 1 : T do 291 | Γ ⊢ t : T 292 | end 293 | Γ ⊢ {t, ts} . 1 : T do 294 | Γ ⊢ t : T 295 | end 296 | Γ ⊢ {t1, ts} . n1 : T2 do 297 | 298 | Γ ⊢ {ts} . n2 : T2 299 | end 300 | 301 | main do 302 | {0, pred succ 0, pred succ succ 0} . 3 --> v 303 | # v = succ 0 304 | 305 | # φ ⊢ {0, true, false} : T 306 | # T = { Nat , Bool , Bool } 307 | end 308 | -------------------------------------------------------------------------------- /example/tapl.record.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : record 2 | use do end for block 3 | 4 | op 99 : _ _ 5 | op 90 : not _ 6 | op 90 : X _ 7 | op 80 : succ _ # successor 8 | op 80 : pred _ # predecessor 9 | op 80 : iszero _ # zero test 10 | op 74 : _ - _ 11 | op 72 : _ = _ 12 | op 71 r : _ , _ 13 | op 70 : { _ } # tuple 14 | op 60 : _ . _ # projection 15 | op 50 : λ _ : _ . _ 16 | op 50 : if _ then _ else _ 17 | op 50 : [ _ -> _ ] _ 18 | op 40 r : _ -> _ 19 | op 30 : _ : _ 20 | op 30 : _ \= _ 21 | op 20 : _ is _ 22 | op 15 : _ : _ ∈ _ 23 | op 10 : _ ⊢ _ : _ 24 | op 10 : _ => _ 25 | op 10 : _ --> _ 26 | op 10 : free _ in _ 27 | 28 | syntax do 29 | t ::= # terms 30 | true # constant true 31 | | false # constant false 32 | | x # variables 33 | | λ x : T . t # abstraction value 34 | | t t # application 35 | | if t then t else t # conditional 36 | | 0 # constant zero 37 | | succ t # successor 38 | | pred t # predecessor 39 | | iszero t # zero test 40 | | { ts } # tuple 41 | | t . n # projection 42 | | { lt } # label-term pairs 43 | | t . l # label projection 44 | 45 | ts ::= t | t, ts 46 | 47 | lt ::= l = t | l = t , lt 48 | l ::= 49 | 50 | v ::= # values 51 | true 52 | | false 53 | | λ x : T . t # abstraction value 54 | | nv # numeric value 55 | | { vs } # tuple value 56 | | { lv } # label-value pairs 57 | 58 | vs ::= v | v, vs 59 | 60 | lv ::= l = v | l = v , lv 61 | 62 | nv ::= # numeric values: 63 | 0 # zero 64 | | succ nv # successor value 65 | 66 | n ::= 67 | 68 | # variables 69 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 70 | 71 | T ::= # types 72 | Bool # type of booleans 73 | | Nat # type of natural numbers 74 | | T -> T # type of functions 75 | | { Ts } # tuple 76 | | { LT } # record type : label-type pairs 77 | 78 | Ts ::= T | T, Ts 79 | 80 | LT ::= l : T | (l : T) , LT # record 81 | 82 | Γ ::= # contexts 83 | φ # empty context 84 | | Γ, x : T # term variable binding 85 | 86 | s ::= t # term 87 | y ::= x # variable 88 | z ::= x # variable 89 | 90 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 91 | # t, s : 項を表すメタ変数 92 | end 93 | 94 | # T-Abs 95 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 do 96 | Γ, x : T1 ⊢ t : T2 97 | end 98 | 99 | # T-App 100 | Γ ⊢ t1 t2 : T2 do 101 | Γ ⊢ t1 : T1 -> T2 102 | Γ ⊢ t2 : T1 103 | end 104 | 105 | # T-Var 106 | Γ ⊢ x : T do 107 | x : T ∈ Γ 108 | end 109 | 110 | # type for x in Γ is T <=> x : T ∈ Γ 111 | x : T ∈ (Γ, x : T) 112 | x : T1 ∈ (Γ, y : T2) do 113 | 114 | x : T1 ∈ Γ 115 | end 116 | 117 | # 適用 t s の形はまず左側の t を簡約する 118 | t s -> t' s do 119 | t -> t' 120 | end 121 | # 左側が値になったら右側を簡約する 122 | v t -> v t' do 123 | t -> t' 124 | end 125 | 126 | # 右側が値になったらベータ簡約する 127 | (λ x : T . t) v -> s' do 128 | [x -> v] t => s' 129 | end 130 | 131 | # 簡約の反射推移閉包 132 | t1 --> t2 do 133 | t1 -> t3 134 | t3 --> t2 135 | end 136 | t1 --> t2 do 137 | t1 -> t2 138 | end 139 | t1 --> t1 140 | 141 | # ベータ簡約 142 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 143 | 144 | # true と false はそのまま 145 | [x -> s] true => true 146 | [x -> s] false => false 147 | 148 | # succ t は、t の中で置き換える 149 | [x -> s] (succ t1) => succ t1' do 150 | [x -> s] t1 => t1' 151 | end 152 | 153 | # pred t は、t の中で置き換える 154 | [x -> s] (pred t1) => pred t1' do 155 | [x -> s] t1 => t1' 156 | end 157 | 158 | # iszero t は、t の中で置き換える 159 | [x -> s] (iszero t1) => iszero t1' do 160 | [x -> s] t1 => t1' 161 | end 162 | 163 | # if t1 then t2 else t3 は、各項の中で置き換える 164 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' do 165 | [x -> s] t1 => t1' 166 | [x -> s] t2 => t2' 167 | [x -> s] t3 => t3' 168 | end 169 | 170 | # x は x の中で自由なので s に置き換える 171 | [x -> s] x => s 172 | # x と異なる変数 y の中に x はないので y のまま 173 | [x -> s] y => y do 174 | 175 | end 176 | 177 | # t1 t2 は、それぞれの項の中で置き換える 178 | [x -> s] (t1 t2) => t1' t2' do 179 | [x -> s] t1 => t1' 180 | [x -> s] t2 => t2' 181 | end 182 | 183 | # λx. t1 の中に自由な x はないのでそのまま 184 | [x -> s] (λx : T. t1) => λx : T. t1 185 | 186 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 187 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 188 | # そんな y がないという条件でそうする 189 | [x -> s] (λy : T. t1) => λy : T. t2 do 190 | 191 | 192 | [x -> s] t1 => t2 193 | end 194 | 195 | # λy. t1 で s の中に自由な y があるときは、 196 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 197 | # その際は仮引数の y と t1 の中の自由な y を z に変える 198 | [x -> s] (λy : T. t1) => λz : T. t2 do 199 | 200 | free y in s 201 | X z # 新しい変数 z を、以下を満たすように 202 | # バックトラックを繰り返して探す 203 | # つまり z は x, y や s, t1 の中の自由変数の 204 | # どれとも異なる 205 | # z の条件ここまで 206 | [y -> z] t1 => t3 207 | [x -> s] t3 => t2 208 | end 209 | 210 | # free x in t : 項 t に x が自由変数として出現する 211 | free x in x 212 | free x in t1 t2 do 213 | free x in t1 214 | end 215 | free x in t1 t2 do 216 | free x in t2 217 | end 218 | free x in λy : T. t do 219 | 220 | free x in t 221 | end 222 | 223 | # Nat 224 | Γ ⊢ 0 : Nat 225 | Γ ⊢ succ t1 : Nat do 226 | Γ ⊢ t1 : Nat 227 | end 228 | Γ ⊢ pred t1 : Nat do 229 | Γ ⊢ t1 : Nat 230 | end 231 | Γ ⊢ iszero t1 : Bool do 232 | Γ ⊢ t1 : Nat 233 | end 234 | 235 | succ t1 -> succ t2 do # E-Succ 236 | t1 -> t2 237 | end 238 | pred 0 -> 0 # E-PredZero 239 | pred (succ nv) -> nv # E-PredSucc 240 | pred t1 -> pred t1' do # E-Pred 241 | t1 -> t1' 242 | end 243 | iszero 0 -> true # E-IsZeroZero 244 | iszero (succ nv) -> false # E-IsZeroSucc 245 | iszero t1 -> iszero t1' do # E-IsZero 246 | t1 -> t1' 247 | end 248 | 249 | # Bool 250 | 251 | # T-True, T-False 252 | Γ ⊢ true : Bool 253 | Γ ⊢ false : Bool 254 | 255 | # T-If 256 | Γ ⊢ if t1 then t2 else t3 : T do 257 | Γ ⊢ t1 : Bool 258 | Γ ⊢ t2 : T 259 | Γ ⊢ t3 : T 260 | end 261 | 262 | if true then t2 else t3 -> t2 # E-IfTrue 263 | if false then t2 else t3 -> t3 # E-ifFalse 264 | # E-If 265 | if t1 then t2 else t3 -> if t1' then t2 else t3 do 266 | t1 -> t1' 267 | end 268 | 269 | {v, vs} . 1 -> v 270 | {v1, vs} . n1 -> v2 do 271 | 272 | {vs} . n2 -> v2 273 | end 274 | {v} . 1 -> v 275 | 276 | t . n -> t' . n do 277 | t -> t' 278 | end 279 | 280 | {v, ts} -> {v, ts'} do 281 | {ts} -> {ts'} 282 | end 283 | {t, ts} -> {t', ts} do 284 | t -> t' 285 | end 286 | {t} -> {t'} do 287 | t -> t' 288 | end 289 | 290 | # T-Tuple 291 | Γ ⊢ {t1, ts} : {T1, Ts} do 292 | Γ ⊢ t1 : T1 293 | Γ ⊢ {ts} : {Ts} 294 | end 295 | Γ ⊢ {t} : {T} do 296 | Γ ⊢ t : T 297 | end 298 | 299 | # T-Proj 300 | Γ ⊢ {t} . 1 : T do 301 | Γ ⊢ t : T 302 | end 303 | Γ ⊢ {t, ts} . 1 : T do 304 | Γ ⊢ t : T 305 | end 306 | Γ ⊢ {t1, ts} . n1 : T2 do 307 | 308 | Γ ⊢ {ts} . n2 : T2 309 | end 310 | 311 | # E-ProjRcd 312 | {l = v, lv} . l -> v 313 | {l1 = v1, lv} . l2 -> v2 do 314 | 315 | {lv} . l2 -> v2 316 | end 317 | {l = v} . l -> v 318 | 319 | # E-Proj 320 | t . l -> t' . l do 321 | t -> t' 322 | end 323 | 324 | # E-Rcd 325 | {l = v, lt} -> {l = v, lt'} do 326 | {lt} -> {lt'} 327 | end 328 | {l = t, lt} -> {l = t', lt} do 329 | t -> t' 330 | end 331 | {l = t} -> {l = t'} do 332 | t -> t' 333 | end 334 | 335 | # T-Rcd 336 | Γ ⊢ {l1 = t1, lt} : {(l1 : T1), LT} do 337 | Γ ⊢ t1 : T1 338 | Γ ⊢ {lt} : {LT} 339 | end 340 | 341 | Γ ⊢ {l = t} : {(l : T)} do 342 | Γ ⊢ t : T 343 | end 344 | 345 | # T-ProjRcd 346 | Γ ⊢ {l = t} . l : T do 347 | Γ ⊢ t : T 348 | end 349 | Γ ⊢ {l = t, lt} . l : T do 350 | Γ ⊢ t : T 351 | end 352 | Γ ⊢ {l1 = t1, lt} . l2 : T2 do 353 | 354 | Γ ⊢ {lt} . l2 : T2 355 | end 356 | 357 | main do 358 | φ ⊢ {man = true, age = pred succ succ 0} . age : T 359 | # T = Nat 360 | 361 | # φ ⊢ {man = true, age = pred succ succ 0} : T 362 | # T = { man : Bool , age : Nat } 363 | 364 | # {man = true, age = pred succ succ 0, woman = false} . age --> v 365 | # v = succ 0 366 | 367 | # {age = 0, man = true, woman = false} . woman -> v 368 | # v = false 369 | 370 | # LT? age : Nat 371 | # T? {(age : Nat), (man : Bool)} 372 | # v? {age = succ 0, man = true} 373 | # t? {age = 0, man = true} . man 374 | end 375 | -------------------------------------------------------------------------------- /example/tapl.fix.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : simple extension : full 2 | use % for newline 3 | 4 | op 99 : _ _ 5 | op 99 : succ _ # successor 6 | op 99 : pred _ # predecessor 7 | op 99 : iszero _ # zero test 8 | op 99 : fix _ # fix 9 | op 90 : not _ 10 | op 90 : X _ 11 | op 75 : _ * _ # product type 12 | op 70 : _ + _ # sum type 13 | op 70 : ( _ , _ ) # pair 14 | op 60 : _ . _ # projection 15 | op 55 : _ as _ # ascription 16 | op 50 : let _ = _ in _ 17 | op 50 : λ _ : _ . _ 18 | op 50 : if _ then _ else _ 19 | op 50 : left _ 20 | op 50 : right _ 21 | op 50 : case _ of left _ => _ / right _ => _ 22 | op 50 : [ _ -> _ ] _ 23 | op 40 r : _ -> _ 24 | op 30 : _ : _ 25 | op 30 : _ \= _ 26 | op 25 : _ ; _ 27 | op 20 : _ , _ 28 | op 15 : _ : _ ∈ _ 29 | op 10 : _ ⊢ _ : _ 30 | op 10 : _ => _ 31 | op 10 : _ --> _ 32 | op 10 : free _ in _ 33 | 34 | syntax { 35 | t ::= # terms 36 | true # constant true 37 | | false # constant false 38 | | x # variables 39 | | λ x : T . t # abstraction value 40 | | t t # application 41 | | if t then t else t # conditional 42 | | 0 # constant zero 43 | | succ t # successor 44 | | pred t # predecessor 45 | | iszero t # zero test 46 | | t as T # ascription 47 | | unit 48 | | let x = t in t # let binding 49 | | ( t , t ) # pair 50 | | t . 1 # 1st projection 51 | | t . 2 # 2nd projection 52 | | left t # sum : tagging left 53 | | right t # sum : tagginf right 54 | | case t of left x => t / right x => t 55 | | fix t 56 | 57 | v ::= # values 58 | true 59 | | false 60 | | λ x : T . t # abstraction value 61 | | nv # numeric value 62 | | unit 63 | | ( v , v ) # pair value 64 | | left v # sum value : tagging left 65 | | right v # sum value : tagging right 66 | 67 | nv ::= # numeric values: 68 | 0 # zero 69 | | succ nv # successor value 70 | 71 | # variables 72 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 73 | 74 | T ::= # types 75 | Bool # type of booleans 76 | | Nat # type of natural numbers 77 | | T -> T # type of functions 78 | | Unit # unit type 79 | | T * T # product type 80 | | T + T # sum type 81 | 82 | Γ ::= # contexts 83 | φ # empty context 84 | | Γ, x : T # term variable binding 85 | 86 | s ::= t # term 87 | y ::= x # variable 88 | z ::= x # variable 89 | 90 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 91 | # t, s : 項を表すメタ変数 92 | } 93 | 94 | # 評価文脈の文法 95 | context syntax { 96 | E ::= 97 | _ t # 適用 s t の形はまず左側の s を簡約する 98 | | v _ # 左側が値 v になったら右側を簡約する 99 | | succ _ # E-Succ 100 | | pred _ # E-Pred 101 | | iszero _ # E-IsZero 102 | | if _ then t else t # E-If 103 | | _ as T # E-Ascribe2 104 | | let x = _ in t # E-Let 105 | | _ . 1 # E-Proj1 106 | | _ . 2 # E-Proj2 107 | | ( _ , t ) # E-Pair1 : ペアは左側から評価する 108 | | ( v , _ ) # E-Pair2 : 左側が値になったら右側へ 109 | | case _ of left x => t / right x => t 110 | | left _ 111 | | right _ 112 | | fix _ 113 | } 114 | 115 | # 評価文脈の展開ルール 116 | context rule { 117 | E [t] -> E [t'] { 118 | t -> t' 119 | } 120 | } 121 | 122 | # T-Abs 123 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 { 124 | Γ, x : T1 ⊢ t : T2 125 | } 126 | 127 | # T-App 128 | Γ ⊢ t1 t2 : T2 { 129 | Γ ⊢ t1 : T1 -> T2 130 | Γ ⊢ t2 : T1 131 | } 132 | 133 | # T-Var 134 | Γ ⊢ x : T { 135 | x : T ∈ Γ 136 | } 137 | 138 | # type for x in Γ is T <=> x : T ∈ Γ 139 | x : T ∈ (Γ, x : T) 140 | x : T1 ∈ (Γ, y : T2) { 141 | 142 | x : T1 ∈ Γ 143 | } 144 | 145 | # 右側が値になったらベータ簡約する 146 | (λ x : T . t) v -> s' { 147 | [x -> v] t => s' 148 | } 149 | 150 | # 簡約の反射推移閉包 151 | t1 --> t2 { 152 | t1 -> t3 153 | t3 --> t2 154 | } 155 | t1 --> t2 { 156 | t1 -> t2 157 | } 158 | t1 --> t1 159 | 160 | # ベータ簡約 161 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 162 | 163 | # x は x の中で自由なので s に置き換える 164 | [x -> s] x => s 165 | # x と異なる変数 y の中に x はないので y のまま 166 | [x -> s] y => y { 167 | 168 | } 169 | 170 | # t1 t2 は、それぞれの項の中で置き換える 171 | [x -> s] (t1 t2) => t1' t2' { 172 | [x -> s] t1 => t1' 173 | [x -> s] t2 => t2' 174 | } 175 | 176 | # true と false はそのまま 177 | [x -> s] true => true 178 | [x -> s] false => false 179 | 180 | # 0 はそのまま 181 | [x -> s] 0 => 0 182 | 183 | # succ t は、t の中で置き換える 184 | [x -> s] (succ t1) => succ t1' { 185 | [x -> s] t1 => t1' 186 | } 187 | 188 | # pred t は、t の中で置き換える 189 | [x -> s] (pred t1) => pred t1' { 190 | [x -> s] t1 => t1' 191 | } 192 | 193 | # iszero t は、t の中で置き換える 194 | [x -> s] (iszero t1) => iszero t1' { 195 | [x -> s] t1 => t1' 196 | } 197 | 198 | # fix t は、t の中で置き換える 199 | [x -> s] (fix t1) => fix t1' { 200 | [x -> s] t1 => t1' 201 | } 202 | 203 | # if t1 then t2 else t3 は、各項の中で置き換える 204 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' { 205 | [x -> s] t1 => t1' 206 | [x -> s] t2 => t2' 207 | [x -> s] t3 => t3' 208 | } 209 | # λx. t1 の中に自由な x はないのでそのまま 210 | [x -> s] (λx : T. t1) => λx : T. t1 211 | 212 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 213 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 214 | # そんな y がないという条件でそうする 215 | [x -> s] (λy : T. t1) => λy : T. t2 { 216 | 217 | 218 | [x -> s] t1 => t2 219 | } 220 | 221 | # λy. t1 で s の中に自由な y があるときは、 222 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 223 | # その際は仮引数の y と t1 の中の自由な y を z に変える 224 | [x -> s] (λy : T. t1) => λz : T. t2 { 225 | 226 | free y in s 227 | X z # 新しい変数 z を、以下を満たすように 228 | # バックトラックを繰り返して探す 229 | # つまり z は x, y や s, t1 の中の自由変数の 230 | # どれとも異なる 231 | # z の条件ここまで 232 | [y -> z] t1 => t3 233 | [x -> s] t3 => t2 234 | } 235 | 236 | # free x in t : 項 t に x が自由変数として出現する 237 | free x in x 238 | free x in t1 t2 { 239 | free x in t1 240 | } 241 | free x in t1 t2 { 242 | free x in t2 243 | } 244 | free x in λy : T. t { 245 | 246 | free x in t 247 | } 248 | 249 | # Nat 250 | Γ ⊢ 0 : Nat 251 | Γ ⊢ succ t1 : Nat { 252 | Γ ⊢ t1 : Nat 253 | } 254 | Γ ⊢ pred t1 : Nat { 255 | Γ ⊢ t1 : Nat 256 | } 257 | Γ ⊢ iszero t1 : Bool { 258 | Γ ⊢ t1 : Nat 259 | } 260 | 261 | pred 0 -> 0 # E-PredZero 262 | pred (succ nv) -> nv # E-PredSucc 263 | iszero 0 -> true # E-IsZeroZero 264 | iszero (succ nv) -> false # E-IsZeroSucc 265 | 266 | # Bool 267 | 268 | # T-True, T-False 269 | Γ ⊢ true : Bool 270 | Γ ⊢ false : Bool 271 | 272 | # T-If 273 | Γ ⊢ if t1 then t2 else t3 : T { 274 | Γ ⊢ t1 : Bool 275 | Γ ⊢ t2 : T 276 | Γ ⊢ t3 : T 277 | } 278 | 279 | if true then t2 else t3 -> t2 # E-IfTrue 280 | if false then t2 else t3 -> t3 # E-ifFalse 281 | 282 | # E-Ascribe 283 | v as T -> v 284 | 285 | # T-Ascribe 286 | Γ ⊢ t as T : T { 287 | Γ ⊢ t : T 288 | } 289 | 290 | # unit -- derived form 291 | # t1 ; t2 は (λ x : Unit. t2) t1 の糖衣構文 292 | # ただし x は t2 の中に自由変数として現れない 293 | (t1 ; t2) --> t3 { 294 | 295 | (λ x : Unit. t2) t1 --> t3 296 | } 297 | 298 | # T-Unit 299 | Γ ⊢ unit : Unit 300 | 301 | # unit は変数を含まないのでそのまま 302 | [x -> s] unit => unit 303 | 304 | # E-LetV 305 | let x = v in t -> s { 306 | [x -> v] t => s 307 | } 308 | 309 | # T-Let 310 | Γ ⊢ let x = t1 in t2 : T2 { 311 | Γ ⊢ t1 : T1 312 | Γ, x : T1 ⊢ t2 : T2 313 | } 314 | 315 | # Pair : (t1, t2) は、それぞれの項の中で置き換える 316 | [x -> s] (t1, t2) => (t1', t2') { 317 | [x -> s] t1 => t1' 318 | [x -> s] t2 => t2' 319 | } 320 | 321 | # t . 1 は t の中で置き換える 322 | [x -> s] t . 1 => t' . 1 { 323 | [x -> s] t => t' 324 | } 325 | [x -> s] t . 2 => t' . 2 { 326 | [x -> s] t => t' 327 | } 328 | 329 | # E-PairBeta 330 | (v1, v2) . 1 -> v1 331 | (v1, v2) . 2 -> v2 332 | 333 | # T-Pair 334 | Γ ⊢ (t1, t2) : T1 * T2 { 335 | Γ ⊢ t1 : T1 336 | Γ ⊢ t2 : T2 337 | } 338 | # T-Proj 339 | Γ ⊢ t . 1 : T1 { 340 | Γ ⊢ (t1, t2) : T1 * T2 341 | } 342 | Γ ⊢ t . 2 : T2 { 343 | Γ ⊢ (t1, t2) : T1 * T2 344 | } 345 | 346 | # E-CaseLeft 347 | case (left v) of left x1 => t1 / right x2 => t2 -> t3 { 348 | [x1 -> v] t1 => t3 349 | } 350 | case (right v) of left x1 => t1 / right x2 => t2 -> t3 { 351 | [x2 -> v] t1 => t3 352 | } 353 | 354 | # T-Left 355 | Γ ⊢ left t1 : T1 + T2 { 356 | Γ ⊢ t1 : T1 357 | } 358 | # T-Right 359 | Γ ⊢ right t2 : T1 + T2 { 360 | Γ ⊢ t2 : T2 361 | } 362 | # T-Case 363 | Γ ⊢ case t0 of left x1 => t1 / right x2 => t2 : T { 364 | Γ ⊢ t0 : T1 + T2 365 | Γ, x1 : T1 ⊢ t1 : T 366 | Γ, x2 : T2 ⊢ t2 : T 367 | } 368 | 369 | # T-Fix 370 | Γ ⊢ fix t1 : T { 371 | Γ ⊢ t1 : T -> T 372 | } 373 | 374 | # E-Fix 375 | fix (λx : T. t) -> t' { 376 | [x -> fix (λx : T. t)] t => t' 377 | } 378 | 379 | main { 380 | fix (λe : (Nat -> Bool) . λn : Nat . if iszero n then true else (if iszero (pred n) then false else e (pred (pred n)))) (succ succ 0) --> w 381 | } -------------------------------------------------------------------------------- /example/tapl.record.pattern.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : record 2 | use do end for block 3 | 4 | op 99 : _ _ 5 | op 90 : not _ 6 | op 90 : X _ 7 | op 80 : succ _ # successor 8 | op 80 : pred _ # predecessor 9 | op 80 : iszero _ # zero test 10 | op 74 : _ - _ 11 | op 72 : _ = _ 12 | op 71 r : _ , _ 13 | op 70 : { _ } # tuple 14 | op 60 : _ . _ # projection 15 | op 50 : λ _ : _ . _ 16 | op 50 : if _ then _ else _ 17 | op 50 : let _ = _ in _ 18 | op 50 : [ _ -> _ ] _ 19 | op 40 r : _ -> _ 20 | op 30 : _ : _ 21 | op 30 : _ \= _ 22 | op 20 : _ is _ 23 | op 15 : _ : _ ∈ _ 24 | op 10 : _ ⊢ _ : _ 25 | op 10 : _ => _ 26 | op 10 : _ --> _ 27 | op 10 : free _ in _ 28 | 29 | syntax do 30 | t ::= # terms 31 | true # constant true 32 | | false # constant false 33 | | x # variables 34 | | λ x : T . t # abstraction value 35 | | t t # application 36 | | if t then t else t # conditional 37 | | 0 # constant zero 38 | | succ t # successor 39 | | pred t # predecessor 40 | | iszero t # zero test 41 | | { ts } # tuple 42 | | t . n # projection 43 | | { lt } # label-term pairs 44 | | t . l # label projection 45 | | let p = t in t # pattern binding 46 | 47 | p ::= 48 | x # variable pattern 49 | | { ps } # record pattern 50 | 51 | ps ::= l = p | l = p , ps 52 | 53 | ts ::= t | t, ts 54 | 55 | lt ::= l = t | l = t , lt 56 | l ::= 57 | 58 | v ::= # values 59 | true 60 | | false 61 | | λ x : T . t # abstraction value 62 | | nv # numeric value 63 | | { vs } # tuple value 64 | | { lv } # label-value pairs 65 | 66 | vs ::= v | v, vs 67 | 68 | lv ::= l = v | l = v , lv 69 | 70 | nv ::= # numeric values: 71 | 0 # zero 72 | | succ nv # successor value 73 | 74 | n ::= 75 | 76 | # variables 77 | x ::= a | b | c | d | e | f | g | h | i | j | k | l | m | n 78 | 79 | T ::= # types 80 | Bool # type of booleans 81 | | Nat # type of natural numbers 82 | | T -> T # type of functions 83 | | { Ts } # tuple 84 | | { LT } # record type : label-type pairs 85 | 86 | Ts ::= T | T, Ts 87 | 88 | LT ::= l : T | (l : T) , LT # record 89 | 90 | Γ ::= # contexts 91 | φ # empty context 92 | | Γ, x : T # term variable binding 93 | 94 | s ::= t # term 95 | y ::= x # variable 96 | z ::= x # variable 97 | 98 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 99 | # t, s : 項を表すメタ変数 100 | end 101 | 102 | # T-Abs 103 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 do 104 | Γ, x : T1 ⊢ t : T2 105 | end 106 | 107 | # T-App 108 | Γ ⊢ t1 t2 : T2 do 109 | Γ ⊢ t1 : T1 -> T2 110 | Γ ⊢ t2 : T1 111 | end 112 | 113 | # T-Var 114 | Γ ⊢ x : T do 115 | x : T ∈ Γ 116 | end 117 | 118 | # type for x in Γ is T <=> x : T ∈ Γ 119 | x : T ∈ (Γ, x : T) 120 | x : T1 ∈ (Γ, y : T2) do 121 | 122 | x : T1 ∈ Γ 123 | end 124 | 125 | # 適用 t s の形はまず左側の t を簡約する 126 | t s -> t' s do 127 | t -> t' 128 | end 129 | # 左側が値になったら右側を簡約する 130 | v t -> v t' do 131 | t -> t' 132 | end 133 | 134 | # 右側が値になったらベータ簡約する 135 | (λ x : T . t) v -> s' do 136 | [x -> v] t => s' 137 | end 138 | 139 | # 簡約の反射推移閉包 140 | t1 --> t2 do 141 | t1 -> t3 142 | t3 --> t2 143 | end 144 | t1 --> t2 do 145 | t1 -> t2 146 | end 147 | t1 --> t1 148 | 149 | # ベータ簡約 150 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 151 | 152 | # true と false はそのまま 153 | [x -> s] true => true 154 | [x -> s] false => false 155 | 156 | # succ t は、t の中で置き換える 157 | [x -> s] (succ t1) => succ t1' do 158 | [x -> s] t1 => t1' 159 | end 160 | 161 | # pred t は、t の中で置き換える 162 | [x -> s] (pred t1) => pred t1' do 163 | [x -> s] t1 => t1' 164 | end 165 | 166 | # iszero t は、t の中で置き換える 167 | [x -> s] (iszero t1) => iszero t1' do 168 | [x -> s] t1 => t1' 169 | end 170 | 171 | # if t1 then t2 else t3 は、各項の中で置き換える 172 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' do 173 | [x -> s] t1 => t1' 174 | [x -> s] t2 => t2' 175 | [x -> s] t3 => t3' 176 | end 177 | 178 | # x は x の中で自由なので s に置き換える 179 | [x -> s] x => s 180 | # x と異なる変数 y の中に x はないので y のまま 181 | [x -> s] y => y do 182 | 183 | end 184 | 185 | # t1 t2 は、それぞれの項の中で置き換える 186 | [x -> s] (t1 t2) => t1' t2' do 187 | [x -> s] t1 => t1' 188 | [x -> s] t2 => t2' 189 | end 190 | 191 | # λx. t1 の中に自由な x はないのでそのまま 192 | [x -> s] (λx : T. t1) => λx : T. t1 193 | 194 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 195 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 196 | # そんな y がないという条件でそうする 197 | [x -> s] (λy : T. t1) => λy : T. t2 do 198 | 199 | 200 | [x -> s] t1 => t2 201 | end 202 | 203 | # λy. t1 で s の中に自由な y があるときは、 204 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 205 | # その際は仮引数の y と t1 の中の自由な y を z に変える 206 | [x -> s] (λy : T. t1) => λz : T. t2 do 207 | 208 | free y in s 209 | X z # 新しい変数 z を、以下を満たすように 210 | # バックトラックを繰り返して探す 211 | # つまり z は x, y や s, t1 の中の自由変数の 212 | # どれとも異なる 213 | # z の条件ここまで 214 | [y -> z] t1 => t3 215 | [x -> s] t3 => t2 216 | end 217 | 218 | # free x in t : 項 t に x が自由変数として出現する 219 | free x in x 220 | free x in t1 t2 do 221 | free x in t1 222 | end 223 | free x in t1 t2 do 224 | free x in t2 225 | end 226 | free x in λy : T. t do 227 | 228 | free x in t 229 | end 230 | 231 | # Nat 232 | Γ ⊢ 0 : Nat 233 | Γ ⊢ succ t1 : Nat do 234 | Γ ⊢ t1 : Nat 235 | end 236 | Γ ⊢ pred t1 : Nat do 237 | Γ ⊢ t1 : Nat 238 | end 239 | Γ ⊢ iszero t1 : Bool do 240 | Γ ⊢ t1 : Nat 241 | end 242 | 243 | succ t1 -> succ t2 do # E-Succ 244 | t1 -> t2 245 | end 246 | pred 0 -> 0 # E-PredZero 247 | pred (succ nv) -> nv # E-PredSucc 248 | pred t1 -> pred t1' do # E-Pred 249 | t1 -> t1' 250 | end 251 | iszero 0 -> true # E-IsZeroZero 252 | iszero (succ nv) -> false # E-IsZeroSucc 253 | iszero t1 -> iszero t1' do # E-IsZero 254 | t1 -> t1' 255 | end 256 | 257 | # Bool 258 | 259 | # T-True, T-False 260 | Γ ⊢ true : Bool 261 | Γ ⊢ false : Bool 262 | 263 | # T-If 264 | Γ ⊢ if t1 then t2 else t3 : T do 265 | Γ ⊢ t1 : Bool 266 | Γ ⊢ t2 : T 267 | Γ ⊢ t3 : T 268 | end 269 | 270 | if true then t2 else t3 -> t2 # E-IfTrue 271 | if false then t2 else t3 -> t3 # E-ifFalse 272 | # E-If 273 | if t1 then t2 else t3 -> if t1' then t2 else t3 do 274 | t1 -> t1' 275 | end 276 | 277 | {v, vs} . 1 -> v 278 | {v1, vs} . n1 -> v2 do 279 | 280 | {vs} . n2 -> v2 281 | end 282 | {v} . 1 -> v 283 | 284 | t . n -> t' . n do 285 | t -> t' 286 | end 287 | 288 | {v, ts} -> {v, ts'} do 289 | {ts} -> {ts'} 290 | end 291 | {t, ts} -> {t', ts} do 292 | t -> t' 293 | end 294 | {t} -> {t'} do 295 | t -> t' 296 | end 297 | 298 | # T-Tuple 299 | Γ ⊢ {t1, ts} : {T1, Ts} do 300 | Γ ⊢ t1 : T1 301 | Γ ⊢ {ts} : {Ts} 302 | end 303 | Γ ⊢ {t} : {T} do 304 | Γ ⊢ t : T 305 | end 306 | 307 | # T-Proj 308 | Γ ⊢ {t} . 1 : T do 309 | Γ ⊢ t : T 310 | end 311 | Γ ⊢ {t, ts} . 1 : T do 312 | Γ ⊢ t : T 313 | end 314 | Γ ⊢ {t1, ts} . n1 : T2 do 315 | 316 | Γ ⊢ {ts} . n2 : T2 317 | end 318 | 319 | # E-ProjRcd 320 | {l = v, lv} . l -> v 321 | {l1 = v1, lv} . l2 -> v2 do 322 | 323 | {lv} . l2 -> v2 324 | end 325 | {l = v} . l -> v 326 | 327 | # E-Proj 328 | t . l -> t' . l do 329 | t -> t' 330 | end 331 | 332 | # E-Rcd 333 | {l = v, lt} -> {l = v, lt'} do 334 | {lt} -> {lt'} 335 | end 336 | {l = t, lt} -> {l = t', lt} do 337 | t -> t' 338 | end 339 | {l = t} -> {l = t'} do 340 | t -> t' 341 | end 342 | 343 | # T-Rcd 344 | Γ ⊢ {l1 = t1, lt} : {(l1 : T1), LT} do 345 | Γ ⊢ t1 : T1 346 | Γ ⊢ {lt} : {LT} 347 | end 348 | 349 | Γ ⊢ {l = t} : {(l : T)} do 350 | Γ ⊢ t : T 351 | end 352 | 353 | # T-ProjRcd 354 | Γ ⊢ {l = t} . l : T do 355 | Γ ⊢ t : T 356 | end 357 | Γ ⊢ {l = t, lt} . l : T do 358 | Γ ⊢ t : T 359 | end 360 | Γ ⊢ {l1 = t1, lt} . l2 : T2 do 361 | 362 | Γ ⊢ {lt} . l2 : T2 363 | end 364 | 365 | # E-LetV 366 | let x = v in t1 -> t2 do 367 | [x -> v] t1 => t2 368 | end 369 | let {l = p} = {l = v} in t2 -> t3 do 370 | [p -> v] t2 => t3 371 | end 372 | let {l1 = p} = {l2 = v} in t2 -> t2 373 | let {l = p} = {l = v, lt} in t2 -> t3 do 374 | [p -> v] t2 => t3 375 | end 376 | let {l1 = p} = {l2 = v, lt} in t2 -> t3 do 377 | 378 | let {l1 = p} = {lt} in t2 -> t3 379 | end 380 | let {l1 = p, ps} = t1 in t2 -> t4 do 381 | let {l1 = p} = t1 in t2 -> t3 382 | let {ps} = t1 in t3 -> t4 383 | end 384 | 385 | # E-Let 386 | let p = t1 in t2 -> let p = t1' in t2 do 387 | t1 -> t1' 388 | end 389 | 390 | # {t, ts} は、それぞれの項の中で置き換える 391 | [x -> s] {t, ts} => {t', ts'} do 392 | [x -> s] t => t' 393 | [x -> s] ts => ts' 394 | end 395 | [x -> s] {t} => {t'} do 396 | [x -> s] t => t' 397 | end 398 | 399 | main do 400 | let {age = a, man = b} = {age = 0, man = true} in {succ a, b} --> v 401 | # v = {succ 0, true} 402 | 403 | # let {age = a} = {man = true} in 0 -> w 404 | # w = 0 405 | # let {age = a, man = b} = {age = 0} in a -> w 406 | # w = 0 407 | # let {age = a} = {man = true, age = 0} in a --> v 408 | # let {man = a} = {man = true, age = 0} in a --> v 409 | # let {age = a} = {age = 0} in a --> v 410 | # let a = {age = 0, man = true} in a --> v 411 | # t? let {age = a, man = b} = {age = 0, man = true} in a 412 | # p? {age = a, man = b, woman = c} 413 | end 414 | -------------------------------------------------------------------------------- /example/tapl.simple.full.ron: -------------------------------------------------------------------------------- 1 | # simply typed lambda calculus : simple extension : full 2 | use % for newline 3 | use do end for block 4 | 5 | op 99 : _ _ 6 | op 99 : succ _ # successor 7 | op 99 : pred _ # predecessor 8 | op 99 : iszero _ # zero test 9 | op 99 : fix _ # fix 10 | op 99 : nil [ _ ] # empty list 11 | op 99 : cons [ _ ] _ _ # list constructor 12 | op 99 : isnil [ _ ] _ # test for empty list 13 | op 99 : head [ _ ] _ # head of a list 14 | op 99 : tail [ _ ] _ # tail of a list 15 | op 99 : List _ # type of lists 16 | op 90 : not _ 17 | op 90 : X _ 18 | op 75 : _ * _ # product type 19 | op 74 : _ - _ 20 | op 74 : _ > _ 21 | op 72 : _ = _ 22 | op 70 : _ + _ # sum type 23 | op 68 r : _ , _ 24 | op 65 : { _ } # record, tuple 25 | op 65 : ≺ _ ≻ as _ # variant 26 | op 65 : ≺ _ ≻ => _ # variant case 27 | op 63 : ≺ _ ≻ # variant 28 | op 60 : _ . _ # projection 29 | op 55 : _ as _ # ascription 30 | op 50 : let _ = _ in _ 31 | op 50 : λ _ : _ . _ 32 | op 50 : if _ then _ else _ 33 | op 50 : letrec _ : _ = _ in _ # recursion 34 | op 50 : left _ 35 | op 50 : right _ 36 | op 50 : case _ of left _ => _ / right _ => _ 37 | op 48 r : _ / _ # case separator 38 | op 45 : case _ of _ # variant case 39 | op 50 : [ _ -> _ ] _ 40 | op 100 : map _ _ _ => _ 41 | op 40 r : _ -> _ 42 | op 30 : _ : _ 43 | op 30 : _ \= _ 44 | op 25 : _ ; _ 45 | op 20 : _ is _ 46 | op 15 : _ : _ ∈ _ 47 | op 10 : _ ⊢ _ : _ 48 | op 10 : _ => _ 49 | op 10 : _ --> _ 50 | op 10 : free _ in _ 51 | 52 | syntax do 53 | t ::= # terms 54 | true # constant true 55 | | false # constant false 56 | | x # variables 57 | | λ x : T . t # abstraction value 58 | | t t # application 59 | | if t then t else t # conditional 60 | | 0 # constant zero 61 | | succ t # successor 62 | | pred t # predecessor 63 | | iszero t # zero test 64 | | t as T # ascription 65 | | unit 66 | | let x = t in t # let binding 67 | | { ts } # tuple 68 | | t . n # tuple projection 69 | | left t # sum : tagging left 70 | | right t # sum : tagginf right 71 | | case t of left x => t / right x => t 72 | | fix t 73 | | nil [ T ] # empty list 74 | | cons [ T ] t t # list constructor 75 | | isnil [ T ] t # test for empty list 76 | | head [ T ] t # head of a list 77 | | tail [ T ] t # tail of a list 78 | | { lt } # record : {a = 1, b = 2} 79 | | t . l # label 80 | | ≺ l = t ≻ as T # variant tagging 81 | | case t of cs # case 82 | 83 | ts ::= φ | t , ts # list of term 84 | lt ::= φ | l = t , lt # list of label = term 85 | l ::= # record label 86 | n ::= # 1, 2, 3, ... 87 | 88 | cs ::= φ | ≺ l = x ≻ => t / cs 89 | 90 | v ::= # values 91 | true 92 | | false 93 | | λ x : T . t # abstraction value 94 | | nv # numeric value 95 | | unit 96 | | { vs } # tuple value 97 | | left v # sum value : tagging left 98 | | right v # sum value : tagging right 99 | | nil [ T ] # empty list 100 | | cons [ T ] v v # list constructor 101 | | { lv } # record value 102 | 103 | vs ::= φ | v , vs # values 104 | nv ::= # numeric values: 105 | 0 # zero 106 | | succ nv # successor value 107 | lv ::= φ | l = v , lv # record values 108 | 109 | # variables 110 | x ::= a | b | c | d | e | f | g | h | i | j | k | m 111 | 112 | T ::= # types 113 | Bool # type of booleans 114 | | Nat # type of natural numbers 115 | | T -> T # type of functions 116 | | Unit # unit type 117 | | T * T # type of products 118 | | T + T # type of sums 119 | | List T # type of lists 120 | | { Ts } # tuple type 121 | | { lT } # record type 122 | | ≺ lT ≻ # variant type 123 | 124 | Ts ::= φ | T , Ts # list of types 125 | lT ::= φ | (l : T), lT # record type 126 | 127 | Γ ::= # contexts 128 | φ # empty context 129 | | Γ, x : T # term variable binding 130 | 131 | s ::= t # term 132 | y ::= x # variable 133 | z ::= x # variable 134 | 135 | S ::= T # type variable 136 | 137 | # x, y, z : 変数を表すメタ変数:実際の変数は a から n までの1文字 138 | # t, s : 項を表すメタ変数 139 | # S, T : 型を表すメタ変数 140 | end 141 | 142 | # 評価文脈の文法 143 | context syntax do 144 | E ::= 145 | _ t # 適用 s t の形はまず左側の s を簡約する 146 | | v _ # 左側が値 v になったら右側を簡約する 147 | | succ _ # E-Succ 148 | | pred _ # E-Pred 149 | | iszero _ # E-IsZero 150 | | if _ then t else t # E-If 151 | | _ as T # E-Ascribe2 152 | | let x = _ in t # E-Let 153 | | case _ of left x => t / right x => t 154 | | left _ 155 | | right _ 156 | | fix _ 157 | | cons [ T ] _ t # E-Cons1 158 | | cons [ T ] v _ # E-Cons2 159 | | isnil [ T ] _ # E-IsNil 160 | | _ . n # E-Proj 161 | | { _ , ts } # E-Tuple1 162 | | _ . l # E-Proj Record 163 | | case _ of cs # E-Case 164 | | ≺ l = _ ≻ as T # E-Variant 165 | end 166 | 167 | # 評価文脈の展開ルール 168 | context rule do 169 | E [t] -> E [t'] do 170 | t -> t' 171 | end 172 | end 173 | 174 | # T-Abs 175 | Γ ⊢ (λ x : T1 . t) : T1 -> T2 do 176 | Γ, x : T1 ⊢ t : T2 177 | end 178 | 179 | # T-App 180 | Γ ⊢ t1 t2 : T2 do 181 | Γ ⊢ t1 : T1 -> T2 182 | Γ ⊢ t2 : T1 183 | end 184 | 185 | # T-Var 186 | Γ ⊢ x : T do 187 | x : T ∈ Γ 188 | end 189 | 190 | # type for x in Γ is T <=> x : T ∈ Γ 191 | x : T ∈ (Γ, x : T) 192 | x : T1 ∈ (Γ, y : T2) do 193 | 194 | x : T1 ∈ Γ 195 | end 196 | 197 | # 右側が値になったらベータ簡約する 198 | (λ x : T . t) v -> s' do 199 | [x -> v] t => s' 200 | end 201 | 202 | # 簡約の反射推移閉包 203 | t1 --> t2 do 204 | t1 -> t3 205 | t3 --> t2 206 | end 207 | t1 --> t2 do 208 | t1 -> t2 209 | end 210 | t1 --> t1 211 | 212 | # ベータ簡約 213 | # [x -> s] t => u で、t の自由な x を s に置き換えると u になる、の意味 214 | 215 | # x は x の中で自由なので s に置き換える 216 | [x -> s] x => s 217 | # x と異なる変数 y の中に x はないので y のまま 218 | [x -> s] y => y do 219 | 220 | end 221 | 222 | # t1 t2 は、それぞれの項の中で置き換える 223 | [x -> s] (t1 t2) => t1' t2' do 224 | [x -> s] t1 => t1' 225 | [x -> s] t2 => t2' 226 | end 227 | 228 | # true と false はそのまま 229 | [x -> s] true => true 230 | [x -> s] false => false 231 | 232 | # 0 はそのまま 233 | [x -> s] 0 => 0 234 | 235 | # succ t は、t の中で置き換える 236 | [x -> s] (succ t1) => succ t1' do 237 | [x -> s] t1 => t1' 238 | end 239 | 240 | # pred t は、t の中で置き換える 241 | [x -> s] (pred t1) => pred t1' do 242 | [x -> s] t1 => t1' 243 | end 244 | 245 | # iszero t は、t の中で置き換える 246 | [x -> s] (iszero t1) => iszero t1' do 247 | [x -> s] t1 => t1' 248 | end 249 | 250 | # if t1 then t2 else t3 は、各項の中で置き換える 251 | [x -> s] (if t1 then t2 else t3) => if t1' then t2' else t3' do 252 | [x -> s] t1 => t1' 253 | [x -> s] t2 => t2' 254 | [x -> s] t3 => t3' 255 | end 256 | # λx. t1 の中に自由な x はないのでそのまま 257 | [x -> s] (λx : T. t1) => λx : T. t1 258 | 259 | # λy. t1 は、t1 の x を s に置き換えたものとしたいが 260 | # s の中に自由な y があると λy. で束縛されて意味か変わってしまうので、 261 | # そんな y がないという条件でそうする 262 | [x -> s] (λy : T. t1) => λy : T. t2 do 263 | 264 | 265 | [x -> s] t1 => t2 266 | end 267 | 268 | # λy. t1 で s の中に自由な y があるときは、 269 | # そもそも λy. t1 の中の y を無関係な変数 z に変える 270 | # その際は仮引数の y と t1 の中の自由な y を z に変える 271 | [x -> s] (λy : T. t1) => λz : T. t2 do 272 | 273 | free y in s 274 | X z # 新しい変数 z を、以下を満たすように 275 | # バックトラックを繰り返して探す 276 | # つまり z は x, y や s, t1 の中の自由変数の 277 | # どれとも異なる 278 | # z の条件ここまで 279 | [y -> z] t1 => t3 280 | [x -> s] t3 => t2 281 | end 282 | 283 | # free x in t : 項 t に x が自由変数として出現する 284 | free x in x 285 | free x in t1 t2 do 286 | free x in t1 287 | end 288 | free x in t1 t2 do 289 | free x in t2 290 | end 291 | free x in λy : T. t do 292 | 293 | free x in t 294 | end 295 | 296 | # Nat 297 | Γ ⊢ 0 : Nat 298 | Γ ⊢ succ t1 : Nat do 299 | Γ ⊢ t1 : Nat 300 | end 301 | Γ ⊢ pred t1 : Nat do 302 | Γ ⊢ t1 : Nat 303 | end 304 | Γ ⊢ iszero t1 : Bool do 305 | Γ ⊢ t1 : Nat 306 | end 307 | 308 | pred 0 -> 0 # E-PredZero 309 | pred (succ nv) -> nv # E-PredSucc 310 | iszero 0 -> true # E-IsZeroZero 311 | iszero (succ nv) -> false # E-IsZeroSucc 312 | 313 | # Bool 314 | 315 | # T-True, T-False 316 | Γ ⊢ true : Bool 317 | Γ ⊢ false : Bool 318 | 319 | # T-If 320 | Γ ⊢ if t1 then t2 else t3 : T do 321 | Γ ⊢ t1 : Bool 322 | Γ ⊢ t2 : T 323 | Γ ⊢ t3 : T 324 | end 325 | 326 | if true then t2 else t3 -> t2 # E-IfTrue 327 | if false then t2 else t3 -> t3 # E-ifFalse 328 | 329 | # E-Ascribe 330 | v as T -> v 331 | 332 | # T-Ascribe 333 | Γ ⊢ t as T : T do 334 | Γ ⊢ t : T 335 | end 336 | 337 | # unit -- derived form 338 | # t1 ; t2 は (λ x : Unit. t2) t1 の糖衣構文 339 | # ただし x は t2 の中に自由変数として現れない 340 | (t1 ; t2) --> t3 do 341 | 342 | (λ x : Unit. t2) t1 --> t3 343 | end 344 | 345 | # T-Unit 346 | Γ ⊢ unit : Unit 347 | 348 | # unit は変数を含まないのでそのまま 349 | [x -> s] unit => unit 350 | 351 | # E-LetV 352 | let x = v in t -> s do 353 | [x -> v] t => s 354 | end 355 | 356 | # T-Let 357 | Γ ⊢ let x = t1 in t2 : T2 do 358 | Γ ⊢ t1 : T1 359 | Γ, x : T1 ⊢ t2 : T2 360 | end 361 | 362 | # t . 1 は t の中で置き換える 363 | [x -> s] t . 1 => t' . 1 do 364 | [x -> s] t => t' 365 | end 366 | [x -> s] t . 2 => t' . 2 do 367 | [x -> s] t => t' 368 | end 369 | 370 | # E-CaseLeft 371 | case (left v) of left x1 => t1 / right x2 => t2 -> t3 do 372 | [x1 -> v] t1 => t3 373 | end 374 | case (right v) of left x1 => t1 / right x2 => t2 -> t3 do 375 | [x2 -> v] t1 => t3 376 | end 377 | 378 | # T-Left 379 | Γ ⊢ left t1 : T1 + T2 do 380 | Γ ⊢ t1 : T1 381 | end 382 | # T-Right 383 | Γ ⊢ right t2 : T1 + T2 do 384 | Γ ⊢ t2 : T2 385 | end 386 | # T-Case 387 | Γ ⊢ case t0 of left x1 => t1 / right x2 => t2 : T do 388 | Γ ⊢ t0 : T1 + T2 389 | Γ, x1 : T1 ⊢ t1 : T 390 | Γ, x2 : T2 ⊢ t2 : T 391 | end 392 | 393 | # E-Fix 394 | fix (λx : T. t) -> t' do 395 | [x -> fix (λx : T. t)] t => t' 396 | end 397 | 398 | # fix t は、t の中で置き換える 399 | [x -> s] (fix t1) => fix t1' do 400 | [x -> s] t1 => t1' 401 | end 402 | 403 | # letrec : derived form 404 | letrec x : T = t1 in t2 --> t3 do 405 | let x = fix (λx : T. t1) in t2 --> t3 406 | end 407 | 408 | # E-IsNilNil 409 | isnil [S] (nil [T]) -> true 410 | 411 | # E-IsNilCons 412 | isnil [S] (cons [T] v1 v2) -> false 413 | 414 | # E-HeadCons 415 | head [S] (cons [T] v1 v2) -> v1 416 | 417 | # E-TailCons 418 | tail [S] (cons [T] v1 v2) -> v2 419 | 420 | # T-Nil 421 | Γ ⊢ nil [T] : List T 422 | 423 | # T-Cons1 424 | Γ ⊢ cons [T] t1 t2 : List T do 425 | Γ ⊢ t1 : T 426 | Γ ⊢ t2 : List T 427 | end 428 | 429 | # T-IsNil 430 | Γ ⊢ isnil [T] t : Bool do 431 | Γ ⊢ t : List T 432 | end 433 | 434 | # T-Head 435 | Γ ⊢ head [T] t : T do 436 | Γ ⊢ t : List T 437 | end 438 | 439 | # T-Tail 440 | Γ ⊢ tail [T] t : List T do 441 | Γ ⊢ t : List T 442 | end 443 | 444 | # E-ProjTuple 445 | {v, vs} . 1 -> v 446 | {v1, vs} . n1 -> v2 do 447 | 1> 448 | 449 | {vs} . n2 -> v2 450 | end 451 | 452 | # E-Tuple2 453 | {v, ts} -> {v, ts'} do 454 | {ts} -> {ts'} 455 | end 456 | 457 | # T-Tuple 458 | Γ ⊢ {φ} : {φ} 459 | Γ ⊢ {v, vs} : {T, Ts} do 460 | Γ ⊢ v : T 461 | Γ ⊢ {vs} : {Ts} 462 | end 463 | 464 | # T-Proj 465 | Γ ⊢ {t, ts} . 1 : T do 466 | Γ ⊢ t : T 467 | end 468 | Γ ⊢ {t, ts} . n1 : T do 469 | 1> 470 | 471 | Γ ⊢ {ts} . n2 : T 472 | end 473 | 474 | # E-ProjRecord 475 | {l = v, lv} . l -> v 476 | {l1 = v1, lv} . l2 -> v2 do 477 | 478 | {lv} . l2 -> v2 479 | end 480 | 481 | # E-Rcd 482 | {l = v, lt} -> {l = v, lt'} do 483 | {lt} -> {lt'} 484 | end 485 | {l = t, lt} -> {l = t', lt} do 486 | t -> t' 487 | end 488 | 489 | # T-Rcd 490 | Γ ⊢ {l = t, lt} : {(l : T), LT} do 491 | Γ ⊢ t : T 492 | Γ ⊢ {lt} : {LT} 493 | end 494 | 495 | # T-Proj 496 | Γ ⊢ {l = t, lt} . l : T do 497 | Γ ⊢ t : T 498 | end 499 | Γ ⊢ {l1 = t1, lt} . l2 : T2 do 500 | 501 | Γ ⊢ {lt} . l2 : T2 502 | end 503 | 504 | # E-CaseVariant 505 | (case (≺l = v≻ as T) of ≺l = x≻ => t / cs) -> t2 do 506 | [x -> v] t => t2 507 | end 508 | (case (≺l1 = v≻ as T) of ≺l2 = x≻ => t / cs) -> t2 do 509 | 510 | (case (≺l1 = v≻ as T) of cs) -> t2 511 | end 512 | 513 | # T-Variant 514 | Γ ⊢ (≺l = t≻ as ≺(l : T), lT≻) : ≺(l : T), lT≻ do 515 | Γ ⊢ t : T 516 | end 517 | Γ ⊢ (≺l1 = t1≻ as ≺(l2 : T2), lT≻) : ≺(l2 : T2), lT≻ do 518 | 519 | Γ ⊢ (≺l1 = t1≻ as ≺lT≻) : ≺lT≻ 520 | end 521 | 522 | # T-Case 523 | Γ ⊢ (case t of φ) : ≺φ≻ 524 | Γ ⊢ (case t of cs) : ≺lT2≻ do 525 | Γ ⊢ t : ≺lT1≻ 526 | map Γ cs lT1 => lT2 527 | end 528 | 529 | map Γ (≺l1 = x1≻ => t1 / cs) ((l1 : T1), lT1) => ((l1 : T1'), lT2) do 530 | Γ, x1 : T1 ⊢ t1 : T1' 531 | map Γ cs lT1 => lT2 532 | end 533 | map Γ φ φ => φ 534 | 535 | main do 536 | # variant 537 | map φ (≺age = a≻ => succ a / ≺mouth = a≻ => succ a / φ) ((age : Nat), (mouth : Nat), φ) => ((age : Nat), (mouth : Nat), φ) 538 | map φ (≺age = a≻ => succ a / φ) ((age : Nat), φ) => ((age : Nat), φ) 539 | map φ φ φ => φ 540 | φ ⊢ (case ≺age = 0≻ as ≺(age : Nat), (mouth : Nat), φ≻ of ≺age = a≻ => succ a / ≺mouth = a≻ => succ succ a / φ) : ≺(age : Nat), (mouth : Nat), φ≻ 541 | φ ⊢ (case ≺age = 0≻ as ≺(age : Nat), φ≻ of ≺age = a≻ => succ a / φ) : ≺(age : Nat), φ≻ 542 | φ ⊢ (case ≺age = 0≻ as ≺(age : Nat), φ≻ of φ) : ≺φ≻ 543 | φ ⊢ ≺man = true≻ as ≺(age : Nat), (man : Bool), φ≻ : ≺(age : Nat), (man : Bool), φ≻ 544 | φ ⊢ ≺age = 0≻ as ≺(age : Nat), φ≻ : ≺(age : Nat), φ≻ 545 | case ≺age = pred succ 0≻ as ≺(age : Nat), φ≻ of ≺age = a≻ => succ a / φ -> case ≺age = 0≻ as ≺(age : Nat), φ≻ of ≺age = a≻ => succ a / φ 546 | ≺age = pred succ 0≻ as ≺(age : Nat), φ≻ -> ≺age = 0≻ as ≺(age : Nat), φ≻ 547 | case ≺mouth = 0≻ as ≺(age : Nat), (mouth : Nat), φ≻ of ≺age = a≻ => succ a / ≺mouth = a≻ => succ succ a / φ -> t2 548 | case ≺age = 0≻ as ≺(age : Nat), φ≻ of ≺age = a≻ => succ a / φ -> t1 549 | t? case a of ≺age = b≻ => c / ≺man = d≻ => e / φ 550 | t? case a of ≺age = b≻ => c / φ 551 | t? case a of φ 552 | T? ≺(age : Nat), φ≻ 553 | T? ≺φ≻ 554 | t? ≺age = 0≻ as Nat 555 | 556 | # record 557 | φ ⊢ {age = 0, man = true, φ} . man : Bool 558 | φ ⊢ {age = 0, man = true, φ} . age : Nat 559 | φ ⊢ {age = 0, man = true, φ} : {(age : Nat), (man : Bool), φ} 560 | φ ⊢ {age = 0, φ} : {(age : Nat), φ} 561 | {age = pred succ 0, φ} . age -> {age = 0, φ} . age 562 | {age = 0, height = pred succ 0, φ} -> {age = 0, height = 0, φ} 563 | {age = pred succ 0, φ} -> {age = 0, φ} 564 | {age = 0, man = true, φ} . man -> true 565 | {age = 0, man = true, φ} . age -> 0 566 | T? { (age : Nat), (man : Bool), φ } 567 | T? { (age : Nat), φ } 568 | v? { age = 0 , man = true , φ } 569 | t? { age = 0 , man = true , φ } 570 | t? { age = 0 , man = true , φ } . age 571 | 572 | # tuple 573 | φ ⊢ {0, succ 0, true, φ} . 3 : Bool 574 | φ ⊢ {0, succ 0, true, φ} . 2 : Nat 575 | φ ⊢ {0, succ 0, true, φ} . 1 : Nat 576 | 577 | φ ⊢ {0, true, φ} : {Nat, Bool, φ} 578 | φ ⊢ {φ} : {φ} 579 | {0, pred succ 0, φ} -> {0, 0, φ} 580 | {pred succ 0, pred succ 0, φ} -> {0, pred succ 0, φ} 581 | 582 | {0, succ 0, true, φ} . 3 -> true 583 | {0, succ 0, true, φ} . 2 -> succ 0 584 | {0, succ 0, true, φ} . 1 -> 0 585 | 586 | T? {Nat, Bool, φ} 587 | T? {φ} 588 | v? {0, true, succ 0, φ} 589 | v? {φ} 590 | t? {0, true, succ 0, φ} 591 | t? {φ} 592 | 593 | φ ⊢ tail [Nat] (cons [Nat] 0 (nil [Nat])) : List Nat 594 | φ ⊢ head [Nat] (cons [Nat] 0 (nil [Nat])) : Nat 595 | φ ⊢ isnil [Nat] (nil [Nat]) : Bool 596 | φ ⊢ cons [Bool] true (nil [Bool]) : List Bool 597 | φ ⊢ nil [Bool] : List Bool 598 | 599 | tail [Bool] (cons [Nat] 0 (cons [Nat] 0 0)) --> cons [Nat] 0 0 600 | head [Bool] (cons [Nat] (succ 0) 0) --> succ 0 601 | isnil [Bool] (cons [Nat] 0 (succ 0)) --> false 602 | isnil [Bool] (nil [Nat]) --> true 603 | 604 | φ ⊢ (left 0) : T1 + Nat 605 | # T1 : Nat 606 | 607 | case (left 0) of left a => succ a / right b => pred b --> v7 608 | # v = succ 0 609 | 610 | (λa : (Nat * Nat) . (a . 2)) {pred succ 0, pred succ succ 0, φ} --> v6 611 | # v6 = succ 0 612 | 613 | let f = λa : Bool. a in f true --> v5 614 | # v5 = true 615 | 616 | (λa: Unit. a) unit ; (λc: Unit. c) (λd: Unit. d) --> v4 617 | # v4 = λ d : Unit . d 618 | 619 | (λa: Nat. a) (succ 0) as Nat --> v3 620 | # v3 = succ 0 621 | 622 | if (iszero 0) then pred succ 0 else succ succ 0 --> v2 623 | # v2 = 0 624 | 625 | (λa : Nat. succ a) (succ (succ 0)) --> v1 626 | # v1 = succ succ succ 0 627 | 628 | letrec e : (Nat -> Bool) = λm : Nat . if iszero m then true else (if iszero (pred m) then false else e (pred pred m)) in e (succ succ 0) --> v8 629 | # v8 = true 630 | 631 | t? 0 632 | end --------------------------------------------------------------------------------