Format for conditional structures is actually its own language.
Chris Pressey
3 months ago
451 | 451 | by hand would be tiresome and error-prone. So it would be beneficial to have them be |
452 | 452 | machine-generated. |
453 | 453 | |
454 | To that end, the reference implementation of Burro contains a facility to generate these | |
455 | conditional structures. | |
456 | ||
457 | -> Tests for functionality "Generate Burro Conditional" | |
458 | ||
459 | -> Functionality "Generate Burro Conditional" is implemented by | |
460 | -> shell command "bin/burro gencond %(test-body-file)" | |
461 | ||
462 | The facility to generate conditional structures takes, as input, a sequence of | |
463 | Burro program fragments, one on each line. It generates a conditional structure | |
464 | following this pattern: | |
454 | To that end, a facility to generate these conditional structures has been implemented. | |
455 | In fact, a mini language for describing these structure, **Kondey**, has been defined, | |
456 | and we have implemented a compiler from Kondey to Burro. | |
457 | ||
458 | -> Tests for functionality "Compile Kondey Program" | |
459 | ||
460 | -> Functionality "Compile Kondey Program" is implemented by | |
461 | -> shell command "bin/burro compile-kondey %(test-body-file)" | |
462 | ||
463 | A Kondey program (for now) consists of a sequence of Burro program fragments, | |
464 | one on each line. It generates a conditional structure following this pattern: | |
465 | 465 | |
466 | 466 | * if the current cell is greater than 0, then execute the 1st fragment |
467 | 467 | * if the current cell is greater than 2, then undo the 1st fragment and execute the 2nd fragment |
0 | -- Copyright (c) 2007-2023, Chris Pressey, Cat's Eye Technologies. | |
1 | -- This file is distributed under a 2-clause BSD license, see LICENSES/ dir. | |
2 | -- SPDX-License-Identifier: LicenseRef-BSD-2-Clause-X-Burro | |
3 | ||
4 | module Language.Burro.Generator where | |
5 | ||
6 | import Language.Burro.Definition | |
7 | ||
8 | ||
9 | genCond :: [String] -> Burro | |
10 | genCond (burroText:burroTexts) = | |
11 | let | |
12 | b = parse burroText | |
13 | counter = 0 | |
14 | fore = Seq (makeBranch counter b) (Test Null Null) | |
15 | rest = genCondRest burroTexts b (counter + 1) | |
16 | in | |
17 | Seq fore rest | |
18 | ||
19 | genCondRest [] _prevFragment _counter = Null | |
20 | genCondRest (burroText:burroTexts) prevFragment counter = | |
21 | let | |
22 | b = parse burroText | |
23 | invB = inverse prevFragment | |
24 | branch = makeBranch counter (catBurros invB b) | |
25 | coda = repl (counter * 2) Dec (Test Null Null) | |
26 | fore = repl (counter * 2) Dec (Seq branch coda) | |
27 | rest = genCondRest burroTexts b (counter + 1) | |
28 | in | |
29 | Seq fore rest | |
30 | ||
31 | makeBranch counter b = | |
32 | let | |
33 | -- We construct a Test where the "then" side is b, with | |
34 | -- counter <'s added in front, and counter+1 >'s added behind. | |
35 | thenSide = repl counter GoLeft $ Seq b $ repl counter GoRight GoRight | |
36 | elseSide = GoRight | |
37 | in | |
38 | Test thenSide elseSide | |
39 | ||
40 | catBurros b1 b2 = | |
41 | Seq b1 b2 | |
42 | ||
43 | repl 0 _head tail = tail | |
44 | repl n head tail = Seq head (repl (n-1) head tail) | |
45 | ||
46 | renderBurro Null = "" | |
47 | renderBurro ToggleHalt = "!" | |
48 | renderBurro Inc = "+" | |
49 | renderBurro Dec = "-" | |
50 | renderBurro GoLeft = "<" | |
51 | renderBurro GoRight = ">" | |
52 | renderBurro (Test a b) = "(" ++ (renderBurro a) ++ "/" ++ (renderBurro b) ++ ")" | |
53 | renderBurro (Seq a b) = (renderBurro a) ++ (renderBurro b) |
0 | -- Copyright (c) 2007-2023, Chris Pressey, Cat's Eye Technologies. | |
1 | -- This file is distributed under a 2-clause BSD license, see LICENSES/ dir. | |
2 | -- SPDX-License-Identifier: LicenseRef-BSD-2-Clause-X-Burro | |
3 | ||
4 | module Language.Kondey.Compiler where | |
5 | ||
6 | import Language.Burro.Definition | |
7 | ||
8 | ||
9 | compile :: String -> Burro | |
10 | compile kondeyText = | |
11 | genCond $ lines kondeyText | |
12 | ||
13 | ||
14 | genCond :: [String] -> Burro | |
15 | genCond (burroText:burroTexts) = | |
16 | let | |
17 | b = parse burroText | |
18 | counter = 0 | |
19 | fore = Seq (makeBranch counter b) (Test Null Null) | |
20 | rest = genCondRest burroTexts b (counter + 1) | |
21 | in | |
22 | Seq fore rest | |
23 | ||
24 | genCondRest [] _prevFragment _counter = Null | |
25 | genCondRest (burroText:burroTexts) prevFragment counter = | |
26 | let | |
27 | b = parse burroText | |
28 | invB = inverse prevFragment | |
29 | branch = makeBranch counter (catBurros invB b) | |
30 | coda = repl (counter * 2) Dec (Test Null Null) | |
31 | fore = repl (counter * 2) Dec (Seq branch coda) | |
32 | rest = genCondRest burroTexts b (counter + 1) | |
33 | in | |
34 | Seq fore rest | |
35 | ||
36 | makeBranch counter b = | |
37 | let | |
38 | -- We construct a Test where the "then" side is b, with | |
39 | -- counter <'s added in front, and counter+1 >'s added behind. | |
40 | thenSide = repl counter GoLeft $ Seq b $ repl counter GoRight GoRight | |
41 | elseSide = GoRight | |
42 | in | |
43 | Test thenSide elseSide | |
44 | ||
45 | catBurros b1 b2 = | |
46 | Seq b1 b2 | |
47 | ||
48 | repl 0 _head tail = tail | |
49 | repl n head tail = Seq head (repl (n-1) head tail) | |
50 | ||
51 | renderBurro Null = "" | |
52 | renderBurro ToggleHalt = "!" | |
53 | renderBurro Inc = "+" | |
54 | renderBurro Dec = "-" | |
55 | renderBurro GoLeft = "<" | |
56 | renderBurro GoRight = ">" | |
57 | renderBurro (Test a b) = "(" ++ (renderBurro a) ++ "/" ++ (renderBurro b) ++ ")" | |
58 | renderBurro (Seq a b) = (renderBurro a) ++ (renderBurro b) |
6 | 6 | import System.Environment |
7 | 7 | import Language.Burro.Definition |
8 | 8 | import qualified Language.Burro.Debugger as Debugger |
9 | import qualified Language.Burro.Generator as Generator | |
9 | import qualified Language.Kondey.Compiler as Compiler | |
10 | 10 | |
11 | 11 | main = do |
12 | 12 | args <- getArgs |
18 | 18 | burroText <- readFile fileName |
19 | 19 | state <- Debugger.interpret burroText |
20 | 20 | putStrLn $ show $ state |
21 | ["gencond", fileName] -> do | |
22 | burroCollectionText <- readFile fileName | |
23 | let burroTexts = lines burroCollectionText | |
24 | let g :: Burro = Generator.genCond burroTexts | |
25 | putStrLn $ Generator.renderBurro g | |
21 | ["compile-kondey", fileName] -> do | |
22 | kondeyText <- readFile fileName | |
23 | let g :: Burro = Compiler.compile kondeyText | |
24 | putStrLn $ Compiler.renderBurro g | |
26 | 25 | _ -> do |
27 | putStrLn "Usage: burro (run|debug|gencond) <filename.burro>" | |
26 | putStrLn $ | |
27 | "Usage:\n" ++ | |
28 | " burro run <filename.burro>\n" ++ | |
29 | " burro debug <filename.burro>\n" ++ | |
30 | " burro compile-kondey <filename.kondey>\n" |