-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathCodeGen.hs
More file actions
80 lines (64 loc) · 3.6 KB
/
CodeGen.hs
File metadata and controls
80 lines (64 loc) · 3.6 KB
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
{-
Copyright 2014 Harold H. Lee
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-}
module CodeGen where
import Data.List
import AST
data Context = Function String
| Class String
contextName (Function name) = name
contextName (Class name) = name
codegen :: [Context] -> Expr -> String
codegen ctx T = "t"
codegen ctx Nil = "nil"
codegen ctx NoOp = "nil"
codegen ctx (Assign dests vals) = "(psetf " ++ (codegenSeveral ctx dests) ++ " " ++ (codegenSeveral ctx vals) ++ ")"
codegen ctx (VariableRef name) = name
codegen ctx (Literal value) = value
codegen ctx (Format dest vals newline) = "(format " ++ codegen ctx dest ++ " " ++ show formatString ++ " " ++ codegenSeveral ctx vals ++ ")"
where formatString = (unwords $ take (length vals) (repeat "~a")) ++ (if newline then "~%" else "")
codegen ctx (FunDef name params body) = "(defun " ++ name ++ " (" ++ genParams ctx params ++ ") " ++ codegenSeveral (Function name : ctx) body ++ ")"
codegen (c:ctx) (ReturnExpr Nothing) = "(return-from " ++ contextName c ++ ")"
codegen (c:ctx) (ReturnExpr (Just exprs)) = "(return-from " ++ contextName c ++ " " ++ codegenSeveral (c:ctx) exprs ++ ")"
codegen ctx (ApplyFun name args) = "(" ++ codegen ctx name ++ " " ++ genArgs ctx args ++ ")"
codegen ctx (CondBlock cases) = "(cond " ++ unwords (map (genCondCase ctx) cases) ++ ")"
codegen ctx ToDo = error "ack! There is a ToDo left in the parse tree!"
codegen ctx expr = error $ "ack! Unimplemented AST structure, need to fix CodeGen for " ++ (show expr)
codegenSeveral ctx exprs = unwords $ map (codegen ctx) exprs
genArgs ctx (Params positional varargs kwargs) = unwords (map (genParam ctx) positional) ++ var ++ kw
where var = case varargs of
Nothing -> ""
Just name -> " name"
kw = "" -- TODO
genParams ctx (Params positional varargs kwargs) = genPositionalParams ctx False positional ++ genVarargs varargs ++ genKwargs kwargs
-- The boolean flag indicates whether or not we have added the &optional marker yet.
genPositionalParams :: [Context] -> Bool -> [Expr] -> String
genPositionalParams _ _ [] = ""
genPositionalParams ctx True ps = unwords $ map (genParam ctx) ps
genPositionalParams ctx False (p:ps) | isOptionalParam p = " &optional " ++ (genPositionalParams ctx True (p:ps))
genPositionalParams ctx False (p:ps) = (genParam ctx p) ++ (genPositionalParams ctx False ps)
isOptionalParam :: Expr -> Bool
isOptionalParam (Param (Just _) (Just _)) = True
isOptionalParam _ = False
genParam ctx (Param (Just (Literal name)) Nothing) = name
genParam ctx (Param (Just (Literal name)) (Just expr)) = "(" ++ name ++ " " ++ (codegen ctx expr) ++ ")"
genParam ctx (Param Nothing (Just (Literal value))) = value
genParam ctx (Param Nothing (Just expr)) = codegen ctx expr
genParam ctx (VariableRef name) = name
genParam ctx (Literal value) = value
genParam ctx expr = codegen ctx expr
--genParam ctx expr = error $ "Can't treat as a parameter: " ++ show expr
genVarargs Nothing = ""
genVarargs (Just name) = " &rest " ++ name
genKwargs Nothing = ""
genKwargs _ = undefined
genCondCase ctx (test, exprs) = "(" ++ codegen ctx test ++ " " ++ codegenSeveral ctx exprs ++ ")"