module Turbo where import Data.Map.Strict (Map) import Data.Map.Strict qualified as Map import Prelude hiding (fmap, pure, (<*>), (<*), (*>), (>>=)) import TurboDef -- "Run" a Turbo program to produce SVG path commands. -- This is the only function that will be tested. runTurbo :: Stmt -> [SVGPathCmd] runTurbo stmt = snd (unTurbo (turbo stmt) initTurboMem) -- But the actual execution engine and recursion are in "turbo" and "evalReal" -- below. -- Evaluate an expression. evalReal :: RealExpr -> Turbo Double evalReal (RLit r) = pure r evalReal (RVar var) = getVar var evalReal (e1 :+: e2) = liftA2 (+) (evalReal e1) (evalReal e2) evalReal (e1 :-: e2) = liftA2 (-) (evalReal e1) (evalReal e2) evalReal (e1 :*: e2) = liftA2 (*) (evalReal e1) (evalReal e2) evalReal (e1 :/: e2) = liftA2 (/) (evalReal e1) (evalReal e2) -- Turbo interpreter. Return SVG path commands. turbo :: Stmt -> Turbo [SVGPathCmd] turbo = error "TODO" -- If you could code up the following helpers, your turbo implementation could -- be much less repetitive and higher-level. fmap, get, modify, Map.lookup, and -- Map.insert will get you a long way. getPen and setPen are provided as examples. -- Get current direction. getAngle :: Turbo Double getAngle = error "TODO" -- Change direction by adding the given angle. turn :: Double -> Turbo () turn t = error "TODO" -- Get pen state. getPen :: Turbo Bool getPen = fmap (\(TurboMem _ _ p) -> p) get -- Set pen state. setPen :: Bool -> Turbo () setPen b = modify (\(TurboMem vs a _) -> TurboMem vs a b) -- Get a variable's current value. (If not found, give 0 for simplicity.) getVar :: String -> Turbo Double getVar = error "TODO" -- Set a variable to value. setVar :: String -> Double -> Turbo () setVar = error "TODO"