Sockeye: Implement module instantiator
[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 Numeric (showHex)
23
24 import qualified SockeyeASTDecodingNet as AST
25
26 compile :: AST.NetSpec -> String
27 compile = generate
28
29 {- Code Generator -}
30 class PrologGenerator a where
31     generate :: a -> String
32
33 instance PrologGenerator AST.NetSpec where
34     generate (AST.NetSpec net) = let
35         mapped = Map.mapWithKey toFact net
36         facts = Map.elems mapped
37         in unlines facts
38         where
39             toFact nodeId nodeSpec = let
40                 atom = generate nodeId
41                 node = generate nodeSpec
42                 in predicate "net" [atom, node] ++ "."
43
44 instance PrologGenerator AST.NodeId where
45     generate ast = let
46         name = AST.name ast
47         namespace = AST.namespace ast
48         in predicate "nodeId" [atom name, generate namespace]
49
50 instance PrologGenerator AST.Namespace where
51     generate ast = let
52         ns = AST.ns ast
53         in list $ map atom ns
54
55 instance PrologGenerator AST.NodeSpec where
56     generate ast = let
57         nodeType = generate $ AST.nodeType ast
58         accept = generate $ AST.accept ast
59         translate = generate $ AST.translate ast
60         in predicate "node" [nodeType, accept, translate]
61
62 instance PrologGenerator AST.BlockSpec where
63     generate blockSpec = let
64         base = generate $ AST.base blockSpec
65         limit = generate $ AST.limit blockSpec
66         in predicate "block" [base, limit]
67
68 instance PrologGenerator AST.MapSpec where
69     generate mapSpec = let
70         src  = generate $ AST.srcBlock mapSpec
71         dest = generate $ AST.destNode mapSpec
72         base = generate $ AST.destBase mapSpec
73         in predicate "map" [src, dest, base]
74
75 instance PrologGenerator AST.NodeType where
76     generate AST.Memory = atom "memory"
77     generate AST.Device = atom "device"
78     generate AST.Other  = atom "other"
79
80 instance PrologGenerator AST.Address where
81     generate (AST.Address addr) = "16'" ++ showHex addr ""
82
83 instance PrologGenerator a => PrologGenerator [a] where
84     generate ast = let
85         mapped = map generate ast
86         in list mapped
87
88 {- Helper functions -}
89 atom :: String -> String
90 atom "" = ""
91 atom name@(c:cs)
92     | isLower c && allAlphaNum cs = name
93     | otherwise = quotes name
94     where
95         allAlphaNum cs = foldl (\acc c -> isAlphaNum c && acc) True cs
96
97 predicate :: String -> [String] -> String
98 predicate name args = name ++ (parens $ intercalate "," args)
99
100 list :: [String] -> String
101 list elems = brackets $ intercalate "," elems
102
103 enclose :: String -> String -> String -> String
104 enclose start end string = start ++ string ++ end
105
106 parens :: String -> String
107 parens = enclose "(" ")"
108
109 brackets :: String -> String
110 brackets = enclose "[" "]"
111
112 quotes :: String -> String
113 quotes = enclose "'" "'"