module CompilerMacros(compilerMacros) where import AST compilerMacros :: Program -> Program compilerMacros (Program values) = Program (map process values) process :: Value -> Value process (VList [VName "define", VName name, VList args, body]) | Just names <- mapM fromVName args = process (VList [VName "define", VName name, VLambda names body]) | otherwise = error "Invalid 'define' shorthand syntax: Invalid argument list" process (VList [VName "define", VName name, value]) = VDefine name (process value) process (VList (VName "define" : _)) = error "Invalid 'define' syntax" process (VList [VName "declare", VName name]) = process (VDeclare name) process (VList (VName "declare" : _)) = error "Invalid 'declare' syntax" process (VList [VName "lambda", VList args, body]) | Just names <- mapM fromVName args = process (VLambda names body) | otherwise = error "Invalid 'lambda' syntax: Invalid argument list" process (VList (VName "lambda" : _)) = error "Invalid 'lambda' syntax" process (VList [VName "lambdarec", VName recname, VList args, body]) | Just names <- mapM fromVName args = process (VLambdaRec recname names body) | otherwise = error "Invalid 'lambdarec' syntax: Invalid argument list" process (VList (VName "lambdarec" : _)) = error "Invalid 'lambdarec' syntax" -- process (VList [VName "let", VList args, body]) = -- case sequence [case p of { [n, v] -> Just (n, v); _ -> Nothing } | VList p <- args] of -- Just pairs -> -- process (VList (VList [VName "lambda", VList (map fst pairs), body] : map snd pairs)) -- Nothing -> -- error "Invalid 'let' syntax: Invalid variable list (not all pairs)" process (VList [VName "let", VList args, body]) = case sequence [case p of { [VName n, v] -> Just (n, v); _ -> Nothing } | VList p <- args] of Just pairs -> process (VLet pairs body) Nothing -> error "Invalid 'let' syntax: Invalid variable list (not all pairs)" process (VList (VName "let" : _)) = error "Invalid 'let' syntax: Invalid argument list" process (VList [VName "cond", defval]) = process defval process (VList (VName "cond" : cond1 : val1 : rest)) = process (VList [VName "if", cond1, val1, VList (VName "cond" : rest)]) process (VList [VName "cond"]) = error "Invalid 'cond' syntax: Even number of arguments" process (VList values) = VList (map process values) process (VDeclare name) = VDeclare name process (VDefine name body) = VDefine name (process body) process (VLambda args body) = VLambda args (process body) process (VLambdaRec recname args body) = VLambdaRec recname args (process body) process (VLet args body) = VLet [(name, process value) | (name, value) <- args] (process body) process v@(VNum _) = v process v@(VString _) = v process v@(VName _) = v process v@(VQuoted _) = v process v@(VBuiltin _) = v process v@VEllipsis = v