Danish Code



#!/usr/local/bin/perl

# Danish (goes with Java, get it?)
# Tim Preston and 145 crew, 27 March 1998
# based on Daistish III++, Merlin P. D. Hughes, 8 June 1995
# $Id: da,v 1.2 1995/09/06 17:47:03 hughesm Exp hughesm $

  require "ctime.pl";

  &initialise;
  &addTypes;
  &processRCFile;
  &processParameters;

  &useFiles (@aliasFiles);
  &readAlii;

  &useFiles (@signatureFiles);
  &readSignatures;

  &useFiles (@vectorFiles);
  &readVectors;
  &useFiles ();
  &checkVectors;

  &useFiles (@axiomFiles);
  &readAxia;
  &useFiles ();
  &checkAxia;

  if ($verbose)
  {
    &reportParameters;
    &reportAlii;
    &reportSignatures;
    &reportTypes;
    &reportVectors;
    &reportAxia;
  }

  &openOutput;
  &outputVectors;
  &outputDispensers;
  &outputAxia;
  &outputMain;
  &closeOutput;

end;

# OUTPUT MODULE ---------------------------------------------------------------

sub outputMain			# Java
  # Output the mainline
{
  local ($axiom);

  print "// main code\n\n";
  print "  public static void main (String argv[]) {\n";
  print "    $DAVerb = ((argv.length > 0) && argv[0].equals( \"-verbose\"));";
  print "\n\n";

  foreach $axiom (@axia)
  {
    if ($web)
      {
        print "    if ($DAVerb) System.out.print (\"<A NAME=fail$axiom>\");\n";
      }
    print "    $DATest$axiom ();\n";
    print "    System.out.println ();\n";
  }

  print "    System.out.println (\"Summary\");\n";
  foreach $axiom (@axia)
  {
    print "    System.out.print (\"Axiom `$axiom' tested \" + $DAn$axiom + \" times\");\n";
    if ($web) 
    {
	print "    if ($DAf$axiom != 0) System.out.print (($DAVerb ? \", <A HREF=#fail$axiom>failed<\/A> \" : \", failed \") + $DAf$axiom + \" times\");\n";
    }
    else
    {
        print "    if ($DAf$axiom != 0) System.out.print (\", failed \" + $DAf$axiom + \" times\");\n";
    }
    print "    if ($DAa$axiom != 0) System.out.print (\", aborted \" + $DAa$axiom + \" times\");\n";
    print "    if ($DAg$axiom != 0) System.out.print (\", reneged \" + $DAg$axiom + \" times\");\n";
    print "    System.out.println (\".\");\n";
  }

  print "  }\n\n}\n";
}
  
