Sockeye: Start implementing overley to map translation
[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 = let
47         name = AST.name ast
48         namespace = AST.namespace ast
49         in predicate "nodeId" [atom name, generate namespace]
50
51 instance PrologGenerator AST.Namespace where
52     generate ast = let
53         ns = AST.ns ast
54         in list $ map atom ns
55
56 instance PrologGenerator AST.NodeSpec where
57     generate ast = let
58         nodeType = generate $ AST.nodeType ast
59         accept = generate $ AST.accept ast
60         translate = generate $ AST.translate ast
61         in predicate "node" [nodeType, accept, translate]
62
63 instance PrologGenerator AST.BlockSpec where
64     generate blockSpec = let
65         base = generate $ AST.base blockSpec
66         limit = generate $ AST.limit blockSpec
67         in predicate "block" [base, limit]
68
69 instance PrologGenerator AST.MapSpec where
70     generate mapSpec = let
71         src  = generate $ AST.srcBlock mapSpec
72         dest = generate $ AST.destNode mapSpec
73         base = generate $ AST.destBase mapSpec
74         in predicate "map" [src, dest, base]
75
76 instance PrologGenerator AST.NodeType where
77     generate AST.Memory = atom "memory"
78     generate AST.Device = atom "device"
79     generate AST.Other  = atom "other"
80
81 instance PrologGenerator AST.Address where
82     generate (AST.Address addr) = "16'" ++ showHex addr ""
83
84 instance PrologGenerator a => PrologGenerator [a] where
85     generate ast = let
86         mapped = map generate ast
87         in list mapped
88
89 {- Helper functions -}
90 atom :: String -> String
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 "'" "'"