HerculesExpr: DEFINITIONS = BEGIN Se: TYPE = REF ANY; Se: TYPE = REF ANY; -- Symbolic Expression. Either: OpPtr: TYPE = REF OpRec; OpRec: TYPE = RECORD [ op: ATOM, -- operation (usually atom, a function or operator name) larg, rarg: Se -- Unevaluated arguments. larg is NIL for prefix operators. ]; CellPtr: TYPE = REF; NumPtr: TYPE = REF NumCell; NumCell: TYPE = RECORD [val: REAL, -- current value const: BOOL _ TRUE, -- if TRUE, val is frozen (e.g., result of '+', or coord of frozen point) int: BOOL FALSE, -- if TRUE, val is constrained to be integral col: INTEGER _ 0 -- (used by solver) column index in the partial derivative matrix ]; RopePtr: TYPE = REF RopeCell; RopeCell: TYPE = RECORD [rope: Rope.ROPE, -- rope (obviously) const: BOOL _ TRUE -- if FALSE, rope can be changed by assignment ]; FunPtr: TYPE = REF FunRec; FunRec: TYPE = RECORD [body: Se, -- Body of lambda. parms: LIST OF ATOM, -- formal parameters of the lambda. alist: Alist -- bindings for free variables in body of lambda, other than the parms ]; UnionMold: TYPE = REF UnionRec; UnionMoldRec: TYPE = RECORD [alts: LIST OF Mold]; VectorMold: TYPE = REF VectorMoldRec; VectorMoldRec: TYPE = RECORD [min: INTEGER, max: INTEGER _ LAST[INTEGER], -- LAST[INTEGER] means infinity elm: Mold]; Mold: TYPE = REF; Fits: PROC [e: Se, mold: Mold] RETURNS [fits: BOOL, culprit: Se]; -- Returns fits=true if the expression e is in the set of expressions described by the mold. -- If fits = FALSE, the culprit is the first sub-expression of e that -- does not fit the corresponding -- piece of the mold. -- More precisely, if the mold is not list or vector, then culprit will be always -- e; if the mold is a vector -- or list, culprit will be e if e is not a list, or is of the wrong length; otherwise -- culprit will be the culprit in the first element of e that fails to fit. IsList: PROC [e: Se, min: INTEGER _ 0, max: INTEGER _ LAST[INTEGER]] RETURNS [fits: BOOL, list: LIST OF Se]; -- If e is LIST OF Se, returns [Length[Se] IN [min..max], NARROW[e]]; -- otherwise returns [FALSE, NIL] IsUnAppl: PROC [e: Se, op: Se] RETURNS [fits: BOOL, arg: Se]; -- If e is (op ), returns [TRUE, ]; otherwise returns [FALSE, NIL] IsBinAppl: PROC [e: Se, op: Se] RETURNS [fits: BOOL, larg, rarg: Se]; -- If e is (op ), returns [TRUE, , ]; -- otherwise returns [FALSE, NIL, NIL] InvalidSe: ERROR [e: Se]; -- Raised by the various procedures here when the argument is of the wrong format. ToList: PROC [e: Se, min: INTEGER _ 0, max: INTEGER _ LAST[INTEGER]] RETURNS [list: LIST OF Se]; -- Narrows e to LIST OF Se with [min..max] elements, and returns it. Car: PROC [r: Se] RETURNS [Se]; Cdr: PROC [r: Se] RETURNS [Se]; Cadr: PROC [r: Se] RETURNS [Se]; Caddr: PROC [r: Se] RETURNS [Se]; Unnest: PROC[e: Se, op, zero: Se, tail: LIST OF Se _ NIL] RETURNS [list: LIST OF Se]; -- Recursively unbundles an expression of the form (op ), -- and returns the list ( ... )* of all the arguments of -- that are not themselves of the above form, prepended to the given tail. -- Any s that are = zero will be ignored. Alist: TYPE = LIST OF Se; -- of the form ( ...) InsertDef: PROC [name: ATOM, value: Se, alist: Alist] RETURNS [new: Alist]; -- Inserts the definition of name in the front of the alist. GetDef: PROC [name: ATOM, alist: Alist, backup: Alist _ NIL] RETURNS [value: Se]; -- Gets most recently defined value of name from alist. If not found, looks it up in backup. -- Returns NIL if name is not defined (or if value is NIL) BindArgs: PROC [parms: LIST OF Se, args: LIST OF Se, alist: Alist] RETURNS [new: Alist]; -- Prepends to the given alist a segment ( ... ) -- Raises the error ParmNumberError if one of the lists is longer than the other. ParmNumberError: ERROR; MakeNum: PROC [val: REAL, int, const: BOOL _ FALSE] RETURNS [n: NumPtr]; -- Makes a new NumCell with given contents. -- If int=TRUE, round the number to the nearest integer; if the -- result can be represented as a REAL with no error, sets the int flag, otherwise -- leaves it off. END. B HerculesExpr.mesa Last Edited by: Stolfi, April 9, 1984 7:20:16 pm PST Modified pieces of JunoAlgebra and other modules written July, 1982 by Donna M. Auguste and Greg Nelson Last Edited by: Gnelson, October 11, 1983 4:15 pm Format and manipulation of Symbolic Expressions. - - - - SYMBOLIC EXPRESSIONS Symbolic Expression. One of the following: NIL, or atom, or Cell pointer: REF NumCell or REF RopeCell, or Functional Value: REF FunRec, or Application: LIST OF Se, of the form (), ( ), or ( ) where , , and are the "operators" and the s are their "arguments". The only s are and ; they occur as in symbolic expressions resulting from the parsing of the Hercules external expressions () and []. In all other cases, and are always s. For example, the external expression f(a, b) should be parsed into ($f ( ( $a $b))). - - - - New Se's (April 9, 1984 7:18:46 pm PST) ATOM (variable, operator, or function name) Cell pointer: REF NumCell or REF RopeCell, or Functional Value: REF FunRec, or OpPtr - - - - SIMPLE VALUE CELLS A simple value cell is a record that can hold a single value of type Int, Real, or Rope. Value cells are created (1) when a new atom is declared in an if or do operation, or (2) by operations such as +, -, etc., to hold the resulting value. In the first case, the "value" of the atom is the CellPtr, not the contents of the cell. - - - - FUNCTIONAL VALUES A "functional value" is equivalent to LISP's FUNARG, essentially a lambda-expression plus an a-list that binds all free varaibles (if any) in its body. However, any free variable that is not bound by the given a-list is looked up in the global a-list. Changes in the latter (brought upon, for example, by re-parsing the Procs Viewer) may change the meaning of a FunVal; in this sense, FunVals are not perfectly "closed", as theory would demand. Also, even when a variable is solidly bound to a CellPtr, it may be possible to change the contents of the referenced cell by assignment. - - - - MOLDS AND CASTING A Mold describes a set of Symbolic Expressions. The possible classes of Molds, and the set of Se's that they describe, as listed below: NIL --> just the NIL Se $ANY --> any Se $ATOM --> an atom $LIST --> a list of zero or more arbitrary Se s $NUM, $ROPE --> a non-NIL pointer to a cell of the specified type $FUN --> a non-NIL pointer to a FunRec, $INT --> a pointer to a NumCell with the int flag set, a UnionMold, --> a Se satisfying one of the alternatives listed within it a VectorMold, --> a list of [min...max] Se s all fitting the given elm mold a LIST OF Mold of the form (mold1, mold2, ..., moldn), --> a list of exactly n Se s, each fitting the corresponding mold. The following procedures narrow the argument to a specific type and format, and return its components in a more convenient form. They will raise the InvalidSe error if the argument is of the wrong type. Note: they DO NOT evaluate their arguments in any way. - - - - LIST MANIPULATION PROCS The following procedures narrow their argument(s) to LIST OF Se: - - - - ASSOCIATION LISTS - - - - MISCELLANEOUS Êš– "cedar" style˜šœ™šœ5™5šœ1™1Jšœ6™6Jšœ1™1———Jšœ1™1JšœÏk œ˜Jšœ˜™šœœœœ˜JšœÅÏrœžœžœ žœžœžœ‚žœžœmžœžœ žœž œ™®——™0š ÏcÏbœœœœŸ˜5Jšœœ|™—Jšœœœ˜Jš œœœ œŸ8œŸOœ˜Á—™šœ œ˜Jšœ˜ œ œ«™Ë—Jšœ œ˜Jšœ œœ œŸœ œœŸJœœœŸ.œœŸCœ˜¶Jšœ œ˜Jšœ œœœŸœ œŸžŸœ˜‹—™J™˜Jšœ²™²Jšœ œœ˜Jšœ œœŸœ œœœŸ$œŸGœ˜Ñ—šœ™Jš?œ‹Ðkrœ Ÿœžœ Ÿ œžœŸ œžœ Ÿ+œž œŸ7œžœ ŸœŸœ ÐcrŸœžœ Ÿœ¢œ ¢œ Ÿœž œŸ=œž œŸ¢ Ÿ¢œŸœ¡ž¡žœ žœUžœ™¢Jšœ œœ ˜ Jš œœœœœ˜2Jšžœœœžœ˜&Jšžœ œœ œ œœœŸ œ˜~Jšœœœ˜JšÏnœœœœŸ žŸ¢Ÿ/¢Ÿ¢Ÿ ¢Ÿ<¢Ÿœ˜¼Jš(œ£œœœ œœœœœœœŸ¢ŸÑckr¢Ÿ ¢ž ¤¢ ¤¢Ÿ¢¤¢¤¢Ÿ˜ÛJšœ£œœœœ Ÿ¢ŸœŸ¢¤¢ Ÿ¢¤¢¤¢Ÿ˜‘Jšœ£ œœœœŸ¢ŸœŸœœŸ¢¤¢¤¢Ÿ˜µJšœ–¢ œc™‚Jšœ  œœ ŸR˜mJšœ£œœœ œœœœœœŸ ¢Ÿ¤Ÿ ¢Ÿ¢Ÿ˜©—šœ ™ J™AJš£œœ œ˜ Jš£œœ œ˜ Jš£œœ œ˜!Jš£œœ œ˜"Jšœ£œœœœœœœœŸ†¢Ÿ˜ò—šœ™JšœœœœŸ2˜NJš £ œœœœŸ¢Ÿ¢Ÿ˜ŠJš£œœœ œœŸ¢Ÿ¢Ÿ¢Ÿ¢Ÿ=˜ìJš£ œœ œœ œœœŸ®˜‹Jšœ œœ˜—šœ™Jš£œœœœœœŸ3œŸ¡˜¢—Jšœ˜J˜—…—è#Ä