hop-2012/server/codegen.py

112 lines
3.5 KiB
Python

## Copyright 2012 Tony Garnock-Jones <tonygarnockjones@gmail.com>.
##
## This file is part of Hop.
##
## Hop 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 3 of the License, or (at your
## option) any later version.
##
## Hop 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 Hop. If not, see <http://www.gnu.org/licenses/>.
##
import sys
try:
import json
except:
import simplejson as json
def mlify(s):
s = s.replace('-', '_')
s = s.replace(' ', '_')
return s
class MessageType:
def __init__(self, j):
self.wire_selector = j['selector']
self.selector = mlify(self.wire_selector)
self.constructor = self.selector.capitalize()
self.wire_argnames = j['args']
self.argnames = list(map(mlify, self.wire_argnames))
def format_args(self, template, separator = ', '):
return separator.join([template % (x,) for x in self.argnames])
with open("../protocol/messages.json") as f:
raw_spec = json.load(f)
copyright_stmt = '(* %s *)' % (raw_spec['copyright'])
license = '\n'.join((('(* %s *)' % (x,) if x else '') for x in raw_spec['license']))
spec = list(map(MessageType, raw_spec['definitions']))
def print_list(o, xs, sep, c):
sys.stdout.write(o)
needsep = False
for x in xs:
if needsep:
sys.stdout.write(sep)
else:
needsep = True
sys.stdout.write(x)
sys.stdout.write(c)
def print_codec():
print(copyright_stmt)
print()
print(license)
print()
print('(* WARNING: Autogenerated code. Do not edit by hand! *)')
print()
print('open Sexp')
print()
print('type t =')
for t in spec:
if t.argnames:
print(' | %s of ' % (t.constructor),)
print_list('(', ['Sexp.t' for n in t.argnames], ' * ', ')\n')
else:
print(' | %s' % t.constructor)
print(' | UNKNOWN of Sexp.t')
print()
print('let sexp_of_message m = match m with')
for t in spec:
sys.stdout.write(' | %s' % t.constructor)
if t.argnames:
print_list(' (', [n for n in t.argnames], ', ', ')')
print(' ->')
sys.stdout.write(' Arr [Sexp.litstr "%s"' % t.wire_selector)
if t.argnames:
print_list('; ', t.argnames, '; ', '')
print(']')
print(' | UNKNOWN s -> s')
print()
print('let message_of_sexp s = match s with')
for t in spec:
sys.stdout.write(' | Arr [Str label_bs')
if t.argnames:
print_list('; ', t.argnames, '; ', '')
print(('] when label_bs = Bytes.of_string "%s" ->' % t.wire_selector))
sys.stdout.write(' %s' % t.constructor)
if t.argnames:
print_list(' (', [n for n in t.argnames], ', ', ')')
print()
print(' | _ -> UNKNOWN s')
print()
for t in spec:
sys.stdout.write('let %s' % t.selector)
if t.argnames:
print_list(' (', t.argnames, ', ', ')')
sys.stdout.write(' = sexp_of_message (%s' % t.constructor)
if t.argnames:
print_list(' (', t.argnames, ', ', ')')
sys.stdout.write(')\n')
print()
if __name__ == '__main__':
print_codec()