Created
April 14, 2018 16:14
-
-
Save zehnpaard/1b3bd6448c3bdc8cd3a01b5b3e96755a to your computer and use it in GitHub Desktop.
Minimal Lisp Compiler inspired by Joe Gibbs Politz (@joepolitz) and http://scheme2006.cs.uchicago.edu/11-ghuloum.pdf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Text.ParserCombinators.Parsec | |
import Text.Printf | |
import System.Environment | |
data Sexp = Atom String | |
| List [Sexp] | |
parseSexp :: Parser Sexp | |
parseSexp = parseAtom <|> parseList | |
parseAtom :: Parser Sexp | |
parseAtom = ((many1 letter) <|> (many1 digit)) >>= return . Atom | |
parseList :: Parser Sexp | |
parseList = between (char '(') (char ')') $ sepBy parseSexp (many1 space) >>= return . List | |
stringToSexp :: String -> Sexp | |
stringToSexp s = case parse parseSexp "compiler" s of | |
Left err -> error $ "Parse failed at String->Sexp conversion: " ++ show err | |
Right sexp -> sexp | |
data Op = Inc | |
| Dec | |
data Expr = ENum Integer | |
| EOp Op Expr | |
sexpToExpr :: Sexp -> Expr | |
sexpToExpr (Atom s) = ENum (read s :: Integer) | |
sexpToExpr (List [Atom "inc", arg]) = EOp Inc (sexpToExpr arg) | |
sexpToExpr (List [Atom "dec", arg]) = EOp Dec (sexpToExpr arg) | |
sexpToExpr _ = error "Parse failed at Sexp->Expr conversion" | |
exprToInstrs :: Expr -> [String] | |
exprToInstrs (ENum n) = ["move eax, " ++ show n] | |
exprToInstrs (EOp Inc e) = exprToInstrs e ++ ["add eax, 1"] | |
exprToInstrs (EOp Dec e) = exprToInstrs e ++ ["sub eax, 1"] | |
compile :: String -> String | |
compile s = body `seq` header ++ body ++ footer | |
where header = "section . text\nglobal our_code_starts_here\nour_code_starts_here:\n" | |
body = concat $ map (printf " %s\n") $ exprToInstrs $ sexpToExpr $ stringToSexp s | |
footer = " ret\n" | |
main :: IO () | |
main = do args <- getArgs | |
source <- readFile $ head args | |
putStrLn $ compile source |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment