-- JunoSyntaxImpl.mesa
-- June 6, 1983 2:06 pm
-- GNelson
-- Last Edited by: Gnelson, December 10, 1983 11:19 pm

DIRECTORY JunoSyntax, Rope, Atom, Lisp;

JunoSyntaxImpl: PROGRAM IMPORTS Atom, Lisp EXPORTS JunoSyntax =

BEGIN OPEN JunoSyntax, Lisp;

Gensym: PUBLIC PROC RETURNS [Lisp.Value] = {RETURN[Atom.Gensym[]]};

IsVar: PUBLIC PROC[v: Lisp.Value] RETURNS [BOOL] = 
 {RETURN[ISTYPE[v, ATOM]]};

foo: PUBLIC ATOM ← Atom.Gensym[];

IsProcDef: PUBLIC PROC[v:Lisp.Value] RETURNS [BOOL] =
  {RETURN [Car[v] = proc]};
BodyOfProcDef: PUBLIC PROC[v:ProcDef] RETURNS [Command] =
  {RETURN [Caddr[Cadr[v]]]};
ProcOfProcDef: PUBLIC PROC[v:ProcDef] RETURNS [ProcName] =
  {v ← Cadr[v]; -- Now v is a ProcDef
   v ← Cadr[v]; -- Now v is a ProcDef1
   IF Pair[v] AND Car[v] = colon THEN v ← Cadr[v]; -- Now v is a ProcDef2
   IF Pair[v] AND Car[v] = leftpren THEN RETURN[Cadr[v]] ELSE RETURN [v]};
Varlist1OfProcDef: PUBLIC PROC[v:ProcDef] RETURNS [Varlist] =
   {v ← Cadr[v]; -- Now v is a ProcDef
    v ← Cadr[v]; -- Now v is a ProcDef1
    IF Pair[v] AND Car[v] = colon 
    THEN RETURN[Linearize[Cadr[v], comma]]
    ELSE RETURN [NIL]};
Varlist2OfProcDef: PUBLIC PROC[v:ProcDef] RETURNS [Varlist] =
  {v ← Cadr[v]; -- Now v is a ProcDef
   v ← Cadr[v]; -- Now v is a ProcDef1
   IF Pair[v] AND Car[v] = colon THEN v ← Cadr[v]; -- Now v is a ProcDef2
   IF Pair[v] THEN RETURN[Linearize[Caddr[v], comma]]
   ELSE RETURN[NIL]};

IsFunDef: PUBLIC PROC[v:Value] RETURNS [BOOL] =
  {RETURN [Car[v] = func]};
BodyOfFunDef: PUBLIC PROC[v:FunDef] RETURNS [Formula] =
  {RETURN [Caddr[Cadr[v]]]};
FunOfFunDef: PUBLIC PROC[v:FunDef] RETURNS [FunName] =
   {v ← Cadr[v]; -- Now v is a FunDef
    v ← Cadr[v]; -- Now v is a FunDef1
    v ← Cadr[v]; -- Now v is a FunDef2
    IF Pair[v] THEN RETURN [Cadr[v]] ELSE RETURN[v]};
VarlistOfFunDef: PUBLIC PROC[v:FunDef] RETURNS [Varlist] =
   {v ← Cadr[v]; -- Now v is a FunDef
    v ← Cadr[v]; -- Now v is a FunDef1
    v ← Cadr[v]; -- Now v is a FunDef2
    IF Pair[v] THEN RETURN [Linearize[Caddr[v], comma]] ELSE RETURN[NIL]};
ResultnameOfFunDef: PUBLIC PROC[v:FunDef] RETURNS [Variable] =
   {RETURN [Caddr[Cadr[Cadr[v]]]]};

IsPredDef: PUBLIC PROC[v:Value] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = pred]};
BodyOfPredDef: PUBLIC PROC[v:PredDef] RETURNS [Formula] =
   {RETURN [Caddr[Cadr[v]]]};
PredOfPredDef: PUBLIC PROC[v:PredDef] RETURNS [PredName] =
   {RETURN [Cadr[Cadr[Cadr[v]]]]};
VarlistOfPredDef: PUBLIC PROC[v:PredDef] RETURNS [Varlist] =
   {RETURN [Linearize[Caddr[Cadr[Cadr[v]]], comma]]};

IsConjunction: PUBLIC PROC[v:Formula] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = and]};
LHSOfConjunction: PUBLIC PROC[v:Formula] RETURNS [Formula] =
   {RETURN [Cadr[v]]};
RHSOfConjunction: PUBLIC PROC[v:Formula] RETURNS [Formula] =
   {RETURN [Caddr[v]]};

IsParenthesized: PUBLIC PROC[v:Value] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = leftpren AND Cdr[Cdr[v]] = NIL]};
ContentsOfParentheses: PUBLIC PROC[v:Value] RETURNS [Value] =
   {RETURN [Cadr[v]]};

