-- Copyright (c) 2025, Chris Pressey, Cat's Eye Technologies.
-- This file is distributed under a 2-clause BSD license, see LICENSES/ dir.
-- SPDX-License-Identifier: LicenseRef-BSD-2-Clause-X-Burro
module Language.Kondey.Compiler where
import qualified Language.Kondey.Definition as Kondey
import Language.Kondey.Definition (Kondey)
import Language.Burro.Definition
compile :: String -> Burro
compile kondeyText = genBurro $ Kondey.parse kondeyText
genBurro :: Kondey -> Burro
genBurro Kondey.Null = Null
genBurro Kondey.ToggleHalt = ToggleHalt
genBurro Kondey.Inc = Inc
genBurro Kondey.Dec = Dec
genBurro Kondey.GoLeft = GoLeft
genBurro Kondey.GoRight = GoRight
genBurro (Kondey.Test t f) = Test (genBurro t) (genBurro f)
genBurro (Kondey.Seq k1 k2) = Seq (genBurro k1) (genBurro k2)
genBurro (Kondey.Cond ks) = genCond ks
genCond :: [Kondey] -> Burro
genCond (kbranch:kbranches) =
let
counter = 0
fore = Seq (makeBranch counter (genBurro kbranch)) (Test Null Null)
rest = genCondRest kbranches kbranch (counter + 1)
in
Seq fore rest
genCondRest :: [Kondey] -> Kondey -> Int -> Burro
genCondRest [] _prev _counter = Null
genCondRest (kbranch:kbranches) prev counter =
let
b = genBurro kbranch
invB = inverse (genBurro prev)
branch = makeBranch counter (catBurros invB b)
coda = repl (counter * 2) Dec (Test Null Null)
fore = repl (counter * 2) Dec (Seq branch coda)
rest = genCondRest kbranches kbranch (counter + 1)
in
Seq fore rest
makeBranch :: Int -> Burro -> Burro
makeBranch counter b =
let
-- We construct a Test where the "then" side is b, with
-- counter <'s added in front, and counter+1 >'s added behind.
thenSide = repl counter GoLeft $ Seq b $ repl counter GoRight GoRight
elseSide = GoRight
in
Test thenSide elseSide
catBurros :: Burro -> Burro -> Burro
catBurros b1 b2 =
Seq b1 b2
repl :: Int -> Burro -> Burro -> Burro
repl 0 _head tail = tail
repl n head tail = Seq head (repl (n-1) head tail)