#!/usr/exp/bin/perl

# Put your own path to the perl binaries above.

# This perl-script generates a finite set with equality.
# Usage: mkfin 5 > f5.psf (or: perl mkfin 5 > f5.psf)
# This generates a psf module f5.psf defining a finite sort f5
# with elements 0f5, 1f5, 2f5, 3f5, 4f5.
# Files f1.psf through f25.psf are already part of the PSF-Library.

$prog_name = $0;
$prog_name =~ s+.*/++;

die "usage: $prog_name number\n" if $#ARGV!=0;

$N = $ARGV[0];

die "$prog_name: number of elements must be a positive number\n" if $N<=0;

sub nat {
	$n = shift;
	$n =~ s/./^$&/g;
	return "nat($n)";
}

$M = &nat($N);

@E = 0..$N-1;

print <<EOT;
data module f$N
  begin
    exports
      begin
	sorts f$N

	functions
EOT

foreach $I (@E) {
	print "\t  ${I}f$N : -> f$N\n";
}

print <<EOT;

	  ord : f$N -> NATURAL
	  f$N : NATURAL -> f$N
	  succ : f$N -> f$N
	  pred : f$N -> f$N
	  eq : f$N # f$N -> BOOLEAN
	  ne : f$N # f$N -> BOOLEAN
	  lt : f$N # f$N -> BOOLEAN
	  le : f$N # f$N -> BOOLEAN
	  gt : f$N # f$N -> BOOLEAN
	  ge : f$N # f$N -> BOOLEAN
      end

    imports
      Natural-Comparison, Natural-Addition, Natural-Subtraction

    variables
      x, y : -> f$N
      n : -> NATURAL

    equations
      ['] eq(x,y) = eq(ord(x),ord(y))
      ['] ne(x,y) = not(eq(ord(x),ord(y)))
      ['] lt(x,y) = lt(ord(x),ord(y))
      ['] le(x,y) = le(ord(x),ord(y))
      ['] gt(x,y) = gt(ord(x),ord(y))
      ['] ge(x,y) = ge(ord(x),ord(y))

      ['] succ(x) = f$N(ord(x)+nat(^1))
EOT

print "      ['] pred(x) = f$N(ord(x)+", &nat($N-1), ")\n\n";

foreach $I (@E) {
	print "      ['] ord(${I}f$N) = ", &nat($I), "\n";
}

print <<EOT;

      -- ['] f$N(n) = x when ord(x) = n
EOT

foreach $I (@E) {
	print "      ['] f$N(", &nat($I), ") = ${I}f$N\n";
}

print <<EOT;
      ['] f$N(n) = f$N(n - $M) when ge(n,$M) = true
  end f$N
EOT

__END__