IsQuantification: PUBLIC PROC[v:Formula] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = ex]};
QuantifierOfQuantification: PUBLIC PROC[v:Formula] RETURNS [Value] =
   {RETURN [Car[v]]};  -- someday there may be "for all".
QuantifieeOfQuantification: PUBLIC PROC[v:Formula] RETURNS [Formula] =
   {RETURN [Caddr[Cadr[v]]]};
QuantifierVarlistOfQuantification: PUBLIC PROC[v:Formula] RETURNS [Varlist] =
   {RETURN [Linearize[Cadr[Cadr[v]], comma]]};

IsAtomicFormula: PUBLIC PROC[v:Formula] RETURNS [BOOL] =
   {RETURN [TRUE]};
PredOfAtomicFormula: PUBLIC PROC[v:Formula] RETURNS [PredName] =
   {RETURN [SELECT TRUE FROM 
                  v = true OR v = false => v,
                  Pair[Car[v]] => Car[v],
                  Car[v] = leftpren => Cadr[v],
                  Car[v] = ltop => lt,
                  Car[v] = gtop => gt,
                  Car[v] = leop => le,
                  Car[v] = geop => ge,
                  Car[v] = eq => eq,
                  Car[v] = neq => neq,
                ENDCASE => ERROR]};
TermlistOfAtomicFormula: PUBLIC PROC[v:Formula] RETURNS [Termlist] =
   {RETURN  [SELECT TRUE FROM 
                  v = true OR v = false => NIL,
                  Pair[Car[v]] => Cdr[v],
                  Car[v] = leftpren => Linearize[Caddr[v], comma],
                  Memq[Car[v], LIST[ltop, gtop, leop, geop, eq, neq]] => Cdr[v]
                ENDCASE => ERROR]};
MakeAtomicFormula: PUBLIC PROC[p: PredName, tl: Termlist] RETURNS [Formula] =
   {RETURN [Cons[leftpren, Cons[p, Cons[Unlinearize[tl, comma], NIL]]]]};

IsTerm: PUBLIC PROC[v:Value] RETURNS [BOOL] =
   {RETURN [TRUE]};
FunctionOfTerm: PUBLIC PROC[v:Term] RETURNS [FunName] =
   {RETURN [SELECT TRUE FROM
   			   NOT Pair[v] => v,
   			   Car[v] = leftpren AND Cddr[v] # NIL => Cadr[v],
   			   Car[v] = plusop => plus,
   			   Car[v] = minusop => minus,
   			   Car[v] = timesop => times,
   			   Car[v] = divideop => divide,
   			   Car[v] = div => div,
   			   Car[v] = cons => cons,
      			 -- cons is needed because of Fix below
   			   Car[v] = leftpren AND Cddr[v] = NIL AND Pair[Caddr[v]]
   			   AND Car[Caddr[v]] = comma => cons,
   			   Car[v] = leftpren AND Cddr[v] = NIL => FunctionOfTerm[Cadr[v]],
   			   Car[v] = leftbracket => cons,
                ENDCASE => Car[v]]};
TermlistOfTerm: PUBLIC PROC[v:Term] RETURNS [Termlist] =
   {RETURN [SELECT TRUE FROM
   			   NOT Pair[v] => NIL,
   			   Car[v] = leftpren AND Cddr[v] # NIL => Linearize[Caddr[v], comma],
                  Car[v] = minus AND Cddr[v] = NIL => LIST[NEW[INT ← 0], Cadr[v]],
   			   Memq[Car[v], LIST[plusop, minusop, timesop, divideop, div, cons]] => Cdr[v],
   			   Car[v] = leftpren AND Cddr[v] = NIL AND Pair[Caddr[v]]
   			   AND Car[Caddr[v]] = comma => Linearize[Caddr[v], comma],
   			   Car[v] = leftpren AND Cddr[v] = NIL => TermlistOfTerm[Cadr[v]],
   			   Car[v] = leftbracket => Fix[Linearize[Cadr[v], comma]]
      		 ENDCASE => Cdr[v]]};

Fix: PROC[l: REF] RETURNS [Termlist] = {
  IF Cdr[l] = NIL THEN RETURN [LIST[Car[l], NIL]]
  ELSE RETURN [LIST[Car[l], Cons[cons, Fix[Cdr[l]]]]]};

IsConstant: PUBLIC PROC[v:Value] RETURNS [BOOL] =
  {RETURN[ISTYPE[v, REF INT] OR ISTYPE[v, REF REAL] 
          OR ISTYPE[v, ATOM] OR ISTYPE[v, Rope.ROPE] OR ISTYPE[v, REF TEXT]]};

