1 module Main(main) where
7 import Harpy.X86Disassembler
13 import System.Console.Readline
15 import Text.ParserCombinators.Parsec
17 $(callDecl "callAsWord32" [t|Word32|])
20 main = do putStrLn "\n\n\n\nHarpy Interpreter"
21 putStrLn "(type :help to see a help message)"
22 allocaArray 26 (\ p -> mapM_ (\ i -> poke (advancePtr p i) 0) [0..25] >> repl p False)
24 repl :: Ptr Int32 -> Bool -> IO ()
29 Just s' -> do addHistory s'
30 interpret env verbose s'
32 interpret :: Ptr Int32 -> Bool -> String -> IO ()
33 interpret env verbose s =
34 do let e = parse statement "<standard input>" s
36 Left err -> do putStrLn (show err)
38 Right stmt -> run env verbose stmt
40 run :: Ptr Int32 -> Bool -> Stmt -> IO ()
41 run env verbose (Cmd Help) =
42 do putStrLn "Enter an arithmetic expression to evaluate it"
43 putStrLn " e.g. 5 / 2"
44 putStrLn "Enter an assignment to set a variable"
45 putStrLn " e.g. a := 4 * 2 - (6 + 1)"
46 putStrLn "Enter :help to see this message again"
47 putStrLn "Enter :quit to exit"
48 putStrLn "Enter :verbose to toggle disassembly output"
51 run env _ (Cmd Quit) = return ()
53 run env verbose (Cmd Verbose) = repl env (Prelude.not verbose)
55 run env verbose stmt@(Assign var exp) =
56 do (i, ins) <- eval' env stmt
57 when verbose (mapM_ (putStrLn . showIntel) ins)
60 run env verbose stmt@(Print exp) =
61 do (i, ins) <- eval' env stmt
63 when verbose (mapM_ (putStrLn . showIntel) ins)
66 -- Function for compiling and executing statements.
67 eval' :: Ptr Int32 -> Stmt -> IO (Int32, [Instruction])
68 eval' env e = do (_, Right v) <- runCodeGen (compileAndRun e) env ()
71 compileAndRun :: Stmt -> CodeGen (Ptr Int32) s (Int32, [Instruction])
72 compileAndRun (Assign c exp) =
76 mov (variableAddress env c) eax
81 compileAndRun (Print exp) =
87 return (fromIntegral r, d)
89 compileExp :: Exp -> CodeGen (Ptr Int32) s ()
90 compileExp (Add e1 e2) = compileBinOp e1 e2 (add eax (Ind esp))
91 compileExp (Sub e1 e2) = compileBinOp e1 e2 (sub eax (Ind esp))
92 compileExp (Mul e1 e2) = compileBinOp e1 e2 (imul InPlace eax (Ind esp))
93 compileExp (Div e1 e2) = compileBinOp e1 e2 (cdq >> idiv (Ind esp))
94 compileExp (Lit i) = mov eax ((fromIntegral i) :: Word32)
95 compileExp (Var c) = do env <- getEnv
96 mov eax (variableAddress env c)
98 compileBinOp :: Exp -> Exp -> CodeGen (Ptr Int32) s a -> CodeGen (Ptr Int32) s ()
99 compileBinOp e1 e2 op = do compileExp e2
103 add esp (4 :: Word32)
105 entryCode :: CodeGen e s ()
106 entryCode = do push ebp
109 exitCode :: CodeGen e s ()
110 exitCode = do mov esp ebp
114 variableAddress :: Ptr Int32 -> Char -> Addr
115 variableAddress env c =
116 let ofs = fromEnum c - fromEnum 'a'
117 env' = advancePtr env ofs
118 in Addr (fromIntegral (ptrToWordPtr env'))