convert-constants 3.73 KB
Newer Older
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
#!/usr/bin/python
#

# Copyright (C) 2011 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

"""Script for converting Python constants to Haskell code fragments.

"""

import re

from ganeti import constants
28
from ganeti import compat
29

30
CONSTANT_RE = re.compile("^[A-Z][A-Z0-9_-]+$")
31
32
33
34
35
36


def NameRules(name):
  """Converts the upper-cased Python name to Haskell camelCase.

  """
37
  name = name.replace("-", "_")
38
39
40
41
42
43
44
45
46
47
48
49
50
  elems = name.split("_")
  return elems[0].lower() + "".join(e.capitalize() for e in elems[1:])


def StringValueRules(value):
  """Converts a string value from Python to Haskell.

  """
  value = value.encode("string_escape") # escapes backslashes
  value = value.replace("\"", "\\\"")
  return value


51
52
53
54
55
56
57
def DictKeyName(dict_name, key_name):
  """Converts a dict plus key name to a full name.

  """
  return"%s_%s" % (dict_name, str(key_name).upper())


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
def HaskellTypeVal(value):
  """Returns the Haskell type and value for a Python value.

  Note that this only work for 'plain' Python types.

  @returns: (string, string) or None, if we can't determine the type.

  """
  if isinstance(value, basestring):
    return ("String", "\"%s\"" % StringValueRules(value))
  elif isinstance(value, int):
    return ("Int", "%d" % value)
  elif isinstance(value, long):
    return ("Integer", "%d" % value)
  elif isinstance(value, float):
    return ("Double", "%f" % value)
  else:
    return None


78
79
80
81
82
83
84
85
86
87
def ConvertVariable(name, value):
  """Converts a given variable to Haskell code.

  @param name: the Python name
  @param value: the value
  @return: a list of Haskell code lines

  """
  lines = []
  hs_name = NameRules(name)
88
  hs_typeval = HaskellTypeVal(value)
89
90
  if not CONSTANT_RE.match(name):
    lines.append("-- Skipped %s, not constant" % name)
91
92
93
  elif hs_typeval is not None:
    # this is a simple value
    (hs_type, hs_val) = hs_typeval
94
    lines.append("-- | Converted from Python constant %s" % name)
95
96
    lines.append("%s :: %s" % (hs_name, hs_type))
    lines.append("%s = %s" % (hs_name, hs_val))
97
98
99
100
101
  elif isinstance(value, dict):
    if value:
      lines.append("-- Following lines come from dictionary %s" % name)
      for k in sorted(value.keys()):
        lines.extend(ConvertVariable(DictKeyName(name, k), value[k]))
102
103
104
105
106
107
108
109
110
111
  elif isinstance(value, tuple):
    tvs = [HaskellTypeVal(elem) for elem in value]
    if compat.all(e is not None for e in tvs):
      ttypes = ", ".join(e[0] for e in tvs)
      tvals = ", ".join(e[1] for e in tvs)
      lines.append("-- | Converted from Python tuple %s" % name)
      lines.append("%s :: (%s)" % (hs_name, ttypes))
      lines.append("%s = (%s)" % (hs_name, tvals))
    else:
      lines.append("-- Skipped tuple %s, cannot convert all elements" % name)
112
113
114
115
116
  else:
    lines.append("-- Skipped %s, %s not handled" % (name, type(value)))
  return lines


117
118
119
120
121
122
123
124
125
126
def Convert():
  """Converts the constants to Haskell.

  """
  lines = [""]

  all_names = dir(constants)

  for name in all_names:
    value = getattr(constants, name)
127
    lines.extend(ConvertVariable(name, value))
128
129
130
131
132
133
134
135
136
137
138
    lines.append("")

  return "\n".join(lines)


def main():
  print Convert()


if __name__ == "__main__":
  main()