IsSkip: PUBLIC PROC[v:Value] RETURNS [BOOL] =
   {RETURN [v = $Skip]};

IsAbort: PUBLIC PROC[v:Value] RETURNS [BOOL] =
   {RETURN [v = $Abort]};

IsComposition: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = semicolon]};
LHSOfComposition: PUBLIC PROC[v:GuardedCommand] RETURNS [Command] =
   {RETURN [Cadr[v]]};
RHSOfComposition: PUBLIC PROC[v:GuardedCommand] RETURNS [Command] =
   {RETURN [Caddr[v]]};

IsSuchthatCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = st]};
VarlistOfSuchthatCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [Varlist] =
   {RETURN [Linearize[Cadr[v], comma]]};
PredOfSuchthatCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [Formula] =
   {RETURN [Caddr[v]]};

IsAssignmentCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = assign]};
VarlistOfAssignmentCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [Varlist] =
   {RETURN [Linearize[Cadr[v], comma]]};
TermlistOfAssignmentCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [Termlist] =
   {RETURN [Linearize[Caddr[v], comma]]};

IsProcCall: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [NOT Pair[v] OR Car[v] = colon OR Car[v] = leftpren]};
ProcOfProcCall: PUBLIC PROC[v:GuardedCommand] RETURNS [ProcName] =
   {SELECT TRUE FROM
     NOT Pair[v] => RETURN[v];
     Car[v] = colon AND Pair[Caddr[v]] => RETURN[Cadr[Caddr[v]]];
     Car[v] = colon => RETURN[Caddr[v]];
     Car[v] = leftpren => RETURN[Cadr[v]];
    ENDCASE => ERROR};
VarlistOfProcCall: PUBLIC PROC[v:GuardedCommand] RETURNS [Varlist] =
   {SELECT TRUE FROM
     NOT Pair[v] => RETURN[NIL];
     Car[v] = colon AND Pair[Caddr[v]] => RETURN[Linearize[Cadr[v], comma]];
     Car[v] = colon => RETURN[Linearize[Cadr[v], comma]];
     Car[v] = leftpren => RETURN[NIL];
    ENDCASE => ERROR};
TermlistOfProcCall: PUBLIC PROC[v:GuardedCommand] RETURNS [Termlist] =
   {SELECT TRUE FROM
     NOT Pair[v] => RETURN[NIL];
     Car[v] = colon AND Pair[Caddr[v]] => RETURN[Linearize[Caddr[Caddr[v]], comma]];
     Car[v] = colon => RETURN[NIL];
     Car[v] = leftpren => RETURN[Linearize[Caddr[v], comma]];
   ENDCASE => ERROR};

IsAlternatingCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = if]};
BodyOfAlternatingCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [GuardedCommand] =
   {RETURN [Cadr[v]]};

IsIterativeCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = do]};
BodyOfIterativeCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [GuardedCommand] =
   {RETURN [Cadr[v]]};

IsCompoundGuardedCommand: 
  PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND Car[v] = elseif]};
LHSOfCompoundGuardedCommand: 
  PUBLIC PROC[v:GuardedCommand] RETURNS [GuardedCommand] =
   {RETURN [Cadr[v]]};
RHSOfCompoundGuardedCommand: 
  PUBLIC PROC[v:GuardedCommand] RETURNS [GuardedCommand] =
   {RETURN [Caddr[v]]};

IsSimpleGuardedCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [BOOL] =
   {RETURN [Pair[v] AND NOT Car[v] = elseif]};
PredOfSimpleGuardedCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [PredName] =
   {RETURN [IF Pair[Cadr[v]] AND Car[Cadr[v]] = colon 
                THEN Caddr[Cadr[v]]
                ELSE Cadr[v]]};
CommandOfSimpleCommand: PUBLIC PROC[v:GuardedCommand] RETURNS [Command] =
   {RETURN [Caddr[v]]};
VarlistOfSimpleGuardedCommand: PUBLIC PROC[v:GuardedCommand] RETURNS  [Varlist] =
   {RETURN [IF Pair[Cadr[v]] AND Car[Cadr[v]] = colon 
                THEN Linearize[Cadr[Cadr[v]], comma]
                ELSE NIL]};

KernelPredicate: PUBLIC PROC [p: PredName] RETURNS [BOOLEAN] 
 = {-- IF ISTYPE[p, REF INT] OR ISTYPE[p, REF REAL] THEN RETURN[TRUE];
    IF p = $T OR  p = $F THEN RETURN [TRUE];
    IF Pair[p] AND Car[p] = constant THEN RETURN[TRUE];
    SELECT p FROM
     eq, neq, PairOf, isPositive, isSumOf, isProductOf => RETURN[TRUE]
    ENDCASE => RETURN[FALSE]};

