hnock

A Nock interpreter.
Log | Files | Refs | README | LICENSE

commit 98e9a45cb47a5040a028d720db0ed953a109e3c5
parent 6fb16ac98da9b9458b610e5e7470473d6d7954cd
Author: Jared Tobin <jared@jtobin.ca>
Date:   Fri, 13 Jul 2018 10:26:24 +1200

Misc restructuring.

Diffstat:
M.gitignore | 1+
Mlib/Nock.hs | 208++++++++-----------------------------------------------------------------------
Alib/Nock/Eval.hs | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/Nock/Language.hs | 34++++++++++++++++++++++++++++++++++
4 files changed, 206 insertions(+), 189 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1,3 +1,4 @@ +.stack-work *.swp *.swo *.o diff --git a/lib/Nock.hs b/lib/Nock.hs @@ -1,182 +1,11 @@ {-# OPTIONS_GHC -Wall #-} -data Noun = - Atom !Int - | Cell !Noun !Noun - deriving Eq +module Nock ( + module X + ) where -instance Show Noun where - show noun = case noun of - Atom m -> show m - Cell m n -> mconcat ["[", show m, " ", show n, "]"] - -data ExprF a = - Noun !a - | Wut !a - | Lus !a - | Tis !a - | Fas !a - | Tar !a - deriving Eq - -instance Show a => Show (ExprF a) where - show op = case op of - Noun n -> show n - Wut n -> mconcat ["?", show n] - Lus n -> mconcat ["+", show n] - Tis n -> mconcat ["=", show n] - Fas n -> mconcat ["/", show n] - Tar n -> mconcat ["*", show n] - -type Expr = ExprF Noun - -nock :: Expr -> Noun -nock expr = case expr of - Noun noun -> noun - Wut noun -> wut noun - Lus noun -> lus noun - Tis noun -> tis noun - Fas noun -> fas noun - Tar noun -> tar noun - --- production rules - -wut :: Noun -> Noun -wut noun = case noun of - Cell {} -> Atom 0 - Atom {} -> Atom 1 - -lus :: Noun -> Noun -lus noun = case noun of - Cell {} -> error "lus: bad noun" - Atom m -> Atom (1 + m) - -tis :: Noun -> Noun -tis noun = case noun of - Atom {} -> error "tis: bad noun" - Cell m n -> - if m == n - then Atom 0 - else Atom 1 - -fas :: Noun -> Noun -fas noun = case noun of - Atom {} -> error "fas: bad noun" - Cell m n -> case m of - Cell {} -> error "fas: bad noun" - Atom a -> case a of - - 1 -> n - - 2 -> case n of - Atom {} -> error "fas: bad noun" - Cell o _ -> o - - 3 -> case n of - Atom {} -> error "fas: bad noun" - Cell _ o -> o - - _ -> - if even a - then - let inner = Cell (Atom (a `div` 2)) n - in fas (Cell (Atom 2) (fas inner)) - else - let inner = Cell (Atom ((a - 1) `div` 2)) n - in fas (Cell (Atom 3) (fas inner)) - - -tar :: Noun -> Noun -tar noun = case noun of - Atom {} -> error "tar: bad noun" - Cell a m -> case m of - Atom {} -> error "tar: bad noun" - Cell n d -> case n of - Cell b c -> Cell (tar (Cell a (Cell b c))) (tar (Cell a d)) - Atom z -> case z of - - 0 -> fas (Cell d a) - - 1 -> d - - 2 -> case d of - Atom {} -> error "tar: bad noun" - Cell e f -> - tar (Cell (tar (Cell a e)) (tar (Cell a f))) - - 3 -> wut (tar (Cell a d)) - - 4 -> lus (tar (Cell a d)) - - 5 -> tis (tar (Cell a d)) - - 6 -> case d of - Atom {} -> error "tar: bad noun" - Cell g h -> case h of - Atom {} -> error "tar: bad noun" - Cell i j -> tar (tar6 a g i j) - - 7 -> case d of - Atom {} -> error "tar: bad noun" - Cell g h -> - tar (Cell a (Cell (Atom 2) (Cell g (Cell (Atom 1) h)))) - - 8 -> case d of - Atom {} -> error "tar: bad noun" - Cell g h -> tar (tar8 a g h) - - 9 -> case d of - Atom {} -> error "tar: bad noun" - Cell g h -> tar (tar9 a g h) - - 10 -> case d of - Atom {} -> error "tar: bad noun" - Cell g h -> case g of - Cell i j -> tar (tar10 a i j h) - _ -> tar (Cell a h) - - _ -> error "tar: bad noun" - -tar6 :: Noun -> Noun -> Noun -> Noun -> Noun -tar6 a b c d = - Cell a - (Cell (Atom 2) - (Cell (Cell (Atom 0) (Atom 1)) - (Cell (Atom 2) - (Cell (Cell (Atom 1) (Cell c d)) - (Cell (Cell (Atom 1) (Atom 0)) - (Cell (Atom 2) - (Cell (Cell (Atom 1) (Cell (Atom 2) (Atom 3))) - (Cell (Cell (Atom 1) (Atom 0)) - (Cell (Atom 4) - (Cell (Atom 4) b)))))))))) - -tar8 :: Noun -> Noun -> Noun -> Noun -tar8 a b c = - Cell a - (Cell (Atom 7) - (Cell - (Cell (Atom 7) - (Cell (Cell (Atom 0) (Atom 1)) b)) - (Cell (Cell (Atom 0) (Atom 1)) c))) - -tar9 :: Noun -> Noun -> Noun -> Noun -tar9 a b c = - Cell a - (Cell (Atom 7) - (Cell c - (Cell (Atom 2) - (Cell (Cell (Atom 0) (Atom 1)) - (Cell (Atom 0) b))))) - -tar10 :: Noun -> Noun -> Noun -> Noun -> Noun -tar10 a _ c d = - Cell a - (Cell (Atom 8) - (Cell c - (Cell (Atom 7) - (Cell (Cell (Atom 0) (Atom 3)) - d)))) +import Nock.Language as X +import Nock.Eval as X -- test expressions ----------------------------------------------------------- @@ -185,66 +14,67 @@ tar10 a _ c d = test0 :: Expr test0 = Fas - (Cell (Atom 3) + (Noun (Cell (Atom 3) (Cell (Cell (Atom 4) (Atom 5)) - (Cell (Atom 6) (Cell (Atom 14) (Atom 15))))) + (Cell (Atom 6) (Cell (Atom 14) (Atom 15)))))) -- *[[[4 5] [6 14 15]] [0 7]] -- should be [14 15] test1 :: Expr test1 = Tar - (Cell + (Noun (Cell (Cell (Cell (Atom 4) (Atom 5)) (Cell (Atom 6) (Cell (Atom 14) (Atom 15)))) - (Cell (Atom 0) (Atom 7))) + (Cell (Atom 0) (Atom 7)))) -- *[42 [1 153 218]] -- should be [153 218] test2 :: Expr test2 = Tar - (Cell (Atom 42) - (Cell (Atom 1) (Cell (Atom 153) (Atom 218)))) + (Noun (Cell (Atom 42) + (Cell (Atom 1) (Cell (Atom 153) (Atom 218))))) -- *[57 [4 0 1]] -- should be 58 test3 :: Expr test3 = Tar - (Cell (Atom 57) + (Noun (Cell (Atom 57) (Cell (Atom 4) - (Cell (Atom 0) (Atom 1)))) + (Cell (Atom 0) (Atom 1))))) -- *[[132 19] [4 0 3]] -- should be 20 test4 :: Expr test4 = Tar - (Cell (Cell (Atom 132) (Atom 19)) + (Noun (Cell (Cell (Atom 132) (Atom 19)) (Cell (Atom 4) - (Cell (Atom 0) (Atom 3)))) + (Cell (Atom 0) (Atom 3))))) -- /[7 [[4 5] [6 14 15]]] -- should be [14 15] test5 :: Expr test5 = Fas - (Cell (Atom 7) + (Noun (Cell (Atom 7) (Cell (Cell (Atom 4) (Atom 5)) - (Cell (Atom 6) (Cell (Atom 14) (Atom 15))))) + (Cell (Atom 6) (Cell (Atom 14) (Atom 15)))))) -- *[77 [2 [1 42] [1 1 153 218]]] -- should be [153 218] test6 :: Expr test6 = Tar + (Noun (Cell (Atom 77) (Cell (Atom 2) (Cell (Cell (Atom 1) (Atom 42)) (Cell (Atom 1) (Cell (Atom 1) - (Cell (Atom 153) (Atom 218))))))) + (Cell (Atom 153) (Atom 218)))))))) main :: IO () main = do diff --git a/lib/Nock/Eval.hs b/lib/Nock/Eval.hs @@ -0,0 +1,152 @@ + +module Nock.Eval ( + nock + ) where + +import Nock.Language + +nock :: Expr -> Noun +nock expr = case expr of + Noun noun -> noun + Wut e -> wut (nock e) + Lus e -> lus (nock e) + Tis e -> tis (nock e) + Fas e -> fas (nock e) + Tar e -> tar (nock e) + +wut :: Noun -> Noun +wut noun = case noun of + Cell {} -> Atom 0 + Atom {} -> Atom 1 + +lus :: Noun -> Noun +lus noun = case noun of + Cell {} -> error "lus: bad noun" + Atom m -> Atom (1 + m) + +tis :: Noun -> Noun +tis noun = case noun of + Atom {} -> error "tis: bad noun" + Cell m n -> + if m == n + then Atom 0 + else Atom 1 + +fas :: Noun -> Noun +fas noun = case noun of + Atom {} -> error "fas: bad noun" + Cell m n -> case m of + Cell {} -> error "fas: bad noun" + Atom a -> case a of + + 1 -> n + + 2 -> case n of + Atom {} -> error "fas: bad noun" + Cell o _ -> o + + 3 -> case n of + Atom {} -> error "fas: bad noun" + Cell _ o -> o + + _ -> + if even a + then + let inner = Cell (Atom (a `div` 2)) n + in fas (Cell (Atom 2) (fas inner)) + else + let inner = Cell (Atom ((a - 1) `div` 2)) n + in fas (Cell (Atom 3) (fas inner)) + +tar :: Noun -> Noun +tar noun = case noun of + Atom {} -> error "tar: bad noun" + Cell a m -> case m of + Atom {} -> error "tar: bad noun" + Cell n d -> case n of + Cell b c -> Cell (tar (Cell a (Cell b c))) (tar (Cell a d)) + Atom z -> case z of + + 0 -> fas (Cell d a) + + 1 -> d + + 2 -> case d of + Atom {} -> error "tar: bad noun" + Cell e f -> + tar (Cell (tar (Cell a e)) (tar (Cell a f))) + + 3 -> wut (tar (Cell a d)) + + 4 -> lus (tar (Cell a d)) + + 5 -> tis (tar (Cell a d)) + + 6 -> case d of + Atom {} -> error "tar: bad noun" + Cell g h -> case h of + Atom {} -> error "tar: bad noun" + Cell i j -> tar (tar6 a g i j) + + 7 -> case d of + Atom {} -> error "tar: bad noun" + Cell g h -> + tar (Cell a (Cell (Atom 2) (Cell g (Cell (Atom 1) h)))) + + 8 -> case d of + Atom {} -> error "tar: bad noun" + Cell g h -> tar (tar8 a g h) + + 9 -> case d of + Atom {} -> error "tar: bad noun" + Cell g h -> tar (tar9 a g h) + + 10 -> case d of + Atom {} -> error "tar: bad noun" + Cell g h -> case g of + Cell i j -> tar (tar10 a i j h) + _ -> tar (Cell a h) + + _ -> error "tar: bad noun" + +tar6 :: Noun -> Noun -> Noun -> Noun -> Noun +tar6 a b c d = + Cell a + (Cell (Atom 2) + (Cell (Cell (Atom 0) (Atom 1)) + (Cell (Atom 2) + (Cell (Cell (Atom 1) (Cell c d)) + (Cell (Cell (Atom 1) (Atom 0)) + (Cell (Atom 2) + (Cell (Cell (Atom 1) (Cell (Atom 2) (Atom 3))) + (Cell (Cell (Atom 1) (Atom 0)) + (Cell (Atom 4) + (Cell (Atom 4) b)))))))))) + +tar8 :: Noun -> Noun -> Noun -> Noun +tar8 a b c = + Cell a + (Cell (Atom 7) + (Cell + (Cell (Atom 7) + (Cell (Cell (Atom 0) (Atom 1)) b)) + (Cell (Cell (Atom 0) (Atom 1)) c))) + +tar9 :: Noun -> Noun -> Noun -> Noun +tar9 a b c = + Cell a + (Cell (Atom 7) + (Cell c + (Cell (Atom 2) + (Cell (Cell (Atom 0) (Atom 1)) + (Cell (Atom 0) b))))) + +tar10 :: Noun -> Noun -> Noun -> Noun -> Noun +tar10 a _ c d = + Cell a + (Cell (Atom 8) + (Cell c + (Cell (Atom 7) + (Cell (Cell (Atom 0) (Atom 3)) + d)))) + diff --git a/lib/Nock/Language.hs b/lib/Nock/Language.hs @@ -0,0 +1,34 @@ + +module Nock.Language ( + Noun(..) + , Expr(..) + ) where + +data Noun = + Atom !Int + | Cell !Noun !Noun + deriving Eq + +instance Show Noun where + show noun = case noun of + Atom m -> show m + Cell m n -> mconcat ["[", show m, " ", show n, "]"] + +data Expr = + Noun !Noun + | Wut !Expr + | Lus !Expr + | Tis !Expr + | Fas !Expr + | Tar !Expr + deriving Eq + +instance Show Expr where + show op = case op of + Noun n -> show n + Wut n -> mconcat ["?", show n] + Lus n -> mconcat ["+", show n] + Tis n -> mconcat ["=", show n] + Fas n -> mconcat ["/", show n] + Tar n -> mconcat ["*", show n] +