sub outputAxia			# Java
  # Output axiom code
{
  local ($axiom, $var, $vars, $init, $result, $type, %globalVar);

  print "  // axiom code\n\n";
  for $axiom (@axia)
  {
    local (@localVars, %localFrom, @counts, %counter, $count, %countOf, $numCt, $ctLoc);
    $sp = "   ";
    ($vars, $init, $result, $type, $lType, $rType) = &evalEx ($exParam {$axiom}, $axiom);
    print "  private static " . &deAlias ($lType) . " $DAl$axiom;\n";
    print "  private static " . &deAlias ($rType) . " $DAr$axiom;\n";
    print "  private static int $DAn$axiom = 0, $DAf$axiom = 0, $DAa$axiom = 0, $DAg$axiom = 0;\n";
    for $var (@localVars)
    {
      $count = "$DAi" . $localFrom {$var};
      push (@counts, $count) unless $counter {$count};
      $counter {$count} = $localFrom {$var};
      $countOf {$var} = $count;
      if (!$globalVar {$var})
      {
	print "  private static " . &deAlias ($varType {$localFrom{$var}}) . " $var;\n";
	$globalVar{$var} = 1;
      }
    }
    print "\n  private static " . &deAlias ($type) . " $axiom () {\n";
    print "$vars\n" if $vars ne "";
    print "$init\n" if $init ne "";
    print "    return $result;\n  }\n\n";
    print "  private static void $DATest$axiom () {\n";
    print "    int " . join (", ", @counts) . ";\n\n" if ($#counts >= 0);
    $sp = "   ";
    for $count (@counts)
    {
      $var = $counter {$count};
      $type = $varType {$var};
      if ($web)
      {
        die "<FONT COLOR=\"#FF0022\">Fatal error<\/FONT> : No test vectors given for type `$type'!\n"
            if (!$typeVectors {$type});
      }
      else
      {
        die "Fatal error : No test vectors given for type `$type'!\n"
            if (!$typeVectors {$type});
      }
    }
    if ($#counts < 0)
    {
      @counts = ("");
    }
    for $count (@counts)
    {
      if ($count ne "")
      {
	$var = $counter {$count};
	$type = $varType {$var};
	print "$sp for ($count = 0; $count < " . $typeVectors {$type} .
	  "; ++ $count) {\n";
	$sp .= "  ";
      }
    }
    for $side ($DAl, $DAr)
    {
      local (@types, %doneType, $vector);
      for $var (@localVars)
      {
	$type = $varType {$localFrom {$var}};
	push (@types, $type) unless $doneType {$type};
	$doneType {$type} = 1;
      }
      for $type (@types)
      {
	for $i (0 .. $typeVectors {$type} - 1)
	{
	  $vector = $typeVector {$type, $i};
	  print "$sp $DAOnce$vector = false;\n" if ($vectorOnce {$vector});
	}
      }
      for $var (@localVars)
      {
	if ($var =~ /^$side/)
	{
	  $type = $varType {$localFrom {$var}};
	  $count = $countOf {$var};
	  print "$sp $var = $DADisp$type ($count);\n";
	}
      }
    }
    print "$sp ++ $DAn$axiom;\n";
    print "$sp $DAAbrt = false;\n";
    print "$sp $DARnig = false;\n";
    print "$sp if (!$axiom ()) {\n";
    print "$sp   if ($DAAbrt) {\n";
    print "$sp     ++ $DAa$axiom;\n";
    print "$sp     System.out.println (\"counting REQ failure in $axiom\");\n";
    print "$sp   }\n";
    print "$sp   else if ($DARnig) {\n";
    print "$sp     ++ $DAg$axiom;\n";
    print "$sp     System.out.println (\"counting ENS failure in $axiom\");\n";
    print "$sp   }\n";
    print "$sp   else {\n";
    print "$sp     ++ $DAf$axiom;\n";
    print "$sp     if ($DAVerb) {\n";
    print "$sp       System.out.println (\"Axiom `$axiom' failed.\");\n";
    print "$sp       System.out.println (\" Test Vectors:\");\n";
    for $count (@counts)
    {
      if ($count ne "")
      {
	$var = $counter {$count};
	$type = $varType {$var};
	print "$sp       System.out.println (\"  $var = \" + $DAName$type ($count));\n";
      }
    }
    if ($func = $printOf {$lType})
    {
      print "$sp       System.out.print (\" LHS: \");\n";
      print $seFunc {$func} ? "$sp       $DAl$axiom." . &deAlias ($func) . " ();\n" :
        "$sp       " . &deAlias ($func) . " ($DAl$axiom);\n";
      print "$sp       System.out.println ();\n";
    }
    if ($func = $printOf {$rType})
    {
      print "$sp       System.out.print (\" RHS: \");\n";
      print $seFunc {$func} ? "$sp       $DAr$axiom." . &deAlias ($func) . " ();\n" :
        "$sp       " . &deAlias ($func) . " ($DAr$axiom);\n";
      print "$sp       System.out.println ();\n";
    }
    print "$sp     }\n";
    print "$sp   }\n";
    print "$sp }\n";
    for $count (reverse @counts)
    {
      if ($count ne "")
      {
	chop $sp;
	chop $sp;
	print "$sp }\n";
      }
      if ($ctLoc eq $count)
      {
	chop $sp;
	chop $sp;
      }
    }
    print "  }\n\n";
  }
}

sub outputDispensers		# Java
  # Output vector dispenser code
  #   sets : %typeVectors {type} -- number of test vectors for a type
  #          %typeVector {type,n} -- test vectors for a type
{
  local ($vector, $type, @vectorTypes, $n);

  print "  // dispenser code\n\n";

  for $vector (@vectors)
  {
    $type = $vectorType {$vector};
    push (@vectorTypes, $type) unless $typeVectors {$type} ++;
    $typeVector {$type, $typeVectors {$type} - 1} = $vector;
  }
  for $type (@vectorTypes)
  {
    print "  private static ".&deAlias ($type) . " $DADisp$type (int $DAi" . "n) {\n";
    print "    switch ($DAi" . "n) {\n";
    $n = $typeVectors {$type};
    for $i (0 .. $n - 1)
    {
      print "      " . (($i == $n - 1) ? "default" : "case $i") .
	" : return " . $typeVector {$type, $i} . " ();\n";
    }
    print "    }\n  }\n\n";

    print "  private static String $DAName$type (int $DAi" . "n) {\n";
    print "    switch ($DAi" . "n) {\n";
    for $i (0 .. $n - 1)
    {
      print "      " . (($i == $n - 1) ? "default" : "case $i") .
	" : return \"" . $typeVector {$type, $i} . "\";\n";
    }
    print "    }\n  }\n\n";
  }
}

sub outputVectors		# Java
  # Output vector code
{
  local ($type, $vector, $vars, $init, $result);

  print "  // vector code\n\n";

  for $vector (@vectors)
  {
    $type = &deAlias ($vectorType {$vector});
    if ($vectorOnce {$vector})
    {
      print "  private static boolean $DAOnce$vector = false;\n";
      print "  private static $type $DAGlob$vector;\n";
      print "  private static $type $vector () {\n";
      print "    if (!$DAOnce$vector) {\n";
      print "      $DAGlob$vector = $DAReal$vector ();\n";
      print "      $DAOnce$vector = true;\n";
      print "    }\n  return $DAGlob$vector;\n  }\n\n";
      print "  private static $type $DAReal$vector () {\n";
    }
    else
    {
      print "  private static $type $vector () {\n";
    }
    $varNum = 0;
    $sp = "   ";
    ($vars, $init, $result) = &evalEx ($exParam {$vector});
    print "$vars\n" if $vars ne "";
    print "$init\n" if $init ne "";
    print "    return $result;\n  }\n\n";
  }

}

sub openOutput			# Java
  # Open output files
{
  open (JFILE, ">$outputFile"); #must figure how to handle multiple java imports  TP
  select (JFILE);
  print "/* Danish java code file\n";
  &reportParameters;
  print "*/\n\n";
  for $i (@javaFiles)
  {
      $i =~ s/\.java$//;
      #strip away directory name
      $myind = rindex $i, "/";
      $myi = substr $i, $myind + 1;
      print "import " . $myi. ";" . "\n\n";
  }
  print "public class tester {\n\n";
  print "  protected static boolean $DAVerb;\n";
  print "  protected static boolean $DAAbrt;\n";
  print "  protected static boolean $DARnig;\n\n";

}

sub closeOutput			# Java
  # Close output files
{
  select (STDOUT);
  close (JFILE);
}

sub evalEx			# Java
  # Returns variables, processing and result to evaluate an expression
  # This holds the majority of the Java specific work
  #   in : location, (? set $DAv,$DAl,$DAr variable || ? = axiom name)
  #   out : variables, init code, result, type, lrvars
{
  local ($loc, $setVar, $value, $vars, $init, $result, $type, @lrVars, $temp, $count, $v, $i, $r, $l, $calc, $i0, $r0, $i1, $r1, $sig, $paramN) = @_;

  $vars = "";
  $init = "";
  $result = "";
  $type = "";
  @lrVars = ();

  $value = $exParam {$loc};
  if ($value eq "(")
  {
    ($vars, $init, $result, $type) = &evalEx ($exParam {"$loc.0"});
    $result = "($result)";
  }
  elsif ($value eq "?")
  {
    ($v, $i, $r) = &evalEx ($exParam {"$loc.0"});
    $vars .= $v;
    $init .= $i;
    $l = $exParam {"$loc.1"};	# location of ':'
    $sp .= "  ";
    ($v, $i0, $r0) = &evalEx ($exParam {"$l.0"});
    $vars .= $v;
    ($v, $i1, $r1, $type) = &evalEx ($exParam {"$l.1"});
    $vars .= $v;
    chop $sp;
    chop $sp;
    if (($i0 eq "") && ($i1 eq ""))
    {
      $result = "(($r) ? ($r0) : ($r1))";
    }
    else
    {
      $temp = "$DAt" . $varNum ++;
      $vars .= "    " . &deAlias ($type) . " $temp;\n";
      $init .= "$sp if ($r) {\n$i0$sp   $temp = $r0;\n$sp }\n";
      $init .= "$sp else {\n$i1$sp   $temp = $r1;\n$sp }\n";
      $result = $temp;
    }
  }
  elsif ($isInfix {$value})
  {
    $DAv = $DAl if $setVar;
    $sig = $exParam {"$loc.s"};
    ($v, $i, $r, $type) = &evalEx ($exParam {"$loc.0"});
    $vars .= $v;
    $init .= $i;
    if ($setVar)
    {
      $init .= "$sp $DAv$setVar = $r;\n";
      $r = "$DAv$setVar";
      push (@lrVars, $type);
    }
    $result = "($r " . &deAlias ($value);
    $DAv = $DAr if $setVar;
    ($v, $i, $r, $type) = &evalEx ($exParam {"$loc.1"});
    $vars .= $v;
    $init .= $i;
    if ($setVar)
    {
      $init .= "$sp $DAv$setVar = $r;\n";
      $r = "$DAv$setVar";
      push (@lrVars, $type);
    }
    $result .= " $r)";
    $type = $funcType {$value, $sig};
  }
  elsif ($isFunc {$value})
  {
    $DAv = $DAl if $setVar;
    $sig = $exParam {"$loc.s"};
    if ($seFunc {$value, $sig})
    {
      $calc = "";
      if ($funcSeParam {$value, $sig} < 0)
      {
        $temp = "$DAt" . $varNum ++;
        $result = $temp;
	$vars .= "    " . &deAlias ($funcType {$value, $sig}) . " $temp;\n";
      }
      if ($exParam {"$loc.n"} >= 0)
      {
	$calc .= " (";
	$count = 0;
	for $paramN (0 .. $exParam {"$loc.n"} - 1)
	{
	  ($v, $i, $r, $type) = &evalEx ($exParam {"$loc.$paramN"});
	  $vars .= $v;
	  $init .= $i;
	  if ($setVar)
	  {
	    $init .= "$sp $DAv$setVar = $r;\n";
	    $r = "$DAv$setVar";
	    push (@lrVars, $type);
	  }
	  if ($paramN == $funcSeParam {$value, $sig})
	  {
	    if (&simpleVar ($r))
	    {
	      $result = $r;
	    }
	    else
	    {
	      $temp = "$DAt" . $varNum ++;
	      $result = $temp;
	      $vars .= "    " . &deAlias ($funcType {$value, $sig}) . " $temp;\n";
	      $init .= "$sp $temp = $r;\n";
	    }
	  }
	  else
	  {
	    $calc .= ", " if $count ++;
	    $calc .= $r;
	  }
	  $DAv = $DAr if $setVar;
	}
	$calc .= ")";
      }
      $init .= "$sp $result." . &deAlias ($value) . "$calc;\n";
    }
    else
    {
      $result = &deAlias ($value);
      if ($exParam {"$loc.n"} >= 0)
      {
	$result .= " (";
	$count = 0;
	for $paramN (0 .. $exParam {"$loc.n"} - 1)
	{
	  if ($setVar && ($value eq "not")) # not at root
	  {
	    ($v, $i, $r, $type, @lrVars) = &evalEx ($exParam {"$loc.$paramN"}, $setVar );
	  }
	  else
	  {
	    ($v, $i, $r, $type) = &evalEx ($exParam {"$loc.$paramN"});
	  }
	  $vars .= $v;
	  $init .= $i;
	  if ($setVar && ($value ne "not")) # not at root
	  {
	    $init .= "$sp $DAv$setVar = $r;\n";
	    $r = "$DAv$setVar";
	    push (@lrVars, $type);
	  }
	  if ($paramN == $funcSeParam {$value, $sig})
	  {
	    # It may be worth assigning $r to a temp variable if it is non-simple.
	    $result = "($r).$result";
	  }
	  else
	  {
	    $result .= ", " if $count ++;
	    $result .= $r;
	  }
	  $DAv = $DAr if $setVar;
	}
	$result .= ")";
      }
    }
    $type = $funcType {$value, $sig};
  }
  elsif ($isVector {$value})
  {
    $result = "$value ()";
    $type = $vectorType {$value};
  }
  elsif ($isVar {$value})
  {
    $result = $exParam {"$loc'"} ? "$DAv" . $exParam {"$loc'"} . "_$value" : "$DAv$value";
    $type = $varType {$value};
    push (@localVars, $result) unless $localFrom {$result};
    $localFrom {$result} = $value;
  }
  elsif ($isType {$value})
  {
    ($v, $i, $result) = &evalEx ($exParam {"$loc.0"});
    $vars .= $v;
    $init .= $i;
  }
  elsif ($type = &constType ($value))
  {
    $result = $value;
  }
  else
  {
    &exitError ("Catastrophic eval failure with `$value' at `$loc'; contact the author.");
  }

  ($vars, $init, $result, $type, @lrVars);
}

sub deAlias
  # Return an unaliased alias if it is an alias
{
  local ($i) = @_;
  $isAlias {$i} ? $aliasOf {$i} : $i;
}

sub simpleVar
  # Returns whether or not the parameter is a simple variable ($DAt\d+)
  #   in : exp
  #   out : true/false
{
  local ($i) = @_;
  return ($i =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/);
}

sub reportAxia
  # Reports current axia
{
  local ($axiom);

  print "Axia : " . join (", ", @axia) . "\n";
  foreach $axiom (@axia)
  {
    print "  " . $axiom . " " . &exReport ($exParam {$axiom}) . "\n";
  }
}

sub reportVectors
  # Reports current vectors
{
  local ($vector);

  print "Vectors : " . join (", ", @vectors) . "\n";
  foreach $vector (@vectors)
  {
    print "  " . $vectorType {$vector} . " " . $vector . " " . &exReport ($exParam {$vector}) . "\n";
  }
}

sub reportSignatures
  # Reports current signatures
{
  local ($sig, $func, $type, $p0, $p1);

  print "Signatures : " . join (", ", sort @funcs) . "\n";
  foreach $func (sort @funcs)
  {
    foreach $sig (split (/;/, $funcSigs {$func}))
    {
      $type = $funcType {$func, $sig};
      print $seFunc {$func, $sig} ? "  {$type} $func " : "  $type $func ";
      print &signatureOf ($sig, $funcSeParam {$func, $sig}) . "\n";
    }
  }
  foreach $func (@infex)
  {
    foreach $sig (split (/;/, $funcSigs {$func}))
    {
      ($p0, $p1) = split (/,/, $sig);
      print "  " . $funcType {$func, $sig} . " $p0 $func $p1)\n";
    }
  }
}

sub reportTypes
  # Reports current types
{
  local ($type, $print);

  print "Types : " . join (", ", sort @types) . "\n";
  foreach $type (sort @types)
  {
    $print = $printOf {$type};
    print "  $type : " . ($seFunc {$print} ? "{$print}" : $print) . "\n"
      if $print;
  }
}

sub reportParameters
  # Reports parameters
{
  print "Output : " . $outputFile . "\n";
  print "Java code : " . join (",", @javaFiles) . "\n";
  print "Alii : " . join (",", @aliasFiles) . "\n";
  print "Signatures : " . join (",", @signatureFiles) . "\n";
  print "Test Vectors : " . join (",", @vectorFiles) . "\n";
  print "Axia : " . join (",", @axiomFiles) . "\n";
}

sub reportAlii
  # Reports current alii
{
  print "Aliases : " . join (", ", sort @alii) . "\n";
  foreach $alias (sort @alii)
  {
    print "  " . $alias . " ";
    print ($isAlias {$alias} ? "=" : "#");
    print " " . $aliasOf {$alias} . "\n";
  }
}

sub syntaxError
  # Reports syntax error and exits
{
  die "Syntax: danish {-o  | -j  |" .
      " -a  | -s  | -v  | -web | -dump |" .
      " }\n";
}

sub exitError
  # Report error and exit
{
  die &fileDetails . @_[0] . "\n";
}

sub fileDetails
  # Returns current file, line number, symbols, current object
  #   out: $fileName . $fileLine . $_ . $currentObject
{
  chop;
  if ($web)
  {
      "<FONT COLOR=\"#FF0022\">Parse failure<\/FONT>" . ($fileName ne "NIL" ? " in file `$fileName', line $fileLine" : "") . ($_ ? ", at `$_'" : "") . ($currentObject ? " with $currentObject" : "") . ".\n";
  }
  else
  {
      "Parse failure" . ($fileName ne "NIL" ? " in file `$fileName', line $fileLine" : "") . ($_ ? ", at `$_'" : "") . ($currentObject ? " with $currentObject" : "") . ".\n";
  }

}

sub exReport
  # Returns an ascii expression
  #   in : location
  #   out : string
{
  local ($loc, $notify, $value, $paramN, $ret, $arrow) = @_;

  $value = $exParam {$loc};
  $arrow = ($loc eq $notify) ? " ----> " : "";
  if ($value eq "(")
  {
    $ret = "$arrow(" . &exReport ($exParam {"$loc.0"}, $notify) . ")";
  }
  elsif ($isInfix {$value})
  {
    $ret = &exReport ($exParam {"$loc.0"}, $notify) . " $arrow$value " .
      &exReport ($exParam {"$loc.1"}, $notify);
  }
  elsif ($isFunc {$value})
  {
    $ret = "$arrow$value";
    if ($exParam {"$loc.n"} >= 0)
    {
      $ret .= " (";
      for $paramN (0 .. $exParam {"$loc.n"} - 1)
      {
	$ret .= ", " if ($paramN > 0);
	$ret .= &exReport ($exParam {"$loc.$paramN"}, $notify);
      }
      $ret .= ")";
    }
  }
  elsif ($isType {$value})
  {
    $ret = "$arrow$value (" . &exReport ($exParam {"$loc.0"}, $notify) . ")";
  }
  elsif ($isVar {$value})
  {
    $ret = "$arrow$value" . ("'" x $exParam {"$loc'"});
  }
  else
  {
    $ret = "$arrow$value";
  }

  $ret;
}

sub signatureOf
  # Returns a textual signature
  #   out: text signature
{
  local ($sig, $se, @types) = @_;

  $se = -1 if $se eq "";
  $sig =~ s/^\(//;
  @types = split (/,/, $sig);
  $types[$se] = "{" . $types[$se] . "}" if ($se >= 0);
  ($sig ne "!") ? "(" . join (", ", @types) . ")" : "";
}

###################################################
##   Once input files are read and checked, the following arrays are set:
##      (associative arrays called by $the_array{key})
##      (side-effect function is one that is called by class.function() )
## @alii         - list of arrays
## %isAlias      - contains 1 if key is an alias 
## %aliasOf      - contains replacement of key
## @types        - list of variable types
## %isType       - contains 1 if key is a variable type
## @vectors      - list of test vectors
## %isVector     - contains 1 if key is a test vector
## %vectorType   - contains variable type of test vector key
## %exParam      - contains expression for test vector or axiom key
## %vectorOnce   - contains 1 if key is a 'resolve-once' test vector
## @funcs        - list of function names in signature file
## %isFunc       - contains 1 if key is a function name 
## %seFunc       - contains 1 if function signature key is a side effect func
## %funcType     - conatins return value type of function signature key
## %funcSeParam  - contains side-effect parameter of function signature key
## %funcSigs     - contains signature of function key
## %printOf      - contains print function of type key
## @infix        - list of infix functions (functions between basic types)
## %isInfix      - conatins 1 if key is an infix function
## @vars         - list of variables 
## %isVar        - contains 1 if key is a variable
## %varType      - contains type of variable key
## @axia         - list of axia
## %isAxiom      - contains 1 if key is an axiom
##
## The following function is also useful
##
## &constType    - returns variable type of whatever it is passed
###################################################

# READ AND CHECK INPUT FILES MODULE -------------------------------------------

sub useFiles
  # Start using a new set of files
  #   out: file list
{
  @fileList = @_;
  $fileName = "NIL";
  &getLine;
  while (s/--.*$//) {}
}

sub getLine
  # Reads a new line from the current fileList
{
  if (($fileName eq "NIL") || eof)
  {
    local ($name);
    
    close (FILE) if $fileName ne "NIL";
    if ($name = shift (@fileList))
    {
      $fileName = $name;
      $fileLine = 0;
      if ($web)
      {
        die "<FONT COLOR=\"#FF0022\">Cannot open file `$fileName'.<\/FONT>\n" unless open (FILE, $fileName);
      }
      else
      {
        die "Cannot open file `$fileName'.\n" unless open (FILE, $fileName);
      }
      $eof = 0;
    }
    else
    {
      $fileLine = "EOF";
      $eof = 1;
    }
  }
  ++ $fileLine if !$eof;
  $_ = ;
}

sub readAlii
  # Read alii
  #   sets: %isAlias, %aliasOf, @alii
{
  local ($aliasName, $aliasDefn);

  $currentTask = "Reading alii.";
  while (&nextSymbol)
  {
    $currentObject = "";
    &exitError ("Expecting an alias name.") unless $aliasName = &pullIdentifier;
    $currentObject = "`$aliasName'";
    &exitError ("Duplicate alias `$aliasName'.") if $isAlias {$aliasName};
    &nextSymbol;
    &exitError ("Expecting an alias definition.") unless ($aliasDefn = &pullAlias) ne "";
    $aliasDefn = "" if $aliasDefn eq "{}";
    $isAlias {$aliasName} = 1;
    $aliasOf {$aliasName} = $aliasDefn;
    push (@alii, $aliasName);
  }
  $currentObject = "";
  $currentTask = "";
}

sub readSignatures
  # Read signatures
  #   sets: %isType, @types, %isFunc, @funcs, %funcSigs{func}, %funcType{sig}
  #     %funcType{sig}, -- function return value
  #     %seFunc{sig}, -- does it return by side effect
  #     %funcSeParam{sig}, -- which parameter is a side effect parameter (or -1)
  #     %printOf{type} -- name of print function for type
{
  local ($funcRet, $funcName, $funcSig, $typeName, $isSe, $param, $paramN, $type, $seParam, $sig);

  $currentTask = "Reading signatures.";
  while (&nextSymbol)
  {
    local (@typeList);

    $currentObject = "";
    &exitError ("Expecting a signature return type.") unless $funcRet = &pullType;
    $isSe = $funcRet =~ s/^\{(.*)\}$/\1/;
    &exitError ("Type name `$funcRet' is already a function.") if $isFunc {$funcRet};
    &nextSymbol;
    &exitError ("Expecting a signature function name.") unless $funcName = &pullIdentifier;
    $currentObject = "`$funcName'";
    &exitError ("Function name `$funcName' is already a type.") if $isType {$funcName};
    push (@funcs, $funcName) unless $isFunc {$funcName};
    $isFunc {$funcName} = 1;
    if ($funcRet ne "")
    {				# genuine function
      &nextSymbol;
      &exitError ("Return type must be non-wild.") if ($funcRet eq "*");
      &exitError ("Function name `$funcRet' used as a type.") if $isFunc {$funcRet};
      $seParam = -1;
      $currentObject .= " parameters";
      $funcSig = "!";
      if (s/^\(//)
      {
	local ($isSe);

	$paramN = 0;
	&nextSymbol;
	while (!/^\)/)
	{
	  if ($paramN > 0)
	  {
	    &exitError ("Missing type-separating comma.") unless s/^,//;
	    &nextSymbol;
	  }
	  &exitError ("Expecting type name.") unless $param = &pullType;
	  $isSe = $param =~ s/^\{(.*)\}$/\1/;
	  &exitError ("Parameter type must be non-nil.") if ($funcRet eq "");
	  &exitError ("Function name `$param' used as a type.") if $isFunc {$param};
	  push (@typeList, $param);
	  if ($isSe)
	  {
	    &exitError ("More then one side-effect parameter with `$param'.")
	      if ($seParam >= 0);
	    &exitError ("Side-effect parameter type `$param' does not match return type.")
	      if $seFunc {$funcName} && ($param ne $funcRet);
	    $seParam = $paramN;
	  }
	  &nextSymbol;
	  ++ $paramN;
	}
	&exitError ("Missing type list terminating parenthesis.") unless s/^\)//;
	$funcSig = "(" . join (",", @typeList);
      }
      for $type (@typeList)
      {
	push (@types, $type) unless $isType {$type} || ($type eq "*");
	$isType {$type} = 1 unless ($type eq "*");
      }
      $sig = &matchSig ($funcSigs {$funcName}, $funcSig);
      &exitError ("There is already a `$funcName' function with a compatible signature. It looks like `" . &signatureOf ($sig) . "', this looks like `" . &signatureOf ($funcSig) . "'

.")
	if $sig;
      $funcSigs {$funcName} .= ";" if $funcSigs {$funcName};
      $funcSigs {$funcName} .= $funcSig;
      $funcType {$funcName, $funcSig} = $funcRet;
      $seFunc {$funcName, $funcSig} = $isSe;
      $funcSeParam {$funcName, $funcSig} = $seParam;
    }
    else
    {				# printing function
      &nextSymbol;
      &exitError ("Missing type list introductory parenthesis.") unless s/^\(//;
      &nextSymbol;
      &exitError ("Expecting type name.") unless $typeName = &pullType;
      $isSe = $typeName =~ s/^\{(.*)\}$/\1/;
      &exitError ("Printing functions require a non-wild non-nil type parameter.")
	if ($typeName eq "") || ($typeName eq "*");
      &exitError ("Function name `$typeName' used as a type.") if $isFunc {$typeName};
      &nextSymbol;
      &exitError ("Missing type list terminating parenthesis.") unless s/^\)//;
      &exitError ("There is already a printing function for type `$typeName'.")
	if $printOf {$typeName};
      $printOf {$typeName} = $funcName;
      push (@types, $typeName) unless $isType {$typeName};
      $isType {$typeName} = 1;
      $seFunc {$funcName} = $isSe;
    }
  }
  $currentObject = "";
  $currentTask = "";
}

sub readVectors
  # Read test vectors
  #   sets : %isVector, %vectorOnce, @vectors
  #     %exParam {name.0.1.2.3}
{
  local ($vector, $vectorOnce, $vectorRoot);

  $currentTask = "Reading vectors.";
  while (&nextSymbol)
  {
    $currentObject = "";
    &exitError ("Expecting a vector name.") unless $vector = &pullVectorName;
    $onceVector = $vector =~ s/^\{(.*)\}$/\1/;
    $currentObject = "`$vector'";
    &exitError ("Vector name `$vector' is already a function name.") if $isFunc {$vector};
    &exitError ("Vector name `$vector' is already a type name.") if $isType {$vector};
    &exitError ("Vector name `$vector' is already in use.") if $isVector {$vector};
    $isVector {$vector} = 1;
    $vectorOnce {$vector} = $onceVector;
    push (@vectors, $vector);
    &nextSymbol;
    $exParam {$vector} = &getEx ("V"); # expression is for a vector
  }
  $currentObject = "";
  $currentTask = "";
}

sub checkVectors
  # Checks all vector type sanities
  #   sets : %vectorType {name}
{
  local ($vector);

  $currentTask = "Checking vectors.";
  for $vector (@vectors)
  {
    &vectorCheck ($vector);
  }
  $currentObject = "";
  $currentTask = "";
}

sub vectorCheck
  # Checks vector type sanity
  #   in : vector name
  #   out : vector type
  #   sets : %vectorType {name}
  #     %vectorInUse {name} -- vector is in use
  #     %vectorDone {name} -- vector is done
{
  local ($vector, $type) = @_;

  if (!$vectorDone {$vector})
  {
    &exitError ("Vector `$vector' used recursively.") if ($vectorInUse {$vector});
    $vectorInUse {$vector} = 1;

    $currentObject = "test vector `$vector'";
    $vectorType {$vector} = &vectorParamCheck ($exParam {$vector});

    $vectorInUse {$vector} = 0;
    $vectorDone {$vector} = 1;
  }
  $vectorType {$vector};
}

sub vectorParamCheck
  # Checks type sanity of parameters within test vector
  #   in : vector parameter location (name.0.1.2)
  #   out : type at parameter location
{
  local ($place, $ternOk, $func, $type, $type2, $paramN, $save, $test) = @_;

  $func = $exParam {$place};
  if ($func eq "(")
  {
    $type = &vectorParamCheck ($exParam {"$place.0"});
  }
  elsif ($func eq "?")
  {
    $test = $exParam {"$place.0"};
    $type = &vectorParamCheck ($test);
    &exitError (&exReport ($exParam {$vector}, $test) .
		"\nType of `" . $exParam {$test} . "' ($type) does not match " .
		"boolean required by `?' operator.")
      unless ($type eq "boolean");
    &exitError (&exReport ($exParam {$vector}, $exParam {"$place.1"}) .
		"\nMissing ternary separator `:' following `?' operator.")
      unless $exParam {$exParam {"$place.1"}} eq ":";
    $type = &vectorParamCheck ($exParam {"$place.1"}, 1);
  }
  elsif ($func eq ":")
  {
    &exitError (&exReport ($exParam {$vector}, $place) .
		"\nUnexpected ternary separator `:' encountered.") unless $ternOk;
    $type = &vectorParamCheck ($exParam {"$place.0"}, 1);
    $type2 = &vectorParamCheck ($exParam {"$place.1"}, 1);
    &exitError (&exReport ($exParam {$vector}, $place) .
		"\nType of RHS of `:' operator does not match type of LHS.")
      unless ($type eq $type2);
  }
  elsif ($isFunc {$func} || $isInfix {$func})
  {
    local (@typeList, $sig, $funcSig);
    
    $sig = "!";
    if ($exParam {"$place.n"} >= 0)
    {
      for $paramN (0 .. $exParam {"$place.n"} - 1)
      {
	$test = $exParam {"$place.$paramN"};
	push (@typeList, &vectorParamCheck ($test));
      }
      $sig = "(" . join (",", @typeList);
    }
    &exitError (&exReport ($exParam {$vector}, $place) .
		"\nNo signature for function `$func' matches `" . &signatureOf ($sig) . "'.")
      unless $funcSig = &matchSig ($funcSigs {$func}, $sig);
    $type = $funcType {$func, $funcSig};
    $exParam {"$place.s"} = $funcSig;
  }
  elsif ($isVector {$func})
  {
    $save = $currentObject;
    $type = &vectorCheck ($func);
    $currentObject = $save;
  }
  elsif ($isType {$func})
  {
    &vectorParamCheck ($exParam {"$place.0"});
    $type = $func;
  }
  else
  {
    &exitError ("Unknown variable `$func' used in test vector.")
      unless $type = &constType ($func);
  }

  $type;
}

sub readAxia
  # Read axia
  #   sets : %isAxiom, @axia, $globAx, %exParam {name}
{
  local ($axiom, $axiomRoot, %primed);

  $currentTask = "Reading axia.";
  while (&nextSymbol)
  {
    &exitError ("Expecting an axiom name.") unless $axiom = &pullIdentifier;
    $currentObject = $axiom;
    &exitError ("Axiom name `$axiom' is already a type name.") if $isType {$axiom};
    &exitError ("Axiom name `$axiom' is already a function name.")
      if $isFunc {$axiom};
    &exitError ("Axiom name `$axiom' is already in use.") if $isAxiom {$axiom};
    &exitError ("Axiom name `$axiom' is already a vector name.") if $isVector {$axiom};
    &exitError ("Axiom name `$axiom' is already a variable name.") if $isVar {$axiom};
    $isAxiom {$axiom} = 1;
    push (@axia, $axiom);
    &nextSymbol;
    %primed = ();
    $exParam {$axiom} = &getEx ("A"); # expression is for an axiom
  }
  $currentObject = "";
  $currentTask = "";
}

sub checkAxia		# Java - bool, ? :
  # Checks current axia for type, infix sanity
  #   sets : @vars, %isVar {var}, %varType {var}
{
  local ($axiom, $root, $loc, $func);

  $currentTask = "Checking axia.";

  foreach $i (@vars)
  {
    &exitError ("Type of variable `$i' not specified.")
      unless $varType {$i};
  }

  foreach $axiom (@axia)
  {
    $currentObject = "axiom `$axiom'";
    $loc = $root = $exParam {$axiom};
    $func = $exParam {$root};
    if ($func eq "not")		# not at root
    {
      $loc = $exParam {"$root.0"};
      $func = $exParam {$loc};
    }
    &exitError ("Root of axiom must be an optionally negated binary function.")
      unless (($isFunc {$func} && ($exParam {"$loc.n"} == 2)) ||
	      ($isInfix {$func} && ($func ne "?") && ($func ne ":")));
    &exitError ("Root of axiom must be a boolean function.")
      unless &axiomCheck ($axiom, $root) eq "boolean";
  }
}

sub axiomCheck			# Java - bool, ? :
  # Checks axiom for sanity
  #   in : axiom name, subaxiom location, desired type, ternary ':' acceptability
  #   out : type
  #   sets : $processing - set a variable type
{
  local ($axiom, $loc, $ternOk, $type, $looseType, $value, $paramN, @typeList, $sig, $funcSig) = @_;

  $value = $exParam {$loc};

  if ($value eq "(")
  {
    $type = &axiomCheck ($axiom, $exParam {"$loc.0"});
  }
  elsif ($value eq "?")
  {
    &exitError (&exReport ($exParam {$axiom}, $loc) .
		"\nCondition of ternary `?' must have type `boolean'.")
      unless &axiomCheck ($axiom, $exParam {"$loc.0"}) eq "boolean";
    &exitError (&exReport ($exParam {$axiom}, $loc) .
		"\nMissing ternary separator ':' following '?' operator.")
      unless $exParam {$exParam {"$loc.1"}} eq ":";
    $type = &axiomCheck ($axiom, $exParam {"$loc.1"}, 1);
  }
  elsif ($value eq ":")
  {
    &exitError (&exReport ($exParam {$axiom}, $loc) .
		"\nUnexpected ternary separator `:' encountered.") unless $ternOk;
    $type = &axiomCheck ($axiom, $exParam {"$loc.0"});
    $looseType = &axiomCheck ($axiom, $exParam {"$loc.1"});
    &exitError (&exReport ($exParam {$axiom}, $loc) .
	     "\nLHS (`$type') and RHS (`$looseType') of ternary `:' must have same types.")
      unless $looseType eq $type;
  }
  elsif ($isFunc {$value} || $isInfix {$value})
  {
    $sig = "!";
    if ($exParam {"$loc.n"} >= 0)
    {
      for $paramN (0 .. $exParam {"$loc.n"} - 1)
      {
        push (@typeList, &axiomCheck ($axiom, $exParam {"$loc.$paramN"}));
      }
      $sig = "(" . join (",", @typeList);
    }
    &exitError (&exReport ($exParam {$axiom}, $loc) .
	     "\nNo signature for function `$value' matches `" . &signatureOf ($sig) . "'.")
      unless $funcSig = &matchSig ($funcSigs {$value}, $sig);
    $type = $funcType {$value, $funcSig};
    $exParam {"$loc.s"} = $funcSig;
  }
  elsif ($isType {$value})
  {
    &axiomCheck ($axiom, $exParam {"$loc.0"});
    $type = $value;
  }
  elsif ($isVar {$value})
  {
    $type = $varType {$value};
  }
  else
  {
    &exitError (&exReport ($exParam {$axiom}, $loc) .
		"\naxiomCheck sanity error with `$value', contact the author!")
      unless ($type = &constType ($value));
  }

  $type;
}

sub getEx
  # Reads an expression
  #   in : type; "A" = axiom, "V" = vector
  #   out : root location
  #   sets : $globAx, %exParam {loc}
{
  local ($ex, $loc, $inLoc, $value, $paramN, $inFunc, $type, $prime) = @_;

  $loc = $globAx ++;

  if (s/^\(//)
  {
    $exParam {$loc} = "(";
    &nextSymbol;
    $exParam {"$loc.0"} = &getEx ($ex);
    &nextSymbol;
    &exitError ("Missing closing parenthesis.") unless s/^\)//;
  }
  else
  {
    &exitError ("Expecting an expression.") unless ($value = &pullSymbol) ne "";
    &exitError ("Not expecting an axiom name (`$value') here.") if $isAxiom {$value};
    &exitError ("Not expecting a vector name (`$value') here.")
      if ($ex eq "A") && $isVector {$value};
    $exParam {$loc} = $value;
    if ($isFunc {$value})
    {
      $paramN = -1;
      &nextSymbol;
      if (s/^\(//)
      {
	&nextSymbol;
	$paramN = 0;
	while (!/^\)/)
	{
	  if ($paramN > 0)
	  {
	    &exitError ("Missing parameter-separating comma.") unless s/^,//;
	    &nextSymbol;
	  }
	  $exParam {"$loc.$paramN"} = &getEx ($ex);
	  &nextSymbol;
	  ++ $paramN;
	}
	&exitError ("Missing closing parenthesis.") unless s/^\)//;
      }
      $exParam {"$loc.n"} = $paramN;
    }
    elsif ($isType {$value})
    {
      &nextSymbol;
      if (s/^\(//)
      {
	&nextSymbol;
	$exParam {"$loc.0"} = &getEx ($ex);
	&nextSymbol;
	&exitError ("Missing closing parenthesis.") unless s/^\)//;
      }
      else
      {
	&exitError ("Not expecting a type specification (`$value') here.") if ($ex eq "V");
	$type = $value;
	&exitError ("Expecting a variable name for type specification.") unless $value = &pullIdentifier;
	&exitError ("Not expecting an axiom name (`$value') here.") if $isAxiom {$value};
	&exitError ("Not expecting a vector name (`$value') here.") if $isVector {$value};
	&exitError ("Not expecting a function name (`$value') here.") if $isFunc {$value};
	&exitError ("Not expecting a type name (`$value') here.") if $isType {$value};
	push (@vars, $value) unless $isVar {$value};
	$isVar {$value} = 1;
	&exitError ("Conflicting type `$type' for variable `$value', was " .
		    $varType {$value} . ".")
	  if $varType {$value} && ($varType {$value} ne $type);
	$varType {$value} = $type;
	$exParam {$loc} = $value;
	&nextSymbol;
#	$prime = 0; # primes
#	while (s/^\'//)
#	{
#	  ++ $prime;
#	  &nextSymbol;
#	}
	$exParam{"$loc'"} = ++ $primed{$value};
	&exitError ("Name `$value' is not a known function but is used as such.")
	  if (/^\(/);
      }
    }
    else
    {
      if (($ex eq "A") && !&constType ($value))
      {
	push (@vars, $value) unless $isVar {$value};
	$isVar {$value} = 1;
      }
      &nextSymbol;
#     $prime = 0;
#     while (s/^\'//)
#     {
#       ++ $prime;
#	&nextSymbol;
#     }
      $exParam{"$loc'"} = ++ $primed{$value};
      &exitError ("Name `$value' is not a known function but is used as such.")
        if (/^\(/);
    }
  }
  &nextSymbol;
  if ($inFunc = &pullInfix)
  {
    &exitError ("Infix-like expression `$inFunc' not recognised.")
      unless $isInfix {$inFunc};
    $inLoc = $loc;
    $loc = $globAx ++;
    $exParam {$loc} = $inFunc;
    $exParam {"$loc.0"} = $inLoc;
    &nextSymbol;
    $exParam {"$loc.1"} = &getEx ($ex);
    $exParam {"$loc.n"} = 2;
  }
  $loc;
}

sub matchSig
  # Returns a matching signature from a signature list with a signature
  #   in : signature list, signature
  #   out : signature or "?"
{
  local ($sigs, $test, $sig, $tmp, @sigList, @typeList, $match, $ret) = @_;

  $ret = "";
  if ($sigs)
  {
    $test =~ s/^\(//;
    @typeList = split (/,/, $test);
    for $sig (split (/;/, $sigs))
    {
      $tmp = $sig;
      $tmp =~ s/^\(//;
      @sigList = split (/,/, $tmp);
      $match = ($#sigList == $#typeList);
      if ($match)
      {
	for $i (0 .. $#sigList)
	{
	  $match &= ($typeList[$i] eq "*") || ($sigList[$i] eq "*") ||
	    ($typeList[$i] eq $sigList[$i]);
	}
	$ret = $sig if $match;
      }
    }
  }

  $ret;
}

sub nextSymbol
  # Go to start of next symbol
  #   out: not EOF
{
  for (s/^\s+//; !$_ && !$eof; s/^\s+//)
  {
    &getLine;
    while (s/--.*$//) {}
  }
  !$eof;
}

sub pullIdentifier
  # Return an identifier symbol
  #   out: identifier word or ""
{
  s/^([a-zA-Z_][a-zA-Z0-9_]*)// ? $1 : "";
}

sub pullSymbol
  # Return an identifier or constant symbol
  #   out: identifier word or ""
{
  s/^([a-zA-Z0-9_]+|-[0-9]+|\"[^\"]*\"|\'[^\']*\')// ? $1 : "";	# "
}

sub pullType
  # Return a type symbol
  # Valid sequences are * ident {} {*} {ident}
  #   out: identifier word or ""
{
  s/^(\*|[a-zA-Z_][a-zA-Z0-9_]*|\{\}|\{\*\}|\{[a-zA-Z_][a-zA-Z0-9_]*\})// ? $1 : "";
}

sub pullVectorName
  # Return a vector name
  # Valid sequences are ident {ident}
  #   out: name or ""
{
  s/^([a-zA-Z_][a-zA-Z0-9_]*|\{([a-zA-Z_][a-zA-Z0-9_]*)\})// ? $1 : "";
}

sub pullAlias
  # Return an alias definition
  # Valid sequences are to EOL
  #   out: alias or ""
{
  s/^(.*\S)\s*$// ? $1 : "";
}

sub pullInfix
  # Return an infix name
  # Vald sequences are $infixSearch+
  #   out : name or ""
{
  s/^([$infixSearch]+)// ? $1 : "";
}

sub constType			# Java
  # Return the type of a constant
  #   in : symbol
  #   out : constant type of symbol
{
  local ($const, $ret) = @_;
  $ret = "int" if $const =~ /^[0-9]+|-[0-9]+$/;
  $ret = "String" if $const =~ /^\"[^\"]*\"$/; # "
  $ret = "char" if $const =~ /^\'[^\']*\'$/;
  $ret = "boolean" if $const eq "true"; #better way of combining these? TP
  $ret = "boolean" if $const eq "false";
  $ret;
}

# INITIALIZATION MODULE -------------------------------------------------------

sub initialise
  # Initialise global state
{
  $verbose = 0;
  $web = 0;
  $lineNumber = "NIL";
  $eof = 0;
  $fileName = "NIL";
  @fileList = ();
  $currentTask = "init";
  $currentObject = "world";
  $outputFile = "";
  @javaFiles = ();
  @aliasFiles = ();
  @signatureFiles = ();
  @vectorFiles = ();
  @axiomFiles = ();
  $parameterString = join (" ", @ARGV);
  $globAx = 1;
  $threshold = 512;

  $DAOnce = "DA_Once_";
  $DAGlob = "DA_Glob_";
  $DAReal = "DA_Real_";
  $DADisp = "DA_Disp_";
  $DAName = "DA_Name_";
  $DATest = "DA_Test_";
  $DAVerb = "DA_Verbose";
  $DAAbrt = "DA_Abort";
  $DARnig = "DA_Reneg";
  $DAt = "DA_t_";
  $DAi = "DA_i_";
  $DAl = "DA_l_";
  $DAr = "DA_r_";
  $DAn = "DA_n_";		      # number tried
  $DAf = "DA_f_";		      # number failed
  $DAa = "DA_a_";		      # number aborted
  $DAg = "DA_g_";		      # number reneged
}

sub addTypes			# Java
  # Add basic types
  #   set @types, %isType, @alii, %isAlias, %aliasOf, %isFunc, @funcs, %seFunc,
  #     %funcType, %funcSeParam, %funcParams{name}, @infix, %isInfix, $infixSearch
{
  &typeAdd ("int");
  &typeAdd ("String");
  &typeAdd ("char");
  &typeAdd ("boolean");
#  &aliasAdd ("bool", "int");
#  &aliasAdd ("string", "char *");
#  &constAdd ("true", "bool", "1");
#  &constAdd ("false", "bool", "0");
  &func1Add ("not", "boolean", "!", "boolean");
  &fixIn ("boolean", "*", "==", "!=");
  &fixIn ("boolean", "boolean", "&&", "||", "^^");
  &fixIn ("int", "int", "+", "-", "*", "/", "%");
  &fixIn ("*", "*", "?", ":");	# The ternary operator is hard wired
  $infixSearch = "\\!\\=\\&\\|\\+\\-\\*\\/\\?\\:\\^\\%"; # characters allowed in an infix op
}

sub typeAdd
  # Add types
  #   set @types, %isType
{
  local ($type) = @_;

  push (@types, $type);
  $isType {$type} = 1;
}

sub constAdd
  # Add zero parameter function with alias
  #   in : name, type, alias
  #   set @funcs, %isFunc, %funcType, %seFunc, %funcSeParam, %funcSigs
  #     @alii, %isAlias, %aliasOf
{
  local ($const, $type, $value, $sig) = @_;

  $sig = "!";
  push (@funcs, $const);
  $isFunc {$const} = 1;
  $funcSigs {$const} = $sig;
  $funcType {$const, $sig} = $type;
  $seFunc {$const, $sig} = 0;
  $funcSeParam {$const, $sig} = -1;
  push (@alii, $const);
  $isAlias {$const} = 1;
  $aliasOf {$const} = $value;
}

sub func1Add
  # Add one parameter function with alias
  #   in : name, type, alias, type
  #   set @funcs, %isFunc, %funcType, %seFunc, %funcSeParam, %funcSigs
  #     @alii, %isAlias, %aliasOf
{
  local ($func, $type, $alias, $param, $sig) = @_;

  $sig = "($param";
  push (@funcs, $func);
  $isFunc {$func} = 1;
  $funcSigs {$func} = $sig;
  $funcType {$func, $sig} = $type;
  $seFunc {$func, $sig} = 0;
  $funcSeParam {$func, $sig} = -1;
  push (@alii, $func);
  $isAlias {$func} = 1;
  $aliasOf {$func} = $alias;
}

sub aliasAdd
  # Add alias
  #   set @alii, %isAlias, %aliasOf
{
  local ($of, $is) = @_;

  push (@alii, $of);
  $isAlias {$of} = 1;
  $aliasOf {$of} = $is;
}

sub fixIn
  # Add infix functions
  #   set @infex, %funcType, %isInfix, %funcParam, %funcParams
{
  local ($type, $param, $func, $sig);

  $type = shift;
  $param = shift;
  $sig = "($param,$param";
  while ($func = shift)
  {
    $isInfix {$func} = 1;
    push (@infex, "$func");
    $funcType {$func, $sig} = $type;
    $seFunc {$func, $sig} = 0;
    $funcSeParam {$func, $sig} = -1;
    $funcSigs {$func} = $sig;
  }
}

sub processRCFile
  # Process .danishrc options
  #   desires: .danishrc
  #   sets: $outputFile
  #     @javaFiles, @aliasFiles, @signatureFiles, @vectorFiles, @axiomFiles
{
  local ($parameters);

  if (open (RCFILE, ".danishrc"))
  {
    while ()
    {
      $parameters = " " . $_;
      $outputFile = $1 if ($parameters =~ s/\s+-o\s*(\S+)\s*/ /);
      $threshold = $1 if ($parameters =~ s/\s+-t\s*(\S+)\s*/ /);
      push (javaFiles, $1) while ($parameters =~ s/\s+-j\s*(\S+)\s*/ /);
      push (aliasFiles, $1) while ($parameters =~ s/\s+-a\s*(\S+)\s*/ /);
      push (signatureFiles, $1) while ($parameters =~ s/\s+-s\s*(\S+)\s*/ /);
      push (vectorFiles, $1) while ($parameters =~ s/\s+-v\s*(\S+)\s*/ /);
      push (axiomFiles, $1) while ($parameters =~ s/\s+-x\s*(\S+)\s*/ /);
      $parameters =~ s/^\s*(\S+(\s+\S+)*)\s*$/\1/;
      if ($web)
      {
        die "<FONT COLOR=\"#FF0022\">Syntax error<\/FONT> on line $. in .danishrc file (`$parameters').\n" if $parameters =~ /\S/;
      }
      else
      {
        die "Syntax error on line $. in .danishrc file (`$parameters').\n" if $parameters =~ /\S/;
      }
    }
    close (RCFILE);
  }
}

sub processParameters
  # Processes command line options
  #   needs: @ARGV
  #   sets: $outputFile
  #     @javaFiles, @aliasFiles, @signatureFiles, @vectorFiles, @axiomFiles
{
  local ($parameters);
  $parameters = " " . $parameterString;
  @javaFiles = () if ($parameters =~ /\s+-j\s*(\S+)\s*/);
  @aliasFiles = () if ($parameters =~ /\s+-a\s*(\S+)\s*/);
  @signatureFiles = () if ($parameters =~ /\s+-s\s*(\S+)\s*/);
  @vectorFiles = () if ($parameters =~ /\s+-v\s*(\S+)\s*/);
  $outputFile = $1 if ($parameters =~ s/\s+-o\s*(\S+)\s*/ /);
  $threshold = $1 if ($parameters =~ s/\s+-t\s*(\S+)\s*/ /);
  push (javaFiles, $1) while ($parameters =~ s/\s+-j\s*(\S+)\s*/ /);
  push (aliasFiles, $1) while ($parameters =~ s/\s+-a\s*(\S+)\s*/ /);
  push (signatureFiles, $1) while ($parameters =~ s/\s+-s\s*(\S+)\s*/ /);
  push (vectorFiles, $1) while ($parameters =~ s/\s+-v\s*(\S+)\s*/ /);
  $verbose = ($parameters =~ s/\s+-dump\s*/ /);
  $web = ($parameters =~ s/\s+-web\s*/ /);
  &syntaxError if ($parameters =~ /\s+-/);
  @axiomFiles = split (" ", $parameters)
      if $parameters =~ /\S/;
  if ($web)
  {
      die "<FONT COLOR=\"#FF0022\">No output file<\/FONT>\n" if ($outputFile eq "");
  }
  else
  {
      die "No output file\n" if ($outputFile eq "");
  }
}


Goto Previous Topic Goto Next Topic
Created 04/06/98 by Tim Preston
Revised 04/29/98