leftpren: PUBLIC ATOM ← Atom.MakeAtom["("];
colon: PUBLIC ATOM ← Atom.MakeAtom[":"];
semicolon: PUBLIC ATOM ← Atom.MakeAtom[";"];
comma: PUBLIC ATOM ← Atom.MakeAtom[","];
assign: PUBLIC ATOM ← Atom.MakeAtom[":="];
eq: PUBLIC ATOM ← Atom.MakeAtom["="];
neq: PUBLIC ATOM ← Atom.MakeAtom["neq"];
lt: PUBLIC ATOM ← Atom.MakeAtom["Less"];
gt: PUBLIC ATOM ← Atom.MakeAtom["Greater"];
le: PUBLIC ATOM ← Atom.MakeAtom["LessEq"];
ge: PUBLIC ATOM ← Atom.MakeAtom["GreaterEq"];
ltop: PUBLIC ATOM ← Atom.MakeAtom["<"];
gtop: PUBLIC ATOM ← Atom.MakeAtom[">"];
leop: PUBLIC ATOM ← Atom.MakeAtom["le"];
geop: PUBLIC ATOM ← Atom.MakeAtom["ge"];
do: PUBLIC ATOM ← Atom.MakeAtom["do"];
if: PUBLIC ATOM ← Atom.MakeAtom["if"];
abort: PUBLIC ATOM ← Atom.MakeAtom["Abort"];
skip: PUBLIC ATOM ← Atom.MakeAtom["Skip"];
st: PUBLIC ATOM ← Atom.MakeAtom["st"];
elseif: PUBLIC ATOM ← Atom.MakeAtom["elseif"];
then: PUBLIC ATOM ← Atom.MakeAtom["then"];
and: PUBLIC ATOM ← Atom.MakeAtom["and"];
ex: PUBLIC ATOM ← Atom.MakeAtom["ex"];
para: PUBLIC ATOM ← Atom.MakeAtom["para"];
cong: PUBLIC ATOM ← Atom.MakeAtom["cong"];
perp: PUBLIC ATOM ← Atom.MakeAtom["perp"];
means: PUBLIC ATOM ← Atom.MakeAtom["means"];
plusop: PUBLIC ATOM ← Atom.MakeAtom["+"];
minusop: PUBLIC ATOM ← Atom.MakeAtom["-"];
timesop: PUBLIC ATOM ← Atom.MakeAtom["*"];
divideop: PUBLIC ATOM ← Atom.MakeAtom["/"];
plus: PUBLIC ATOM ← Atom.MakeAtom["plus"];
minus: PUBLIC ATOM ← Atom.MakeAtom["minus"];
times: PUBLIC ATOM ← Atom.MakeAtom["times"];
divide: PUBLIC ATOM ← Atom.MakeAtom["divide"];
div: PUBLIC ATOM ← Atom.MakeAtom["div"];

implies: PUBLIC ATOM ← Atom.MakeAtom["implies"];
or: PUBLIC ATOM ← Atom.MakeAtom["or"];
dot: PUBLIC ATOM ← Atom.MakeAtom["."];
rel: PUBLIC ATOM ← Atom.MakeAtom["rel"];
leftbracket: PUBLIC ATOM ← Atom.MakeAtom["["];
fi: PUBLIC ATOM ← Atom.MakeAtom["fi"];
od: PUBLIC ATOM ← Atom.MakeAtom["od"];
rightpren: PUBLIC ATOM ← Atom.MakeAtom[")"];
rightbracket: PUBLIC ATOM ← Atom.MakeAtom["]"];

quote: PUBLIC ATOM ← Atom.MakeAtom["quote"];
isPositive: PUBLIC ATOM ← Atom.MakeAtom["isPositive"];
isProductOf: PUBLIC ATOM ← Atom.MakeAtom["IsProductOf"];
PairOf: PUBLIC ATOM ← Atom.MakeAtom["PairOf"];
isSumOf: PUBLIC ATOM ← Atom.MakeAtom["IsSumOf"];
constant: PUBLIC ATOM ← Atom.MakeAtom["constant"];
cons: PUBLIC ATOM ← Atom.MakeAtom["cons"];
car: PUBLIC ATOM ← Atom.MakeAtom["car"];
cdr: PUBLIC ATOM ← Atom.MakeAtom["cdr"];
proc: PUBLIC ATOM ← Atom.MakeAtom["proc"];
pred: PUBLIC ATOM ← Atom.MakeAtom["pred"];
func: PUBLIC ATOM ← Atom.MakeAtom["func"];
isPairOf: PUBLIC ATOM ← Atom.MakeAtom["isPairOf"];
true: PUBLIC ATOM ← Atom.MakeAtom["T"];
false: PUBLIC ATOM ← Atom.MakeAtom["F"];





--: PUBLIC ATOM ← Atom.MakeAtom[""];

END.