Sockeye: Implement port mappings
[barrelfish] / tools / sockeye / SockeyeBackendProlog.hs
1 {-
2   SockeyeBackendProlog.hs: Backend for generating Prolog facts for Sockeye
3
4   Part of Sockeye
5
6   Copyright (c) 2017, ETH Zurich.
7
8   All rights reserved.
9
10   This file is distributed under the terms in the attached LICENSE file.
11   If you do not find this file, copies can be found by writing to:
12   ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
13   Attn: Systems Group.
14 -}
15
16 module SockeyeBackendProlog
17 ( compile ) where
18
19 import Data.Char
20 import Data.List
21 import qualified Data.Map as Map
22 import Data.Maybe
23 import Numeric (showHex)
24
25 import qualified SockeyeASTDecodingNet as AST
26
27 compile :: AST.NetSpec -> String
28 compile = generate
29
30 {- Code Generator -}
31 class PrologGenerator a where
32     generate :: a -> String
33
34 instance PrologGenerator AST.NetSpec where
35     generate (AST.NetSpec net) = let
36         mapped = Map.mapWithKey toFact net
37         facts = Map.elems mapped
38         in unlines facts
39         where
40             toFact nodeId nodeSpec = let
41                 atom = generate nodeId
42                 node = generate nodeSpec
43                 in predicate "net" [atom, node] ++ "."
44
45 instance PrologGenerator AST.NodeId where
46     generate ast = atom $ show ast
47
48 instance PrologGenerator AST.NodeSpec where
49     generate ast = let
50         nodeType = generate $ AST.nodeType ast
51         accept = generate $ AST.accept ast
52         translate = generate $ AST.translate ast
53         overlay = case AST.overlay ast of
54             Nothing -> atom "@none"
55             Just id -> generate id
56         in predicate "node" [nodeType, accept, translate, overlay]
57
58 instance PrologGenerator AST.BlockSpec where
59     generate blockSpec = let
60         base = generate $ AST.base blockSpec
61         limit = generate $ AST.limit blockSpec
62         in predicate "block" [base, limit]
63
64 instance PrologGenerator AST.MapSpec where
65     generate mapSpec = let
66         src  = generate $ AST.srcBlock mapSpec
67         dest = generate $ AST.destNode mapSpec
68         base = generate $ AST.destBase mapSpec
69         in predicate "map" [src, dest, base]
70
71 instance PrologGenerator AST.NodeType where
72     generate AST.Memory = atom "memory"
73     generate AST.Device = atom "device"
74     generate AST.Other  = atom "other"
75
76 instance PrologGenerator AST.Address where
77     generate (AST.Address addr) = "16'" ++ showHex addr ""
78
79 instance PrologGenerator a => PrologGenerator [a] where
80     generate ast = let
81         mapped = map generate ast
82         in list mapped
83
84 {- Helper functions -}
85 atom :: String -> String
86 atom name@(c:cs)
87     | isLower c && alphaNum cs = name
88     | otherwise = quotes name
89     where
90         alphaNum cs = foldl (\acc c -> isAlphaNum c && acc) True cs
91
92 predicate :: String -> [String] -> String
93 predicate name args = name ++ (parens $ intercalate "," args)
94
95 list :: [String] -> String
96 list elems = brackets $ intercalate "," elems
97
98 enclose :: String -> String -> String -> String
99 enclose start end string = start ++ string ++ end
100
101 parens :: String -> String
102 parens = enclose "(" ")"
103
104 brackets :: String -> String
105 brackets = enclose "[" "]"
106
107 quotes :: String -> String
108 quotes = enclose "'" "'"