diff options
author | Marvin Borner | 2022-08-07 00:06:20 +0200 |
---|---|---|
committer | Marvin Borner | 2022-08-07 00:08:17 +0200 |
commit | d2a5d69f42d74e8382ca29c8c166eba3a79d20d5 (patch) | |
tree | 01e3fa75173e99dc78b516050079acb1d1b11a0d | |
parent | 4ec1d9312839bf73ad80a4555e5c53e0b388c86a (diff) |
Progress
As always - very descriptive. I've been busy with exams but from now
on I'll be working on bruijn again.
-rw-r--r-- | benchmark.bruijn | 21 | ||||
-rw-r--r-- | src/Eval.hs | 218 | ||||
-rw-r--r-- | src/Helper.hs | 13 | ||||
-rw-r--r-- | src/Parser.hs | 41 | ||||
-rw-r--r-- | std/Combinator.bruijn | 17 | ||||
-rw-r--r-- | std/Number.bruijn | 116 | ||||
-rw-r--r-- | std/Pair.bruijn | 10 |
7 files changed, 266 insertions, 170 deletions
diff --git a/benchmark.bruijn b/benchmark.bruijn index e11668f..e9e539c 100644 --- a/benchmark.bruijn +++ b/benchmark.bruijn @@ -28,4 +28,23 @@ n37 succ (mul n6 n6) n703 sumto n37 n720 fac n6 -main eqnat n720 (add n703 n17) = true +# this can take some time.. +# - should return true +:print eqnat n720 (add n703 n17) + +# ========= +# Ackermann +# From AIT +# ========= + +two [[1 (1 0)]] +omega [0 0] +ackify [[0 1 0]] +ackerlike [0 ackify omega 0] + +# this can take a VERY long while +# maybe even too long for benchmarking +# - should return exponential tower with 256 levels +# :print ackerlike two + +main [0] diff --git a/src/Eval.hs b/src/Eval.hs index e0ad17a..03d5bd5 100644 --- a/src/Eval.hs +++ b/src/Eval.hs @@ -45,28 +45,25 @@ loadFile :: String -> IO EnvState loadFile path = do file <- try $ readFile path :: IO (Either IOError String) case file of - Left exception -> print (exception :: IOError) >> pure (EnvState []) - Right file -> - eval (filter (not . null) $ split "\n\n" file) (EnvState []) False + Left exception -> + print (exception :: IOError) >> pure (EnvState $ Environment []) + Right file -> eval (filter (not . null) $ split "\n\n" file) + (EnvState $ Environment []) + False --- TODO: Add subdefs ([Program (Failable Expression)]) to State somehow -evalVar - :: String -> [Program (Failable Expression)] -> Program (Failable Expression) -evalVar var sub = state $ \e -> +evalVar :: String -> Environment -> Program (Failable Expression) +evalVar var (Environment sub) = state $ \env@(Environment e) -> let find name env = case lookup name env of Nothing -> Left $ UndeclaredFunction var Just x -> Right x - -- search in sub env - subs = map (\s -> let (res, env') = s `runState` e in find var env') sub - in case rights subs of - (head : rst) -> (Right head, e) - _ -> (find var e, e) -- search in global env + in case find var (map fst sub) of + s@(Right _) -> (s, env) + _ -> (find var (map fst e), env) -- search in global env -evalApp - :: Expression - -> Expression - -> [Program (Failable Expression)] - -> Program (Failable Expression) +evalAbs :: Expression -> Environment -> Program (Failable Expression) +evalAbs exp sub = evalExp exp sub >>= pure . fmap Abstraction + +evalApp :: Expression -> Expression -> Environment -> Program (Failable Expression) evalApp f g sub = evalExp f sub >>= (\case @@ -74,32 +71,99 @@ evalApp f g sub = Right f' -> fmap (Application f') <$> evalExp g sub ) -evalExp - :: Expression - -> [Program (Failable Expression)] - -> Program (Failable Expression) -evalExp idx@(Bruijn _ ) _ = pure $ Right idx -evalExp ( Variable var) sub = evalVar var sub -evalExp ( Abstraction exp) sub = evalExp exp sub >>= pure . fmap Abstraction -evalExp ( Application f g) sub = evalApp f g sub +evalExp :: Expression -> Environment -> Program (Failable Expression) +evalExp idx@(Bruijn _ ) = const $ pure $ Right idx +evalExp ( Variable var) = evalVar var +evalExp ( Abstraction exp) = evalAbs exp +evalExp ( Application f g) = evalApp f g -evalDefine :: String -> Expression -> [EnvDef] -> Program (Failable Expression) +evalDefine + :: String -> Expression -> Environment -> Program (Failable Expression) evalDefine name exp sub = - let sub' = fmap (\(name, exp) -> evalDefine name exp []) sub - in evalExp exp sub' - >>= (\case - Left e -> pure $ Left e - Right f -> modify ((name, f) :) >> pure (Right f) - ) + evalExp exp sub + >>= (\case + Left e -> pure $ Left e + Right f -> + modify (\(Environment s) -> Environment $ ((name, f), Environment []) : s) + >> pure (Right f) + ) -evalTest :: Expression -> Expression -> Program (Failable Instruction) -evalTest exp1 exp2 = - evalExp exp1 [] +evalTest :: Expression -> Expression -> Environment -> Program (Failable Instruction) +evalTest exp1 exp2 sub = + evalExp exp1 sub >>= (\case Left exp1 -> pure $ Left exp1 - Right exp1 -> fmap (Test exp1) <$> evalExp exp2 [] + Right exp1 -> fmap (Test exp1) <$> evalExp exp2 sub ) +evalSubEnv :: [Instruction] -> EnvState -> Bool -> IO EnvState +evalSubEnv [] state _ = return state +evalSubEnv (instr : is) state@(EnvState env) isRepl = + handleInterrupt (putStrLn "<aborted>" >> return state) + $ evalInstruction instr state (evalSubEnv is) isRepl + +evalInstruction + :: Instruction + -> EnvState + -> (EnvState -> Bool -> IO EnvState) + -> Bool + -> IO EnvState +evalInstruction instr state@(EnvState env) rec isRepl = case instr of + Define name exp sub -> do + EnvState subEnv <- evalSubEnv sub state isRepl + let + (res, env') = evalDefine name exp subEnv `runState` env + in case res of + Left err -> print err >> rec (EnvState env') isRepl + Right _ -> if isRepl + then (putStrLn $ name <> " = " <> show exp) + >> return (EnvState env') + else rec (EnvState env') isRepl + -- TODO: Import loop detection + -- TODO: Don't import subimports into main env + Import path namespace -> do + lib <- getDataFileName path -- TODO: Use actual lib directory + exists <- doesFileExist lib + EnvState env' <- loadFile $ if exists then lib else path + let prefix | null namespace = takeBaseName path ++ "." + | namespace == "." = "" + | otherwise = namespace ++ "." + env' <- pure $ Environment $ map (\((n, e), s) -> ((prefix ++ n, e), s)) + ((\(Environment e) -> e) env') -- TODO: Improve + rec (EnvState $ env <> env') False -- import => isRepl = False + Evaluate exp -> + let (res, env') = evalExp exp (Environment []) `runState` env + in putStrLn + (case res of + Left err -> show err + Right exp -> + "<> " + <> (show exp) + <> "\n*> " + <> (show reduced) + <> (if likeTernary reduced + then "\t(" <> (show $ ternaryToDecimal reduced) <> ")" + else "" + ) + where reduced = reduce exp + ) + >> rec state isRepl + Test exp1 exp2 -> + let (res, _) = evalTest exp1 exp2 (Environment []) `runState` env + in case res of + Left err -> print err >> pure state + Right (Test exp1' exp2') -> + when + (reduce exp1' /= reduce exp2') + ( putStrLn + $ "ERROR: test failed: " + <> (show exp1) + <> " != " + <> (show exp2) + ) + >> rec state isRepl + _ -> rec state isRepl + eval :: [String] -> EnvState -> Bool -> IO EnvState eval [] state _ = return state eval [""] state _ = return state @@ -107,72 +171,17 @@ eval (block : bs) state@(EnvState env) isRepl = handleInterrupt (putStrLn "<aborted>" >> return state) $ case parse blockParser "" block of Left err -> putStrLn (errorBundlePretty err) >> eval bs state isRepl - Right instr -> case instr of - Define name exp sub -> - let subenv = [ (name, exp) | (Define name exp _) <- sub ] - (res, env') = evalDefine name exp subenv `runState` env - in case res of - Left err -> - putStrLn (show err) >> eval bs (EnvState env') isRepl - Right _ -> if isRepl - then (putStrLn $ name <> " = " <> show exp) - >> return (EnvState env') - else eval bs (EnvState env') isRepl - -- TODO: Import loop detection - -- TODO: Don't import subimports into main env - Import path namespace -> do - lib <- getDataFileName path -- TODO: Use actual lib directory - exists <- doesFileExist lib - EnvState env' <- loadFile $ if exists then lib else path - let prefix | null namespace = takeBaseName path ++ "." - | namespace == "." = "" - | otherwise = namespace ++ "." - env' <- pure $ map (\(n, e) -> (prefix ++ n, e)) env' - eval bs (EnvState $ env <> env') False -- import => isRepl = False - Evaluate exp -> - let (res, env') = evalExp exp [] `runState` env - in - putStrLn - (case res of - Left err -> show err - Right exp -> - "<> " - <> (show exp) - <> "\n*> " - <> (show reduced) - <> (if likeTernary reduced - then - "\t(" <> (show $ ternaryToDecimal reduced) <> ")" - else "" - ) - where reduced = reduce exp - ) - >> eval bs state isRepl - Test exp1 exp2 -> - let (res, _) = evalTest exp1 exp2 `runState` env - in case res of - Left err -> putStrLn (show err) >> pure state - Right (Test exp1' exp2') -> - when - (reduce exp1' /= reduce exp2') - ( putStrLn - $ "ERROR: test failed: " - <> (show exp1) - <> " != " - <> (show exp2) - ) - >> eval bs state isRepl - _ -> eval bs state isRepl + Right instr -> evalInstruction instr state (eval bs) isRepl where blockParser = if isRepl then parseReplLine else parseBlock 0 evalFunc :: String -> Environment -> Maybe Expression -evalFunc func env = do - exp <- lookup func env +evalFunc func (Environment env) = do + exp <- lookup func (map fst env) pure $ reduce exp evalMainFunc :: Environment -> Expression -> Maybe Expression -evalMainFunc env arg = do - exp <- lookup "main" env +evalMainFunc (Environment env) arg = do + exp <- lookup "main" (map fst env) pure $ reduce $ Application exp arg evalFile :: String -> (a -> IO ()) -> (Expression -> a) -> IO () @@ -180,7 +189,7 @@ evalFile path write conv = do EnvState env <- loadFile path arg <- encodeStdin case evalMainFunc env arg of - Nothing -> putStrLn $ "ERROR: main function not found" + Nothing -> putStrLn "ERROR: main function not found" Just exp -> write $ conv exp exec :: String -> (String -> IO (Either IOError a)) -> (a -> String) -> IO () @@ -205,9 +214,9 @@ repl state = lookupCompletion :: String -> M [Completion] lookupCompletion str = do - (EnvState env) <- StrictState.get - return $ map (\(s, _) -> Completion s s False) $ filter - (\(s, _) -> str `isPrefixOf` s) + (EnvState (Environment env)) <- StrictState.get + return $ map (\((s, _), _) -> Completion s s False) $ filter + (\((s, _), _) -> str `isPrefixOf` s) env completionSettings :: String -> Settings M @@ -222,10 +231,11 @@ runRepl = do config <- getDataFileName "config" history <- getDataFileName "history" prefs <- readPrefs config - let looper = runInputTWithPrefs prefs - (completionSettings history) - (withInterrupt $ repl $ EnvState []) - code <- StrictState.evalStateT looper (EnvState []) + let looper = runInputTWithPrefs + prefs + (completionSettings history) + (withInterrupt $ repl $ EnvState $ Environment []) + code <- StrictState.evalStateT looper (EnvState $ Environment []) return code usage :: IO () diff --git a/src/Helper.hs b/src/Helper.hs index 33c0855..e1b3819 100644 --- a/src/Helper.hs +++ b/src/Helper.hs @@ -3,6 +3,7 @@ module Helper where import Control.Monad.State import qualified Data.BitString as Bit import qualified Data.ByteString as Byte +import Data.List data Error = UndeclaredFunction String | DuplicateFunction String | InvalidIndex Int | FatalError String instance Show Error where @@ -14,7 +15,7 @@ type Failable = Either Error data Expression = Bruijn Int | Variable String | Abstraction Expression | Application Expression Expression deriving (Ord, Eq) -data Instruction = Define String Expression [Instruction] | Evaluate Expression | Comment String | Import String String | Test Expression Expression +data Instruction = Define String Expression [Instruction] | Evaluate Expression | Comment | Import String String | Test Expression Expression deriving (Show) instance Show Expression where show (Bruijn x ) = "\ESC[31m" <> show x <> "\ESC[0m" @@ -24,9 +25,17 @@ instance Show Expression where "\ESC[33m(\ESC[0m" <> show exp1 <> " " <> show exp2 <> "\ESC[33m)\ESC[0m" type EnvDef = (String, Expression) -type Environment = [EnvDef] +data Environment = Environment [(EnvDef, Environment)] type Program = State Environment +instance Semigroup Environment where + (Environment e1) <> (Environment e2) = Environment $ e1 <> e2 + +instance Show Environment where + show (Environment env) = intercalate "\n" $ map + (\((n, f), s) -> "\t" <> show n <> ": " <> show f <> " - " <> show s) + env + --- listify :: [Expression] -> Expression diff --git a/src/Parser.hs b/src/Parser.hs index 6fbfc10..54a5a62 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -58,10 +58,6 @@ namespace = parens :: Parser a -> Parser a parens = between (symbol "(") (symbol ")") -almostAnything :: Parser String -almostAnything = - some $ oneOf ".`#~@$%^&*_+-=|;',/?[]<>(){} " <|> letterChar <|> digitChar - importPath :: Parser String importPath = some $ oneOf "./_+-" <|> letterChar <|> digitChar @@ -127,8 +123,7 @@ parseDefine lvl = do exp <- parseExpression -- TODO: Fix >1 sub-defs subs <- - (try $ newline *> (sepEndBy (parseBlock (lvl + 1)) newline)) - <|> (try eof >> return []) + (try $ newline *> (many (parseBlock (lvl + 1)))) <|> (try eof >> return []) pure $ Define var exp subs parseReplDefine :: Parser Instruction @@ -140,8 +135,11 @@ parseReplDefine = do exp <- parseExpression pure $ Define var exp [] -parseComment :: Parser Instruction -parseComment = string "#" >> Comment <$> almostAnything <?> "comment" +parseComment :: Parser () +parseComment = do + string "# " <?> "comment" + some $ noneOf "\r\n" + return () parseImport :: Parser Instruction parseImport = do @@ -171,20 +169,29 @@ parseTest = do exp2 <- parseExpression pure $ Test exp1 exp2 --- TODO: Add comment/test [Instruction] parser and combine with (this) def block +parseCommentBlock :: Parser Instruction +parseCommentBlock = do + sepEndBy1 parseComment newline + eof + return Comment + +-- TODO: Add comment/test [Instruction] parser and combine with (this) def block? +parseDefBlock :: Int -> Parser Instruction +parseDefBlock lvl = + (sepEndBy parseComment newline) + *> string (replicate lvl '\t') + *> ( try (parseDefine lvl) + <|> try parsePrint + <|> try parseImport + <|> try parseTest + ) + parseBlock :: Int -> Parser Instruction -parseBlock lvl = - string (replicate lvl '\t') - *> try (parseDefine lvl) - <|> try parseComment - <|> try parsePrint - <|> try parseImport - <|> try parseTest +parseBlock lvl = try parseCommentBlock <|> parseDefBlock lvl parseReplLine :: Parser Instruction parseReplLine = try parseReplDefine - <|> try parseComment <|> try parseEvaluate <|> try parseImport <|> try parseTest diff --git a/std/Combinator.bruijn b/std/Combinator.bruijn index 95338a6..bedc1e9 100644 --- a/std/Combinator.bruijn +++ b/std/Combinator.bruijn @@ -1,22 +1,39 @@ # MIT License, Copyright (c) 2022 Marvin Borner S [[[2 0 (1 0)]]] + K [[1]] + I [0] + B [[[2 (1 0)]]] + C [[[2 0 1]]] + W [[1 0 0]] + T [[1]] + F [[0]] + ω [0 0] + Ω ω ω + Y [[1 (0 0)] [1 (0 0)]] + Θ [[0 (1 1 0)]] [[0 (1 1 0)]] + i [0 S K] :test I = i i + :test K = i (i (i i)) + :test S = i (i (i (i i))) + :test B = S (K S) K + :test C = S (S (K (S (K S) K)) S) (K K) + :test W = S S (S K) diff --git a/std/Number.bruijn b/std/Number.bruijn index 58a0da9..efd6d2d 100644 --- a/std/Number.bruijn +++ b/std/Number.bruijn @@ -2,51 +2,64 @@ # According to works of T.Æ. Mogensen :import std/Combinator . + :import std/Pair . # checks whether balanced ternary number is zero zero? [0 T [F] [F] I] + :test zero? +0 = T :test zero? -1 = F :test zero? +1 = F :test zero? +42 = F +# negative trit indicating coeffecient of -1 trit-neg [[[2]]] + +# positive trit indicating coeffecient of +1 trit-pos [[[1]]] + +# zero trit indicating coeffecient of 0 trit-zero [[[0]]] # shifts a negative trit into a balanced ternary number up-neg [[[[[2 (4 3 2 1 0)]]]]] + :test up-neg +0 = -1 :test up-neg -1 = -4 :test up-neg +42 = +125 # shifts a positive trit into a balanced ternary number up-pos [[[[[1 (4 3 2 1 0)]]]]] + :test up-pos +0 = +1 :test up-pos -1 = -2 :test up-pos +42 = +127 # shifts a zero trit into a balanced ternary number up-zero [[[[[0 (4 3 2 1 0)]]]]] + :test up-zero +0 = [[[[0 3]]]] :test up-zero +1 = +3 :test up-zero +42 = +126 # shifts a specified trit into a balanced ternary number up [[[[[[5 2 1 0 (4 3 2 1 0)]]]]]] + :test up trit-neg +42 = up-neg +42 :test up trit-pos +42 = up-pos +42 :test up trit-zero +42 = up-zero +42 # negates a balanced ternary number negate [[[[[4 3 1 2 0]]]]] + :test negate +0 = +0 :test negate -1 = +1 :test negate +42 = -42 # extracts least significant trit from balanced ternary numbers lst [0 trit-zero [trit-neg] [trit-pos] [trit-zero]] + :test lst +0 = trit-zero :test lst -1 = trit-neg :test lst +1 = trit-pos @@ -54,30 +67,33 @@ lst [0 trit-zero [trit-neg] [trit-pos] [trit-zero]] # converts the normal balanced ternary representation into abstract # -> the abstract representation is used in add/sub/mul -_abs-neg [[[[[2 4]]]]] -_abs-pos [[[[[1 4]]]]] -_abs-zero [[[[[0 4]]]]] -abstractify [0 [[[[3]]]] _abs-neg _abs-pos _abs-zero] +abstractify [0 [[[[3]]]] abs-neg abs-pos abs-zero] + abs-neg [[[[[2 4]]]]] + abs-pos [[[[[1 4]]]]] + abs-zero [[[[[0 4]]]]] + :test abstractify -3 = [[[[0 [[[[2 [[[[3]]]]]]]]]]]] :test abstractify +0 = [[[[3]]]] :test abstractify +3 = [[[[0 [[[[1 [[[[3]]]]]]]]]]]] # converts the abstracted balanced ternary representation back to normal # using Y/ω to solve recursion -_normalize [[0 +0 [up-neg ([3 3 0] 0)] [up-pos ([3 3 0] 0)] [up-zero ([3 3 0] 0)]]] -normalize ω _normalize +normalize ω normalize' + normalize' [[0 +0 [up-neg ([3 3 0] 0)] [up-pos ([3 3 0] 0)] [up-zero ([3 3 0] 0)]]] + :test normalize [[[[3]]]] = +0 :test normalize (abstractify +42) = +42 :test normalize (abstractify -42) = -42 # checks whether two balanced ternary numbers are equal # -> removes leading 0s! -_eq-z [zero? (normalize 0)] -_eq-neg [[0 F [2 0] [F] [F]]] -_eq-pos [[0 F [F] [2 0] [F]]] -_eq-zero [[0 (1 0) [F] [F] [2 0]]] -_eq-abs [0 _eq-z _eq-neg _eq-pos _eq-zero] -eq? [[_eq-abs 1 (abstractify 0)]] +eq? [[eq-abs 1 (abstractify 0)]] + eq-z [zero? (normalize 0)] + eq-neg [[0 F [2 0] [F] [F]]] + eq-pos [[0 F [F] [2 0] [F]]] + eq-zero [[0 (1 0) [F] [F] [2 0]]] + eq-abs [0 eq-z eq-neg eq-pos eq-zero] + :test eq? -42 -42 = T :test eq? -1 -1 = T :test eq? -1 +0 = F @@ -88,27 +104,29 @@ eq? [[_eq-abs 1 (abstractify 0)]] :test eq? [[[[(1 (0 (0 (0 (0 3)))))]]]] +1 = T # strips leading 0s from balanced ternary number -_strip-z pair +0 T -_strip-neg [0 [[pair (up-neg 1) F]]] -_strip-pos [0 [[pair (up-pos 1) F]]] -_strip-zero [0 [[pair (0 +0 (up-zero 1)) 0]]] -strip [fst (0 _strip-z _strip-neg _strip-pos _strip-zero)] +strip [fst (0 strip-z strip-neg strip-pos strip-zero)] + strip-z pair +0 T + strip-neg [0 [[pair (up-neg 1) F]]] + strip-pos [0 [[pair (up-pos 1) F]]] + strip-zero [0 [[pair (0 +0 (up-zero 1)) 0]]] + :test strip [[[[0 3]]]] = +0 :test strip [[[[2 (0 (0 (0 (0 3))))]]]] = -1 :test strip +42 = +42 -# I believe Mogensen's Paper has an error in its succ/pred definitions. -# They use 3 abstractions in the _inc* functions, also we use switched +/0 +# I believe Mogensen's Paper has an error in its inc/dec definitions. +# They use 3 abstractions in the inc* functions, also we use switched +/0 # in comparison to their implementation, yet the order of neg/pos/zero is # the same. Something's weird. # adds +1 to a balanced ternary number (can introduce leading 0s) -_inc-z pair +0 +1 -_inc-neg [0 [[pair (up-neg 1) (up-zero 1)]]] -_inc-zero [0 [[pair (up-zero 1) (up-pos 1)]]] -_inc-pos [0 [[pair (up-pos 1) (up-neg 0)]]] -inc [snd (0 _inc-z _inc-neg _inc-pos _inc-zero)] +inc [snd (0 inc-z inc-neg inc-pos inc-zero)] + inc-z pair +0 +1 + inc-neg [0 [[pair (up-neg 1) (up-zero 1)]]] + inc-zero [0 [[pair (up-zero 1) (up-pos 1)]]] + inc-pos [0 [[pair (up-pos 1) (up-neg 0)]]] sinc [strip (inc 0)] + :test eq? (inc -42) -41 = T :test eq? (inc -1) +0 = T :test eq? (inc +0) +1 = T @@ -116,12 +134,13 @@ sinc [strip (inc 0)] :test eq? (inc +42) +43 = T # subs +1 from a balanced ternary number (can introduce leading 0s) -_dec-z pair +0 -1 -_dec-neg [0 [[pair (up-neg 1) (up-pos 0)]]] -_dec-zero [0 [[pair (up-zero 1) (up-neg 1)]]] -_dec-pos [0 [[pair (up-pos 1) (up-zero 1)]]] -dec [snd (0 _dec-z _dec-neg _dec-pos _dec-zero)] +dec [snd (0 dec-z dec-neg dec-pos dec-zero)] + dec-z pair +0 -1 + dec-neg [0 [[pair (up-neg 1) (up-pos 0)]]] + dec-zero [0 [[pair (up-zero 1) (up-neg 1)]]] + dec-pos [0 [[pair (up-pos 1) (up-zero 1)]]] sdec [strip (dec 0)] + :test dec -42 = -43 :test dec +0 = -1 :test sdec (dec (dec (dec (dec +5)))) = +0 @@ -129,19 +148,20 @@ sdec [strip (dec 0)] :test dec +42 = +41 # adds two balanced ternary numbers (can introduce leading 0s) -_add-c [[1 0 trit-zero]] -_add-b-neg2 [1 (up-zero (3 0 trit-neg)) (up-neg (3 0 trit-zero)) (up-pos (3 0 trit-neg))] -_add-b-neg [1 (up-pos (3 0 trit-neg)) (up-zero (3 0 trit-zero)) (up-neg (3 0 trit-zero))] -_add-b-zero [up 1 (3 0 trit-zero)] -_add-b-pos [1 (up-zero (3 0 trit-zero)) (up-neg (3 0 trit-pos)) (up-pos (3 0 trit-zero))] -_add-b-pos2 [1 (up-pos (3 0 trit-zero)) (up-zero (3 0 trit-pos)) (up-neg (3 0 trit-pos))] -_add-a-neg [[[1 (_add-b-neg 1) _add-b-neg2 _add-b-zero _add-b-neg]]] -_add-a-pos [[[1 (_add-b-pos 1) _add-b-zero _add-b-pos2 _add-b-pos]]] -_add-a-zero [[[1 (_add-b-zero 1) _add-b-neg _add-b-pos _add-b-zero]]] -_add-z [[0 (dec (normalize 1)) (inc (normalize 1)) (normalize 1)]] -_add-abs [_add-c (0 _add-z _add-a-neg _add-a-pos _add-a-zero)] -add [[_add-abs 1 (abstractify 0)]] -sadd [[strip (add 1 0)]] +add [[add-abs 1 (abstractify 0)]] + add-c [[1 0 trit-zero]] + add-b-neg2 [1 (up-zero (3 0 trit-neg)) (up-neg (3 0 trit-zero)) (up-pos (3 0 trit-neg))] + add-b-neg [1 (up-pos (3 0 trit-neg)) (up-zero (3 0 trit-zero)) (up-neg (3 0 trit-zero))] + add-b-zero [up 1 (3 0 trit-zero)] + add-b-pos [1 (up-zero (3 0 trit-zero)) (up-neg (3 0 trit-pos)) (up-pos (3 0 trit-zero))] + add-b-pos2 [1 (up-pos (3 0 trit-zero)) (up-zero (3 0 trit-pos)) (up-neg (3 0 trit-pos))] + add-a-neg [[[1 (add-b-neg 1) add-b-neg2 add-b-zero add-b-neg]]] + add-a-pos [[[1 (add-b-pos 1) add-b-zero add-b-pos2 add-b-pos]]] + add-a-zero [[[1 (add-b-zero 1) add-b-neg add-b-pos add-b-zero]]] + add-z [[0 (dec (normalize 1)) (inc (normalize 1)) (normalize 1)]] + add-abs [add-c (0 add-z add-a-neg add-a-pos add-a-zero)] +# sadd [[strip (add 1 0)]] + :test eq? (add -42 -1) -43 = T :test eq? (add -5 +6) +1 = T :test eq? (add -1 +0) -1 = T @@ -152,6 +172,7 @@ sadd [[strip (add 1 0)]] # subs two balanced ternary numbers (can introduce leading 0s) sub [[add 1 (negate 0)]] ssub [[strip (sub 1 0)]] + :test eq? (sub -42 -1) -41 = T :test eq? (sub -5 +6) -11 = T :test eq? (sub -1 +0) -1 = T @@ -160,12 +181,15 @@ ssub [[strip (sub 1 0)]] :test eq? (sub +42 +1) +41 = T # muls two balanced ternary numbers (can introduce leading 0s) -_mul-neg [sub (up-zero 0) 1] -_mul-pos [add (up-zero 0) 1] -_mul-zero [up-zero 0] -mul [[1 +0 _mul-neg _mul-pos _mul-zero]] +mul [[1 +0 mul-neg mul-pos mul-zero]] + mul-neg [sub (up-zero 0) 1] + mul-pos [add (up-zero 0) 1] + mul-zero [up-zero 0] smul [[strip (mul 1 0)]] + :test eq? (mul +42 +0) +0 = T :test eq? (mul -1 +42) -42 = T :test eq? (mul +3 +11) +33 = T :test eq? (mul +42 -4) -168 = T + +main [inc +1] diff --git a/std/Pair.bruijn b/std/Pair.bruijn index 75d8680..38046c8 100644 --- a/std/Pair.bruijn +++ b/std/Pair.bruijn @@ -7,20 +7,30 @@ pair [[[0 2 1]]] # extracts first expression from pair fst [0 T] + +# test fst with example pair of [[0]] and [[1]] :test fst (pair [[0]] [[1]]) = [[0]] # extracts second expression from pair snd [0 F] + +# test snd with example pair of [[0]] and [[1]] :test snd (pair [[0]] [[1]]) = [[1]] # applies both elements of a pair to a function uncurry [[1 (fst 0) (snd 0)]] + +# test uncurry with example pair of [[0]] and [[1]] and some combinator :test uncurry W (pair [[0]] [[1]]) = [[1]] # applies a function to the pair of two values curry [[[2 (pair 1 0)]]] + +# test curry with example pair of [[0]] and [[1]] and fst :test curry fst [[0]] [[1]] = [[0]] # swaps the values of a pair swap [pair (snd 0) (fst 0)] + +# test swap with example pair of [[0]] and [[1]] :test swap (pair [[0]] [[1]]) = pair [[1]] [[0]] |