summaryrefslogtreecommitdiff
path: root/CompilerMacros.hs
blob: 086ad2efa1d309342994493f6919bcf2033067f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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