1#! /usr/bin/perl
2#
3# Copyright 2014, General Dynamics C4 Systems
4#
5# This software may be distributed and modified according to the terms of
6# the GNU General Public License version 2. Note that NO WARRANTY is provided.
7# See "LICENSE_GPLv2.txt" for details.
8#
9# @TAG(GD_GPL)
10#
11
12$literate = 0;
13$literate = 1 if $ARGV[0] eq "-l";
14
15$prefix = $literate ? "> " : "";
16
17# read the entire input
18$/ = undef;
19$input = <STDIN>;
20
21# find the module name
22$input =~ /module\s+([A-Z][a-zA-Z0-9._]*)/m or die "no module";
23$modname = $1;
24
25# find the lists of hs-boot imports and exports
26$input =~ /{-# BOOT-IMPORTS:((\s+#?[A-Z][a-zA-Z0-9._]+(\(.*?\))?(%[a-zA-Z]+)?)*) #-}/
27    or die "no imports";
28$imports = $1;
29
30$input =~ /{-# BOOT-EXPORTS:((\s+#?[a-zA-Z][a-zA-Z0-9_']+(\(.*?\))?)*) #-}/
31    or die "no exports";
32$exports = $1;
33
34# transform the import list to import statements
35$imports =~ s/\s+/\n${prefix}import /g;
36$imports =~ s/#/{-# SOURCE #-} /g;
37$imports =~ s/%/ as /g;
38
39# create the export list
40$explist = $exports;
41$explist =~ s/\s#\w+//g;
42$explist =~ s/(\w|\))\s/\1, /g;
43
44# print the module & import statements
45print "${prefix}-- this file is automatically generated, do not edit\n";
46print "${prefix}module $modname($explist) where\n${prefix}import Prelude hiding(Word)\n$imports\n\n";
47
48$exports =~ s/#//g;
49$exports =~ s/\(.*?\)//g;
50
51# find and print all the type definitions...
52while($exports =~ / ([A-Z][a-zA-Z0-9']*)/g) {
53    $name = $1;
54
55    if (not $literate and
56        $input =~ /^((type|newtype|data|class)\s+([A-Z][a-zA-Z0-9_' ]*=>\s+)?$name\W.*?)^\S/ms)
57    {
58        print "$1";
59    } elsif ($literate and
60        $input =~ /^(> (type|newtype|data|class)\s+([A-Z][a-zA-Z0-9_' ]*=>\s+)?$name\W.*?)^> \S/ms)
61    {
62        print "$1";
63    }
64}
65
66# ...and the type signatures
67while($exports =~ / ([a-z][a-zA-Z0-9']*)/g) {
68    $name = $1;
69
70    if (not $literate and $input =~ /^($name\s+::.*?)^\S/ms) {
71        print "$1";
72    } elsif ($literate and $input =~ /^(> $name\s+::.*?)^> \S/ms) {
73        print "$1";
74    }
75}
76
77