diff options
author | Marvin Borner | 2022-08-12 15:26:03 +0200 |
---|---|---|
committer | Marvin Borner | 2022-08-12 15:26:03 +0200 |
commit | cce495b3b4440997274ecab3d72ed61d6a50b007 (patch) | |
tree | cc56c7af514dd6ca31edb5360a6682ac5439af01 | |
parent | b3cf49974e8af4e35ffc01fbe2f8e181d38de03a (diff) |
Added infix operator support
This isn't compatible with the :test .. = .. syntax, therefore I removed
it. They also don't have custom precedence/associativity support and
aren't chainable right now.
-rw-r--r-- | README.md | 22 | ||||
-rw-r--r-- | src/Eval.hs | 4 | ||||
-rw-r--r-- | src/Helper.hs | 4 | ||||
-rw-r--r-- | src/Parser.hs | 28 | ||||
-rw-r--r-- | src/Reducer.hs | 11 | ||||
-rw-r--r-- | std/Combinator.bruijn | 12 | ||||
-rw-r--r-- | std/List.bruijn | 54 | ||||
-rw-r--r-- | std/Logic.bruijn | 73 | ||||
-rw-r--r-- | std/Number.bruijn | 184 | ||||
-rw-r--r-- | std/Option.bruijn | 24 | ||||
-rw-r--r-- | std/Pair.bruijn | 10 | ||||
-rw-r--r-- | std/Result.bruijn | 36 |
12 files changed, 244 insertions, 218 deletions
@@ -65,7 +65,7 @@ form](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form). <singleton> ::= <bruijn> | <numeral> | <abstraction> | "(" <application> ")" | [namespace.]<identifier> <application> ::= <singleton> <singleton> <expression> ::= <application> | <singleton> - <test> ::= ":test " <expression> = <expression> + <test> ::= ":test " "(" <expression> ") (" <expression> ")" <import> ::= ":import " <path> [namespace] <comment> ::= "# " <letter>* @@ -122,19 +122,19 @@ Plain execution without any predefined functions: # we can use the function in all functions below its definition get-one2 get-one - :test get-one2 = +1 + :test (get-one2) (+1) # equivalent of λx.x id [0] # equivalent of (λx.x) (λx.λy.x) = λx.λy.x - :test id [[1]] = [[1]] + :test (id [[1]]) ([[1]]) # multiple arguments set-of-three [[[[0 1 2 3]]]] number-set set-of-three +1 +2 +3 access-first [0 [[[0]]]] - :test access-first number-set = +1 + :test (access-first number-set) (+1) # endless loop using omega combinator om [0 0] @@ -157,23 +157,23 @@ Using standard library: me [[[1]]] you [[[2]]] love pair me you - :test fst love = me - :test snd love = you + :test (fst love) (me) + :test (snd love) (you) # options - :test map inc (some +1) = some +2 - :test apply (some +1) [some (inc 0)] = some +2 + :test (map inc (some +1)) (some +2) + :test (apply (some +1) [some (inc 0)]) (some +2) # numerical operations five dec (sub (add +8 -4) -2) not-five? [if (eq? 0 +5) F T] - :test not-five? five = F + :test (not-five? five) (F) - :test eq? (uncurry mul (pair +3 +2)) = +6 + :test (eq? (uncurry mul (pair +3 +2))) (+6) # boolean main not (or (and F T) T) - :test main = F + :test (main) (F) # read the files in std/ for an overview of all functions/libraries diff --git a/src/Eval.hs b/src/Eval.hs index 65db990..6b165b2 100644 --- a/src/Eval.hs +++ b/src/Eval.hs @@ -66,11 +66,15 @@ evalApp f g sub = Right f' -> fmap (Application f') <$> evalExp g sub ) +evalInfix :: Expression -> String -> Expression -> Environment -> Program (Failable Expression) +evalInfix le i re = evalExp $ Application (Application (Variable i) le) re + evalExp :: Expression -> Environment -> Program (Failable Expression) evalExp idx@(Bruijn _ ) = const $ pure $ Right idx evalExp ( Variable var) = evalVar var evalExp ( Abstraction e) = evalAbs e evalExp ( Application f g) = evalApp f g +evalExp (Infix le i re) = evalInfix le i re evalDefine :: String -> Expression -> Environment -> Program (Failable Expression) diff --git a/src/Helper.hs b/src/Helper.hs index 6626598..66fe265 100644 --- a/src/Helper.hs +++ b/src/Helper.hs @@ -89,7 +89,7 @@ printBundle ParseErrorBundle {..} = <> pointer <> "\n" -data Expression = Bruijn Int | Variable String | Abstraction Expression | Application Expression Expression +data Expression = Bruijn Int | Variable String | Abstraction Expression | Application Expression Expression | Infix Expression String Expression deriving (Ord, Eq) data Instruction = Define String Expression [Instruction] | Evaluate Expression | Comment | Import String String | Test Expression Expression | ContextualInstruction Instruction String deriving (Show) @@ -99,6 +99,8 @@ instance Show Expression where show (Abstraction e ) = "\ESC[36m[\ESC[0m" <> show e <> "\ESC[36m]\ESC[0m" show (Application exp1 exp2) = "\ESC[33m(\ESC[0m" <> show exp1 <> " " <> show exp2 <> "\ESC[33m)\ESC[0m" + show (Infix le i re) = + show le <> "\ESC[95m(" <> i <> ")" <> "\ESC[0m" <> show re type EnvDef = (String, Expression) -- TODO: Add EvalConf to EnvState? diff --git a/src/Parser.hs b/src/Parser.hs index 4237db7..ddf09fb 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -17,14 +17,14 @@ type Parser = Parsec Void String sc :: Parser () sc = void $ char ' ' --- zero or more spaces --- scs :: Parser () --- scs = void $ takeWhileP (Just "white space") (== ' ') +infixOperator :: Parser String +infixOperator = some $ oneOf "!?*@+$%^&<>/|=" -- def identifier disallows the import prefix dots defIdentifier :: Parser String defIdentifier = ((:) <$> (letterChar <|> char '_') <*> many (alphaNumChar <|> oneOf "?!'_-")) + <|> parens infixOperator <?> "defining identifier" -- TODO: write as extension to defIdentifier @@ -53,7 +53,7 @@ parseAbstraction = do -- one or more singletons wrapped in coupled application parseApplication :: Parser Expression parseApplication = do - s <- sepEndBy1 parseSingleton sc -- TODO: Fix consuming space at end (re. test =) + s <- sepEndBy1 parseSingleton sc pure $ foldl1 Application s parseBruijn :: Parser Expression @@ -95,19 +95,29 @@ parseVariable = do var <- identifier pure $ Variable var +parseInfix :: Parser Expression +parseInfix = do + e1 <- parseSingleton + sc + i <- infixOperator + sc + e2 <- parseSingleton + pure $ Infix e1 i e2 + parseSingleton :: Parser Expression parseSingleton = parseBruijn - <|> parseNumeral + <|> try parseNumeral <|> parseString <|> parseChar <|> parseAbstraction + <|> try (parens parseInfix <?> "enclosed infix expr") <|> (parens parseApplication <?> "enclosed application") <|> parseVariable parseExpression :: Parser Expression parseExpression = do - e <- parseApplication + e <- try parseInfix <|> parseApplication pure e <?> "expression" parseEvaluate :: Parser Instruction @@ -160,9 +170,9 @@ parseTest :: Parser Instruction parseTest = do inp <- getInput _ <- string ":test " <?> "test" - e1 <- parseExpression - _ <- string "= " -- TODO: Disallow missing space (non-trivial) - e2 <- parseExpression + e1 <- (parens parseExpression <?> "first expression") + sc + e2 <- (parens parseExpression <?> "second expression") pure $ ContextualInstruction (Test e1 e2) inp parseCommentBlock :: Parser Instruction diff --git a/src/Reducer.hs b/src/Reducer.hs index a0edc25..87d8859 100644 --- a/src/Reducer.hs +++ b/src/Reducer.hs @@ -35,11 +35,12 @@ step (Abstraction e) = Abstraction (step e) step _ = error "invalid" reduceable :: Expression -> Bool -reduceable (Bruijn _ ) = False -reduceable (Variable _ ) = True -reduceable (Application (Abstraction _) _ ) = True -reduceable (Application e1 e2) = reduceable e1 || reduceable e2 -reduceable (Abstraction e ) = reduceable e +reduceable (Bruijn _) = False +reduceable (Variable _) = True +reduceable (Application (Abstraction _) _) = True +reduceable (Application e1 e2) = reduceable e1 || reduceable e2 +reduceable (Abstraction e) = reduceable e +reduceable _ = error "invalid" -- alpha conversion is not needed with de bruijn indexing reduce :: Expression -> Expression diff --git a/std/Combinator.bruijn b/std/Combinator.bruijn index 2a6bb29..1606403 100644 --- a/std/Combinator.bruijn +++ b/std/Combinator.bruijn @@ -28,14 +28,14 @@ Z [[1 [1 1 0]] [1 [1 1 0]]] i [0 S K] -:test I = i i +:test (I) (i i) -:test K = i (i (i i)) +:test (K) (i (i (i i))) -:test S = i (i (i (i i))) +:test (S) (i (i (i (i i)))) -:test B = S (K S) K +:test (B) (S (K S) K) -:test C = S (S (K (S (K S) K)) S) (K K) +:test (C) (S (S (K (S (K S) K)) S) (K K)) -:test W = S S (S K) +:test (W) (S S (S K)) diff --git a/std/List.bruijn b/std/List.bruijn index ac9b574..8f5f478 100644 --- a/std/List.bruijn +++ b/std/List.bruijn @@ -14,30 +14,30 @@ empty F # returns whether a list is empty empty? [0 [[[F]]] T] -:test empty? empty = T -:test empty? (cons +2 empty) = F +:test (empty? empty) (T) +:test (empty? (cons +2 empty)) (F) # appends an element to a list cons P.pair -:test cons +1 (cons +2 empty) = P.pair +1 (P.pair +2 empty) -:test cons 'a' (cons 'b' (cons 'c' empty)) = "abc" +:test (cons +1 (cons +2 empty)) (P.pair +1 (P.pair +2 empty)) +:test (cons 'a' (cons 'b' (cons 'c' empty))) ("abc") # returns the head of a list or empty head P.fst -:test head (cons +1 (cons +2 empty)) = +1 +:test (head (cons +1 (cons +2 empty))) (+1) # returns the tail of a list or empty tail P.snd -:test tail (cons +1 (cons +2 empty)) = cons +2 empty +:test (tail (cons +1 (cons +2 empty))) (cons +2 empty) # returns the length of a list in balanced ternary length Z [[[empty? 0 [2] [3 (N.inc 2) (tail 1)] I]]] +0 -:test length (cons +1 (cons +2 empty)) = +2 -:test length empty = +0 +:test (length (cons +1 (cons +2 empty))) (+2) +:test (length empty) (+0) # returns the element at index in list # TODO: fix for balanced ternary @@ -46,7 +46,7 @@ index [[head (1 tail 0)]] # reverses a list reverse Z [[[empty? 0 [2] [3 (cons (head 1) 2) (tail 1)] I]]] empty -:test reverse (cons +1 (cons +2 (cons +3 empty))) = cons +3 (cons +2 (cons +1 empty)) +:test (reverse (cons +1 (cons +2 (cons +3 empty)))) (cons +3 (cons +2 (cons +1 empty))) # creates list out of n terms # TODO: fix for balanced ternary @@ -55,73 +55,73 @@ list [0 [[[2 (cons 0 1)]]] reverse empty] # merges two lists merge Z [[[empty? 1 [1] [cons (head 2) (3 (tail 2) 1)] I]]] -:test merge (cons +1 (cons +2 (cons +3 empty))) (cons +4 empty) = cons +1 (cons +2 (cons +3 (cons +4 empty))) +:test (merge (cons +1 (cons +2 (cons +3 empty))) (cons +4 empty)) (cons +1 (cons +2 (cons +3 (cons +4 empty)))) # maps each element to a function map Z [[[empty? 0 [empty] [cons (2 (head 1)) (3 2 (tail 1))] I]]] -:test map N.inc (cons +1 (cons +2 (cons +3 empty))) = cons +2 (cons +3 (cons +4 empty)) +:test (map N.inc (cons +1 (cons +2 (cons +3 empty)))) (cons +2 (cons +3 (cons +4 empty))) # applies a left fold on a list foldl Z [[[[empty? 0 [2] [4 3 (3 2 (head 1)) (tail 1)] I]]]] -:test N.eq? (foldl N.add +0 (cons +1 (cons +2 (cons +3 empty)))) +6 = T -:test N.eq? (foldl N.sub +6 (cons +1 (cons +2 (cons +3 empty)))) +0 = T +:test (N.eq? (foldl N.add +0 (cons +1 (cons +2 (cons +3 empty)))) +6) (T) +:test (N.eq? (foldl N.sub +6 (cons +1 (cons +2 (cons +3 empty)))) +0) (T) # applies a right fold on a list foldr [[[Z [[empty? 0 [4] [5 (head 1) (2 (tail 1))] I]] 0]]] -:test N.eq? (foldr N.add +0 (cons +1 (cons +2 (cons +3 empty)))) +6 = T -:test N.eq? (foldr N.sub +2 (cons +1 (cons +2 (cons +3 empty)))) +0 = T +:test (N.eq? (foldr N.add +0 (cons +1 (cons +2 (cons +3 empty)))) +6) (T) +:test (N.eq? (foldr N.sub +2 (cons +1 (cons +2 (cons +3 empty)))) +0) (T) # filters a list based on a predicate filter Z [[[empty? 0 [empty] [2 (head 1) (cons (head 1)) I (3 2 (tail 1))] I]]] -:test filter N.zero? (cons +1 (cons +0 (cons +3 empty))) = cons +0 empty +:test (filter N.zero? (cons +1 (cons +0 (cons +3 empty)))) (cons +0 empty) # returns the last element of a list last Z [[empty? 0 [empty] [empty? (tail 1) (head 1) (2 (tail 1))] I]] -:test last (cons +1 (cons +2 (cons +3 empty))) = +3 +:test (last (cons +1 (cons +2 (cons +3 empty)))) (+3) # returns everything but the last element of a list init Z [[empty? 0 [empty] [empty? (tail 1) empty (cons (head 1) (2 (tail 1)))] I]] -:test init (cons +1 (cons +2 (cons +3 empty))) = cons +1 (cons +2 empty) +:test (init (cons +1 (cons +2 (cons +3 empty)))) (cons +1 (cons +2 empty)) # zips two lists discarding excess elements zip Z [[[empty? 1 [empty] [empty? 1 empty (cons (cons (head 2) (head 1)) (3 (tail 2) (tail 1)))] I]]] -:test zip (cons +1 (cons +2 empty)) (cons +2 (cons +1 empty)) = cons (P.pair +1 +2) (cons (P.pair +2 +1) empty) +:test (zip (cons +1 (cons +2 empty)) (cons +2 (cons +1 empty))) (cons (P.pair +1 +2) (cons (P.pair +2 +1) empty)) # applies pairs of the zipped list as arguments to a function zip-with Z [[[[empty? 1 [empty] [empty? 1 empty (cons (3 (head 2) (head 1)) (4 3 (tail 2) (tail 1)))] I]]]] -:test zip-with N.add (cons +1 (cons +2 empty)) (cons +2 (cons +1 empty)) = cons +3 (cons +3 empty) +:test (zip-with N.add (cons +1 (cons +2 empty)) (cons +2 (cons +1 empty))) (cons +3 (cons +3 empty)) # returns first n elements of a list take Z [[[empty? 0 [empty] [N.zero? 2 empty (cons (head 1) (3 (N.dec 2) (tail 1)))] I]]] -:test take +2 (cons +1 (cons +2 (cons +3 empty))) = cons +1 (cons +2 empty) +:test (take +2 (cons +1 (cons +2 (cons +3 empty)))) (cons +1 (cons +2 empty)) # takes elements while a predicate is satisfied take-while Z [[[empty? 0 [empty] [2 (head 1) (cons (head 1) (3 2 (tail 1))) empty] I]]] -:test take-while N.zero? (cons +0 (cons +0 (cons +1 empty))) = cons +0 (cons +0 empty) +:test (take-while N.zero? (cons +0 (cons +0 (cons +1 empty)))) (cons +0 (cons +0 empty)) # removes first n elements of a list drop Z [[[empty? 0 [empty] [N.zero? 2 1 (3 (N.dec 2) (tail 1))] I]]] -:test drop +2 (cons +1 (cons +2 (cons +3 empty))) = cons +3 empty +:test (drop +2 (cons +1 (cons +2 (cons +3 empty)))) (cons +3 empty) # removes elements while a predicate is satisfied drop-while Z [[[empty? 0 [empty] [2 (head 1) (3 2 (tail 1)) 1] I]]] -:test drop-while N.zero? (cons +0 (cons +0 (cons +1 empty))) = cons +1 empty +:test (drop-while N.zero? (cons +0 (cons +0 (cons +1 empty)))) (cons +1 empty) # returns a list with n-times a element repeat Z [[[N.zero? 1 [empty] [P.pair 1 (3 (N.dec 2) 1)] I]]] -:test repeat +5 +4 = (cons +4 (cons +4 (cons +4 (cons +4 (cons +4 empty))))) -:test repeat +1 +4 = (cons +4 empty) -:test repeat +0 +4 = empty +:test (repeat +5 +4) ((cons +4 (cons +4 (cons +4 (cons +4 (cons +4 empty)))))) +:test (repeat +1 +4) ((cons +4 empty)) +:test (repeat +0 +4) (empty) diff --git a/std/Logic.bruijn b/std/Logic.bruijn index 2e1e654..932a70f 100644 --- a/std/Logic.bruijn +++ b/std/Logic.bruijn @@ -4,67 +4,66 @@ not [0 F T] -:test not T = F -:test not F = T +:test (not T) (F) +:test (not F) (T) and [[1 0 F]] -:test and T T = T -:test and T F = F -:test and F T = F -:test and F F = F +:test (and T T) (T) +:test (and T F) (F) +:test (and F T) (F) +:test (and F F) (F) nand [[1 0 1 F T]] -:test nand T T = F -:test nand T F = T -:test nand F T = T -:test nand F F = T +:test (nand T T) (F) +:test (nand T F) (T) +:test (nand F T) (T) +:test (nand F F) (T) or [[1 T 0]] -:test or T T = T -:test or T F = T -:test or F T = T -:test or F F = F +:test (or T T) (T) +:test (or T F) (T) +:test (or F T) (T) +:test (or F F) (F) nor [[1 1 0 F T]] -:test nor T T = F -:test nor T F = F -:test nor F T = F -:test nor F F = T +:test (nor T T) (F) +:test (nor T F) (F) +:test (nor F T) (F) +:test (nor F F) (T) xor [[1 (not 0) 0]] -:test xor T T = F -:test xor T F = T -:test xor F T = T -:test xor F F = F +:test (xor T T) (F) +:test (xor T F) (T) +:test (xor F T) (T) +:test (xor F F) (F) xnor [[1 0 (not 0)]] -:test xnor T T = T -:test xnor T F = F -:test xnor F T = F -:test xnor F F = T +:test (xnor T T) (T) +:test (xnor T F) (F) +:test (xnor F T) (F) +:test (xnor F F) (T) if [[[2 1 0]]] -:test if T T F = T -:test if F T F = F +:test (if T T F) (T) +:test (if F T F) (F) implies [[or (not 1) 0]] -:test implies T T = T -:test implies T F = F -:test implies F T = T -:test implies F F = T +:test (implies T T) (T) +:test (implies T F) (F) +:test (implies F T) (T) +:test (implies F F) (T) iff [[and (implies 1 0) (implies 0 1)]] -:test iff T T = T -:test iff T F = F -:test iff F T = F -:test iff F F = T - +:test (iff T T) (T) +:test (iff T F) (F) +:test (iff F T) (F) +:test (iff F F) (T) diff --git a/std/Number.bruijn b/std/Number.bruijn index 2a4ca25..f603d88 100644 --- a/std/Number.bruijn +++ b/std/Number.bruijn @@ -25,43 +25,43 @@ trit-zero [[[0]]] # returns whether a trit is zero trit-zero? [0 F F T] -:test trit-neg? trit-neg = T -:test trit-neg? trit-pos = F -:test trit-neg? trit-zero = F -:test trit-pos? trit-neg = F -:test trit-pos? trit-pos = T -:test trit-pos? trit-zero = F -:test trit-zero? trit-neg = F -:test trit-zero? trit-pos = F -:test trit-zero? trit-zero = T +:test (trit-neg? trit-neg) (T) +:test (trit-neg? trit-pos) (F) +:test (trit-neg? trit-zero) (F) +:test (trit-pos? trit-neg) (F) +:test (trit-pos? trit-pos) (T) +:test (trit-pos? trit-zero) (F) +:test (trit-zero? trit-neg) (F) +:test (trit-zero? trit-pos) (F) +:test (trit-zero? trit-zero) (T) # 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 +: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 +: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 +: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 +:test (up trit-neg +42) (up-neg +42) +:test (up trit-pos +42) (up-pos +42) +:test (up trit-zero +42) (up-zero +42) # shifts the least significant trit out - basically div by 3 down [snd (0 z neg pos zero)] @@ -73,9 +73,9 @@ down [snd (0 z neg pos zero)] # negates a balanced ternary number negate [[[[[4 3 1 2 0]]]]] -:test negate +0 = +0 -:test negate -1 = +1 -:test negate +42 = -42 +:test (negate +0) (+0) +:test (negate -1) (+1) +:test (negate +42) (-42) # converts a balanced ternary number to a list of trits list! [0 z neg pos zero] @@ -93,17 +93,17 @@ strip [fst (0 z neg pos zero)] pos [0 [[pair (up-pos 1) F]]] 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 +:test (strip [[[[0 3]]]]) (+0) +:test (strip [[[[2 (0 (0 (0 (0 3))))]]]]) (-1) +:test (strip +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 -:test lst +42 = trit-zero +:test (lst +0) (trit-zero) +:test (lst -1) (trit-neg) +:test (lst +1) (trit-pos) +:test (lst +42) (trit-zero) # extracts most significant trit from balanced ternary numbers # TODO: Find a more elegant way to do this @@ -113,34 +113,34 @@ lst [0 trit-zero [trit-neg] [trit-pos] [trit-zero]] # TODO: Fix list import loop mst [trit-zero] -:test mst +0 = trit-zero -:test mst -1 = trit-neg -:test mst +1 = trit-pos -:test mst +42 = trit-pos +:test (mst +0) (trit-zero) +:test (mst -1) (trit-neg) +:test (mst +1) (trit-pos) +:test (mst +42) (trit-pos) # returns whether balanced ternary number is negative negative? [trit-neg? (mst 0)] -:test negative? +0 = F -:test negative? -1 = T -:test negative? +1 = F -:test negative? +42 = F +:test (negative? +0) (F) +:test (negative? -1) (T) +:test (negative? +1) (F) +:test (negative? +42) (F) # returns whether balanced ternary number is positive positive? [trit-pos? (mst 0)] -:test positive? +0 = F -:test positive? -1 = F -:test positive? +1 = T -:test positive? +42 = T +:test (positive? +0) (F) +:test (positive? -1) (F) +:test (positive? +1) (T) +:test (positive? +42) (T) # 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 +:test (zero? +0) (T) +:test (zero? -1) (F) +:test (zero? +1) (F) +:test (zero? +42) (F) # converts the normal balanced ternary representation into abstract # -> the abstract representation is used in add/sub/mul @@ -150,18 +150,18 @@ abstract! [0 z neg pos zero] pos [[[[[1 4]]]]] zero [[[[[0 4]]]]] -:test abstract! -3 = [[[[0 [[[[2 [[[[3]]]]]]]]]]]] -:test abstract! +0 = [[[[3]]]] -:test abstract! +3 = [[[[0 [[[[1 [[[[3]]]]]]]]]]]] +:test (abstract! -3) ([[[[0 [[[[2 [[[[3]]]]]]]]]]]]) +:test (abstract! +0) ([[[[3]]]]) +:test (abstract! +3) ([[[[0 [[[[1 [[[[3]]]]]]]]]]]]) # converts the abstracted balanced ternary representation back to normal # using ω to solve recursion normal! ω rec rec [[0 +0 [up-neg ([3 3 0] 0)] [up-pos ([3 3 0] 0)] [up-zero ([3 3 0] 0)]]] -:test normal! [[[[3]]]] = +0 -:test normal! (abstract! +42) = +42 -:test normal! (abstract! -42) = -42 +:test (normal! [[[[3]]]]) (+0) +:test (normal! (abstract! +42)) (+42) +:test (normal! (abstract! -42)) (-42) # checks whether two balanced ternary numbers are equal # -> ignores leading 0s! @@ -172,14 +172,16 @@ eq? [[abs 1 (abstract! 0)]] zero [[0 (1 0) [F] [F] [2 0]]] abs [0 z neg pos zero] -:test eq? -42 -42 = T -:test eq? -1 -1 = T -:test eq? -1 +0 = F -:test eq? +0 +0 = T -:test eq? +1 +0 = F -:test eq? +1 +1 = T -:test eq? +42 +42 = T -:test eq? [[[[(1 (0 (0 (0 (0 3)))))]]]] +1 = T +(=?) eq? + +:test (-42 =? -42) (T) +:test (-1 =? -1) (T) +:test (-1 =? +0) (F) +:test (+0 =? +0) (T) +:test (+1 =? +0) (F) +:test (+1 =? +1) (T) +:test (+42 =? +42) (T) +:test ([[[[(1 (0 (0 (0 (0 3)))))]]]] =? +1) (T) # I believe Mogensen's Paper has an error in its inc/dec/add/mul/eq definitions. # They use 3 instead of 2 abstractions in the functions, also we use switched @@ -196,11 +198,11 @@ inc [snd (0 z neg pos zero)] # adds +1 to a balanced ternary number and strips leading 0s sinc [strip (inc 0)] -:test eq? (inc -42) -41 = T -:test eq? (inc -1) +0 = T -:test eq? (inc +0) +1 = T -:test eq? (inc (inc (inc (inc (inc +0))))) +5 = T -:test eq? (inc +42) +43 = T +:test (eq? (inc -42) -41) (T) +:test (eq? (inc -1) +0) (T) +:test (eq? (inc +0) +1) (T) +:test (eq? (inc (inc (inc (inc (inc +0))))) +5) (T) +:test (eq? (inc +42) +43) (T) # subs +1 from a balanced ternary number (can introduce leading 0s) dec [snd (0 dec-z dec-neg dec-pos dec-zero)] @@ -212,11 +214,11 @@ dec [snd (0 dec-z dec-neg dec-pos dec-zero)] # subs +1 from a balanced ternary number and strips leading 0s sdec [strip (dec 0)] -:test eq? (dec -42) -43 = T -:test eq? (dec +0) -1 = T -:test eq? (dec (dec (dec (dec (dec +5))))) +0 = T -:test eq? (dec +1) +0 = T -:test eq? (dec +42) +41 = T +:test (eq? (dec -42) -43) (T) +:test (eq? (dec +0) -1) (T) +:test (eq? (dec (dec (dec (dec (dec +5))))) +0) (T) +:test (eq? (dec +1) +0) (T) +:test (eq? (dec +42) +41) (T) # adds two balanced ternary numbers (can introduce leading 0s) add [[abs 1 (abstract! 0)]] @@ -232,15 +234,17 @@ add [[abs 1 (abstract! 0)]] z [[0 (dec (normal! 1)) (inc (normal! 1)) (normal! 1)]] abs [c (0 z a-neg a-pos a-zero)] +(+) add + # adds two balanced ternary numbers and strips leading 0s 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 -:test eq? (add +0 +0) +0 = T -:test eq? (add +1 +2) +3 = T -:test eq? (add +42 +1) +43 = T +:test (eq? (add -42 -1) -43) (T) +:test (eq? (add -5 +6) +1) (T) +:test (eq? (add -1 +0) -1) (T) +:test (eq? (add +0 +0) +0) (T) +:test (eq? (add +1 +2) +3) (T) +:test (eq? (add +42 +1) +43) (T) # subs two balanced ternary numbers (can introduce leading 0s) sub [[add 1 (negate 0)]] @@ -248,28 +252,34 @@ sub [[add 1 (negate 0)]] # subs two balanced ternary numbers and strips leading 0s 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 -:test eq? (sub +0 +0) +0 = T -:test eq? (sub +1 +2) -1 = T -:test eq? (sub +42 +1) +41 = T +:test (eq? (sub -42 -1) -41) (T) +:test (eq? (sub -5 +6) -11) (T) +:test (eq? (sub -1 +0) -1) (T) +:test (eq? (sub +0 +0) +0) (T) +:test (eq? (sub +1 +2) -1) (T) +:test (eq? (sub +42 +1) +41) (T) # returns whether number is greater than other number gre? [[negative? (sub 0 1)]] +(>?) gre? + # returns whether number is less than or equal to other number leq? [[not (gre? 1 0)]] +(<=?) leq? + # muls two balanced ternary numbers (can introduce leading 0s) mul [[1 +0 neg pos zero]] neg [sub (up-zero 0) 1] pos [add (up-zero 0) 1] zero [up-zero 0] +(*) mul + 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 +: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) diff --git a/std/Option.bruijn b/std/Option.bruijn index a2c1b88..c8a9a95 100644 --- a/std/Option.bruijn +++ b/std/Option.bruijn @@ -10,30 +10,30 @@ some [[[0 2]]] # checks whether option is none none? [0 T [F]] -:test none? none = T -:test none? (some [[0]]) = F +:test (none? none) (T) +:test (none? (some [[0]])) (F) # checks whether option is some some? [0 F [T]] -:test some? none = F -:test some? (some [[0]]) = T +:test (some? none) (F) +:test (some? (some [[0]])) (T) # applies a function to the value in option map [[0 none [some (2 0)]]] -:test map [[1]] (some [[0]]) = some [[[0]]] -:test map [[1]] none = none +:test (map [[1]] (some [[0]])) (some [[[0]]]) +:test (map [[1]] none) (none) # applies a function to the value in option or returns first arg if none map-or [[[0 2 1]]] -:test map-or [[[2]]] [[1]] (some [[0]]) = [[[0]]] -:test map-or [[[2]]] [[1]] none = [[[2]]] +:test (map-or [[[2]]] [[1]] (some [[0]])) ([[[0]]]) +:test (map-or [[[2]]] [[1]] none) ([[[2]]]) # extracts value from option or returns first argument if none unwrap-or [[0 1 I]] -:test unwrap-or F (some T) = T -:test unwrap-or F none = F +:test (unwrap-or F (some T)) (T) +:test (unwrap-or F none) (F) # applies encapsulated value to given function apply [[1 none 0]] -:test apply none [some ([[1]] 0)] = none -:test apply (some [[0]]) [some ([[1]] 0)] = some [[[0]]] +:test (apply none [some ([[1]] 0)]) (none) +:test (apply (some [[0]]) [some ([[1]] 0)]) (some [[[0]]]) diff --git a/std/Pair.bruijn b/std/Pair.bruijn index 38046c8..cca4217 100644 --- a/std/Pair.bruijn +++ b/std/Pair.bruijn @@ -9,28 +9,28 @@ pair [[[0 2 1]]] fst [0 T] # test fst with example pair of [[0]] and [[1]] -:test fst (pair [[0]] [[1]]) = [[0]] +: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]] +: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]] +: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]] +: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]] +:test (swap (pair [[0]] [[1]])) (pair [[1]] [[0]]) diff --git a/std/Result.bruijn b/std/Result.bruijn index a8d830c..3e9960d 100644 --- a/std/Result.bruijn +++ b/std/Result.bruijn @@ -5,48 +5,48 @@ # encapsulates a value in ok ok [[[1 2]]] -:test ok [[0]] = [[1 [[0]]]] +:test (ok [[0]]) ([[1 [[0]]]]) # encapsulates a value in err err [[[0 2]]] -:test err [[0]] = [[0 [[0]]]] +:test (err [[0]]) ([[0 [[0]]]]) # checks whether result is ok ok? [0 [T] [F]] -:test ok? (ok [[0]]) = T -:test ok? (err [[0]]) = F +:test (ok? (ok [[0]])) (T) +:test (ok? (err [[0]])) (F) # checks whether result is not ok err? [0 [F] [T]] -:test err? (ok [[0]]) = F -:test err? (err [[0]]) = T +:test (err? (ok [[0]])) (F) +:test (err? (err [[0]])) (T) # encapsulates result ok value in a option option-ok [0 some [none]] -:test option-ok (ok [[0]]) = some [[0]] -:test option-ok (err [[0]]) = none +:test (option-ok (ok [[0]])) (some [[0]]) +:test (option-ok (err [[0]])) (none) # encapsulate result err value in a option option-err [0 [none] some] -:test option-err (ok [[0]]) = none -:test option-err (err [[0]]) = some [[0]] +:test (option-err (ok [[0]])) (none) +:test (option-err (err [[0]])) (some [[0]]) # extracts value from result or returns first arg unwrap-or [[0 I [2]]] -:test unwrap-or [[1]] (ok [[0]]) = [[0]] -:test unwrap-or [[1]] (err [[0]]) = [[1]] +:test (unwrap-or [[1]] (ok [[0]])) ([[0]]) +:test (unwrap-or [[1]] (err [[0]])) ([[1]]) # applies a function to the value in ok result map [[0 [ok (2 0)] err]] -:test map [[1]] (ok [[0]]) = ok [[[0]]] -:test map [[1]] (err [[0]]) = err [[0]] +:test (map [[1]] (ok [[0]])) (ok [[[0]]]) +:test (map [[1]] (err [[0]])) (err [[0]]) # applies a function to the value in err result map-err [[0 ok [err (2 0)]]] -:test map-err [[1]] (ok [[0]]) = (ok [[0]]) -:test map-err [[1]] (err [[0]]) = (err [[[0]]]) +:test (map-err [[1]] (ok [[0]])) ((ok [[0]])) +:test (map-err [[1]] (err [[0]])) ((err [[[0]]])) # applies encapsulated value to given function (if ok) apply [[1 0 err]] -:test apply (err [[0]]) [ok ([[1]] 0)] = err [[0]] -:test apply (ok [[0]]) [ok ([[1]] 0)] = ok [[[0]]] +:test (apply (err [[0]]) [ok ([[1]] 0)]) (err [[0]]) +:test (apply (ok [[0]]) [ok ([[1]] 0)]) (ok [[[0]]]) |