From af2a6d999e7724f34021d3a5ef9896f0ddb7b00c Mon Sep 17 00:00:00 2001 From: wheatwizard Date: Tue, 13 Jun 2017 14:09:52 -0400 Subject: [PATCH] Improvements to speed, custom miniflak mode --- .gitignore | 2 ++ BrainHack.hs | 15 ++++++---- Helpers.hs | 32 +++++++++++++++++++++ Interpreter.hs | 63 +++++++++++++++++++--------------------- MiniInterpreter.hs | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 146 insertions(+), 38 deletions(-) create mode 100644 Helpers.hs create mode 100644 MiniInterpreter.hs diff --git a/.gitignore b/.gitignore index 450f32e..4746039 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ cabal.sandbox.config .stack-work/ cabal.project.local .HTF/ +BrainHack +*.flk diff --git a/BrainHack.hs b/BrainHack.hs index a59ae68..a26e8d7 100644 --- a/BrainHack.hs +++ b/BrainHack.hs @@ -1,4 +1,5 @@ import Interpreter +import MiniInterpreter import System.Environment import Data.List import Data.Char @@ -39,7 +40,9 @@ helpMenu = unlines ["", " -a, --ascii-out\t\tOutputs as ascii character codes.", " -e, --execute\t\tExecutes the first commandline argument as Brain-Flak code.", " -h, --help\t\t\tPrints this menu and exits.", - " -v, --version\t\tPrints the version number of the interpreter and exits."] + " -m, --mini\t\t\tRun in an interpreter optimized for miniflak,", + " -v, --version\t\tPrints the version number of the interpreter and exits.", + " -x, --cycles\t\t\tPrints the number of cycles elapsed upon termination."] displayInteger :: Integer -> String displayInteger x = show x ++ " " @@ -62,7 +65,9 @@ main = do ) ) let formatOutput = if (elem "a" flags)||(elem "ascii-out" flags) then (\x -> (chr.fromInteger) x:[]) else displayInteger - putStr$ if exiting then - "" - else - (concat (map formatOutput (brainflak source (processInput (tail args))))) + let cycles = (elem "x" flags)||(elem "cycles" flags) + putStr$ (if exiting then + "" + else + (\ (a,b) -> (concat (map formatOutput a)) ++ (if cycles then ("\nCycles: " ++ show b) else "")) (if (elem "m" flags)||(elem "mini" flags) then (miniflak source (processInput (tail args)) cycles) else (brainflak source (processInput (tail args)) cycles)) + ) diff --git a/Helpers.hs b/Helpers.hs new file mode 100644 index 0000000..42ef6c5 --- /dev/null +++ b/Helpers.hs @@ -0,0 +1,32 @@ +module Helpers (pop,rest,topadd,interior,exterior) where + +pop :: (Integral a) => [a] -> a +pop [] = 0 +pop (x:_) = x + +rest :: (Integral a) => [a] -> [a] +rest [] = [] +rest (_:x) = x + +topadd :: [Integer] -> Integer -> [Integer] +topadd [] x = [x] +topadd (a:[]) x = [a+x] +topadd (a:b) x = (a+x):b + +ir :: [Char] -> Integer -> [Char] +ir x 0 = "" +ir ('{':x) y = "{" ++ (ir x (y+1)) +ir ('}':x) y = "}" ++ (ir x (y-1)) +ir (a:x) y = [a] ++ (ir x y ) + +interior :: [Char] -> [Char] +interior x = init (ir x 1) + +ex :: [Char] -> Integer -> [Char] +ex x 0 = x +ex ('{':x) y = ex x (y+1) +ex ('}':x) y = ex x (y-1) +ex (a:x) y = ex x y + +exterior :: [Char] -> [Char] +exterior x = ex x 1 diff --git a/Interpreter.hs b/Interpreter.hs index 8d1b8a1..766ed38 100644 --- a/Interpreter.hs +++ b/Interpreter.hs @@ -1,35 +1,8 @@ module Interpreter (brainflak) where -pop :: (Integral a) => [a] -> a -pop [] = 0 -pop (x:_) = x +import Helpers -rest :: (Integral a) => [a] -> [a] -rest [] = [] -rest (_:x) = x - -topadd :: [Integer] -> Integer -> [Integer] -topadd [] x = [x] -topadd (a:[]) x = [a+x] -topadd (a:b) x = (a+x):b - -ir :: [Char] -> Integer -> [Char] -ir x 0 = "" -ir ('{':x) y = "{" ++ (ir x (y+1)) -ir ('}':x) y = "}" ++ (ir x (y-1)) -ir (a:x) y = [a] ++ (ir x y ) - -interior :: [Char] -> [Char] -interior x = init (ir x 1) - -ex :: [Char] -> Integer -> [Char] -ex x 0 = x -ex ('{':x) y = ex x (y+1) -ex ('}':x) y = ex x (y-1) -ex (a:x) y = ex x y - -exterior :: [Char] -> [Char] -exterior x = ex x 1 +--- bf is the main version of the interpreter --- bf :: [Char] -> ([Integer],[Integer],[Integer]) -> ([Integer],[Integer],[Integer]) bf [] (x,y,z)= (x,y,z) @@ -48,10 +21,32 @@ bf (_:a) t = bf a t run :: [Char] -> ([Integer],[Integer],[Integer]) -> ([Integer],[Integer],[Integer]) run s ([],y,z) = ([],y,z) -run s ([0],y,z) = ([0],y,z) run s (0:x,y,z) = (0:x,y,z) run s x = run s (bf s x) +--- xbf is a slower cycle counting version of bf --- + +xbf :: [Char] -> ([Integer],[Integer],[Integer],Int) -> ([Integer],[Integer],[Integer],Int) +xbf _ (_,_,_,c) | c `seq` False = undefined +xbf [] (x,y,z,c)= (x,y,z,c) +xbf ('(':')':a) (x,y,z,c)= xbf a (x,y,((pop z+1):rest z),c+1) +xbf ('<':'>':a) (x,y,z,c)= xbf a (y,x,z,c+1) +xbf ('{':'}':a) (x,y,z,c)= xbf a ((rest x),y,(topadd z (pop x)),c+1) +xbf ('[':']':a) (x,y,z,c)= xbf a (x,y,(topadd z (toInteger (length x))),c+1) +xbf ('(':a) (x,y,z,c)= xbf a (x,y,(0:z),c+1) +xbf ('<':a) (x,y,z,c)= xbf a (x,y,(0:z),c+1) +xbf ('[':a) (x,y,z,c)= xbf a (x,y,(0:z),c+1) +xbf (')':a) (x,y,(h:z),c)= xbf a ((h:x),y,(topadd z h),c+1) +xbf (']':a) (x,y,(h:z),c)= xbf a (x,y,(topadd z (-h)),c+1) +xbf ('>':a) (x,y,(_:z),c)= xbf a (x,y,z,c+1) +xbf ('{':a) t = xbf (exterior a) (xrun (interior a) t) +xbf (_:a) t = xbf a t + +xrun :: [Char] -> ([Integer],[Integer],[Integer],Int) -> ([Integer],[Integer],[Integer],Int) +xrun s ([],y,z,c) = ([],y,z,c) +xrun s (0:x,y,z,c) = (0:x,y,z,c) +xrun s x = xrun s (xbf s x) + bl :: [Char] -> [Char] -> Bool bl [] [] = True bl [] _ = False @@ -76,7 +71,9 @@ clean (x:xs) | elem x "()[]<>{}" = x:(clean xs) | otherwise = clean xs -brainflak :: [Char] -> [Integer] -> [Integer] -brainflak s x - | balanced s = (\(a,_,_) -> a) (bf (clean s) (x,[],[])) +brainflak :: [Char] -> [Integer] -> Bool -> ([Integer], Int) +brainflak s x c + | balance && c = (\(a,_,_,c) -> (a,c)) (xbf (clean s) (x,[],[],0)) + | balance && (not c) = (\(a,_,_) -> (a,0)) ( bf (clean s) (x,[],[] )) | otherwise = error "Unbalanced braces." + where balance = balanced s diff --git a/MiniInterpreter.hs b/MiniInterpreter.hs new file mode 100644 index 0000000..e0978ac --- /dev/null +++ b/MiniInterpreter.hs @@ -0,0 +1,72 @@ +module MiniInterpreter (miniflak) where + +import Helpers + +bf :: [Char] -> ([Integer],[Integer]) -> ([Integer],[Integer]) +bf [] (x,z)= (x,z) +bf ('(':')':a) (x,z)= bf a (x,((pop z+1):rest z)) +bf ('{':'}':a) (x,z)= bf a ((rest x),(topadd z (pop x))) +bf ('[':']':a) (x,z)= bf a (x,(topadd z (toInteger (length x)))) +bf ('(':a) (x,z)= bf a (x,(0:z)) +bf ('[':a) (x,z)= bf a (x,(0:z)) +bf (')':a) (x,(h:z))= bf a ((h:x),(topadd z h)) +bf (']':a) (x,(h:z))= bf a (x,(topadd z (-h))) +bf ('{':a) t = bf (exterior a) (run (interior a) t) +bf (_:a) t = bf a t + +run :: [Char] -> ([Integer],[Integer]) -> ([Integer],[Integer]) +run s ([],z) = ([],z) +run s (0:x,z) = (0:x,z) +run s x = run s (bf s x) + +--- xbf is a version of bf that counts cycles --- + +xbf :: [Char] -> ([Integer],[Integer],Int) -> ([Integer],[Integer],Int) +xbf _ (_,_,c) | c `seq` False = undefined +xbf [] (x,z,c)= (x,z,c+1) +xbf ('(':')':a) (x,z,c)= xbf a (x,((pop z+1):rest z),c+1) +xbf ('{':'}':a) (x,z,c)= xbf a ((rest x),(topadd z (pop x)),c+1) +xbf ('[':']':a) (x,z,c)= xbf a (x,(topadd z (toInteger (length x))),c+1) +xbf ('(':a) (x,z,c)= xbf a (x,(0:z),c+1) +xbf ('[':a) (x,z,c)= xbf a (x,(0:z),c+1) +xbf (')':a) (x,(h:z),c)= xbf a ((h:x),(topadd z h),c+1) +xbf (']':a) (x,(h:z),c)= xbf a (x,(topadd z (-h)),c+1) +xbf ('{':a) t = xbf (exterior a) (xrun (interior a) t) +xbf (_:a) t = xbf a t + +xrun :: [Char] -> ([Integer],[Integer],Int) -> ([Integer],[Integer],Int) +xrun s ([],z,c) = ([],z,c) +xrun s (0:x,z,c) = (0:x,z,c) +xrun s x = xrun s (xbf s x) + +bl :: [Char] -> [Char] -> Bool +bl [] [] = True +bl [] _ = False +bl ('(':x) y = bl x (')':y) +bl ('[':x) y = bl x (']':y) +bl ('<':x) y = bl x ('>':y) +bl ('{':x) y = bl x ('}':y) +bl (a:x) [] + | elem a ")]>}" = False + | otherwise = bl x [] +bl (a:x) (b:y) + | elem a ")]>}" = (a == b) && (bl x y) + | otherwise = bl x (b:y) + +balanced :: [Char] -> Bool +balanced x = bl x [] + +clean :: [Char] -> [Char] +clean [] = [] +clean ('#':'{':xs) = clean (exterior xs) +clean ('[':']':xs) = clean xs +clean (x:xs) + | elem x "()[]{}" = x:(clean xs) + | otherwise = clean xs + +miniflak :: [Char] -> [Integer] -> Bool -> ([Integer],Int) +miniflak s x c + | balance && c = (\(a,_,c) -> (a,c)) (xbf (clean s) (x,[],0)) + | balance && (not c) = (\(a,_) -> (a,0)) (bf (clean s) (x,[] )) + | otherwise = error "Unbalanced braces." + where balance = balanced s