<<>> <> <> <> <<>> DIRECTORY Ascii, Atom, Basics, Commander, CommanderOps, Convert, CrankIO, CrankTypes, FS, IO, MPLeaves, MesaParser, MPTree, ProcessProps, Rope, StructuredStreams, UnparserBuffer; CrankIOImpl: CEDAR MONITOR IMPORTS Ascii, Atom, Basics, Commander, CommanderOps, Convert, FS, IO, MesaParser, ProcessProps, Rope, StructuredStreams, UnparserBuffer EXPORTS CrankIO ~ BEGIN OPEN CrankTypes; ROPE: TYPE = Rope.ROPE; Huh: PUBLIC SIGNAL [tree: Tree] = CODE; Parse: PROC [program: ROPE, errout: IO.STREAM] RETURNS [Tree] = INLINE { RETURN [MesaParser.Parse[program, errout].root] }; MakeOutputName: PUBLIC PROC [inputName: ROPE, ext: ROPE] RETURNS [ROPE] ~ { cp: FS.ComponentPositions; [inputName, cp] ¬ FS.ExpandName[inputName]; RETURN [Rope.Cat[Rope.Substr[inputName, cp.base.start, cp.base.length], ".", ext]] }; ParseRope: PUBLIC PROC [rope: ROPE] RETURNS [MPTree.Link] = { errout: IO.STREAM ¬ NARROW[ProcessProps.GetProp[$StdOut]]; RETURN [Parse[rope, errout]]; }; GetRopeFile: PROC [name: ROPE] RETURNS [rope: ROPE] = { in: IO.STREAM ¬ FS.StreamOpen[fileName: name, accessOptions: read]; rope ¬ IO.GetRope[in]; IO.Close[in]; }; ParseFile: PUBLIC PROC [fileName: ROPE] RETURNS [MPTree.Link] = { errout: IO.STREAM ¬ NARROW[ProcessProps.GetProp[$StdOut]]; result: MPTree.Link ¬ Parse[GetRopeFile[fileName], errout]; RETURN [result]; }; RopeFromTree: PUBLIC PROC [tree: Tree] RETURNS [ROPE] = { stream: IO.STREAM ¬ IO.ROS[]; PutTree[stream, tree]; RETURN [IO.RopeFromROS[stream]] }; WriteTree: PUBLIC PROC [tree: Tree, fileName: ROPE, sourceName: ROPE, skipAttributes: LIST OF ATOM] RETURNS [fullFName: ROPE] = { stream: IO.STREAM = FS.StreamOpen[fileName, $create]; fullFName ¬ FS.GetName[FS.OpenFileFromStream[stream]].fullFName; PutTree[stream, tree, FALSE, united, sourceName, skipAttributes]; IO.Close[stream]; }; WriteSTree: PUBLIC PROC [tree: Tree, fileName: ROPE, breakCondition: UnparserBuffer.BreakCondition ¬ united, sourceName: ROPE ¬ NIL, skipAttributes: LIST OF ATOM ¬ NIL] RETURNS [fullFName: ROPE] = { IF Basics.IsBound[UnparserBuffer.NewInittedHandle] THEN { <> writer: IO.STREAM = FS.StreamOpen[fileName, $create]; handle: UnparserBuffer.Handle = UnparserBuffer.NewInittedHandle[[output: [stream[writer]]]]; stream: IO.STREAM = StructuredStreams.Create[onTopOf: handle]; PutTree[stream, tree, TRUE, breakCondition, sourceName, skipAttributes]; StructuredStreams.CloseThrough[stream]; <> fullFName ¬ FS.FileInfo[name: fileName].fullFName; } ELSE { RETURN WriteTree[tree, fileName, sourceName, skipAttributes]; }; }; nodeNames: ARRAY MPTree.NodeName OF ROPE ¬ [ list: "list", item: "item", decl: "decl", typedecl: "typedecl", basicTC: "basicTC", enumeratedTC: "enumeratedTC", recordTC: "recordTC", monitoredTC: "monitoredTC", variantTC: "variantTC", refTC: "refTC", pointerTC: "pointerTC", listTC: "listTC", arrayTC: "arrayTC", arraydescTC: "arraydescTC", sequenceTC: "sequenceTC", procTC: "procTC", processTC: "processTC", portTC: "portTC", signalTC: "signalTC", errorTC: "errorTC", programTC: "programTC", anyTC: "anyTC", definitionTC: "definitionTC", unionTC: "unionTC", relativeTC: "relativeTC", subrangeTC: "subrangeTC", longTC: "longTC", opaqueTC: "opaqueTC", zoneTC: "zoneTC", linkTC: "linkTC", varTC: "varTC", implicitTC: "implicitTC", frameTC: "frameTC", discrimTC: "discrimTC", paintTC: "paintTC", optionTC: "optionTC", spareTC: "spareTC", unit: "unit", diritem: "diritem", module: "module", body: "body", inline: "inline", lambda: "lambda", block: "block", assign: "assign", extract: "extract", if: "if", case: "case", casetest: "casetest", caseswitch: "caseswitch", bind: "bind", do: "do", forseq: "forseq", upthru: "upthru", downthru: "downthru", return: "return", result: "result", goto: "goto", exit: "exit", loop: "loop", free: "free", resume: "resume", reject: "reject", continue: "continue", retry: "retry", catchmark: "catchmark", restart: "restart", stop: "stop", lock: "lock", wait: "wait", notify: "notify", broadcast: "broadcast", unlock: "unlock", null: "null", label: "label", open: "open", enable: "enable", catch: "catch", dst: "dst", lste: "lste", lstf: "lstf", syscall: "syscall", checked: "checked", lst: "lst", spareS3: "spareS3", subst: "subst", call: "call", portcall: "portcall", signal: "signal", error: "error", syserror: "syserror", xerror: "xerror", start: "start", join: "join", apply: "apply", callx: "callx", portcallx: "portcallx", signalx: "signalx", errorx: "errorx", syserrorx: "syserrorx", startx: "startx", fork: "fork", joinx: "joinx", index: "index", dindex: "dindex", seqindex: "seqindex", reloc: "reloc", construct: "construct", union: "union", rowcons: "rowcons", sequence: "sequence", listcons: "listcons", substx: "substx", ifx: "ifx", casex: "casex", bindx: "bindx", assignx: "assignx", extractx: "extractx", or: "or", and: "and", relE: "relE", relN: "relN", relL: "relL", relGE: "relGE", relG: "relG", relLE: "relLE", in: "in", notin: "notin", plus: "plus", minus: "minus", times: "times", div: "div", mod: "mod", power: "power", dot: "dot", cdot: "cdot", dollar: "dollar", create: "create", not: "not", uminus: "uminus", addr: "addr", uparrow: "uparrow", min: "min", max: "max", ord: "ord", val: "val", abs: "abs", all: "all", size: "size", first: "first", last: "last", pred: "pred", succ: "succ", arraydesc: "arraydesc", length: "length", base: "base", loophole: "loophole", nil: "nil", new: "new", void: "void", clit: "clit", llit: "llit", cast: "cast", check: "check", float: "float", pad: "pad", chop: "chop", safen: "safen", syscallx: "syscallx", narrow: "narrow", istype: "istype", openx: "openx", mwconst: "mwconst", cons: "cons", atom: "atom", typecode: "typecode", stringinit: "stringinit", textlit: "textlit", signalinit: "signalinit", procinit: "procinit", intOO: "intOO", intOC: "intOC", intCO: "intCO", intCC: "intCC", thread: "thread", none: "none", exlist: "exlist", initlist: "initlist", ditem: "ditem", lengthen: "lengthen", shorten: "shorten", self: "self", gcrt: "gcrt", proccheck: "proccheck", entry: "entry", internal: "internal", invalid: "invalid" ]; RopeFromNodeName: PUBLIC PROC [nodeName: MPTree.NodeName] RETURNS [ROPE] = { RETURN [nodeNames[nodeName]] }; Raise: PROC [old: CHAR] RETURNS [new: CHAR] = {new ¬ Ascii.Upper[old]}; nodeNameAtoms: ARRAY MPTree.NodeName OF ATOM ¬ ALL[NIL]; AtomFromNodeName: PUBLIC PROC [nodeName: MPTree.NodeName] RETURNS [ATOM] = { IF nodeNameAtoms[nodeName] = NIL THEN { nodeNameAtoms[nodeName] ¬ Atom.MakeAtom[Rope.Translate[base: RopeFromNodeName[nodeName], translator: Raise]]; }; RETURN [nodeNameAtoms[nodeName]] }; AllUpperCase: PROC [rope: ROPE] RETURNS [BOOL] = { each: PROC [c: CHAR] RETURNS [quit: BOOL] = { quit ¬ NOT (c IN ['A..'Z] OR c IN ['0..'9]) }; RETURN [NOT Rope.Map[base: rope, action: each]] }; DecodeAttr: PUBLIC PROC [name: MPTree.NodeName, attrBits: PACKED ARRAY MPTree.AttrId OF BOOL] RETURNS [Attributes] = { attr: PACKED ARRAY MPTree.AttrId OF BOOL ¬ attrBits; list: LIST OF REF ANY ¬ NIL; Means: PROC [attrid: MPTree.AttrId, attrName: ATOM] = { IF attr[attrid] THEN { list ¬ CONS[attrName, CONS[$TRUE, list]]; attr[attrid] ¬ FALSE }; }; Checking: PROC = { AddChecking: PROC [a: ATOM] = { list ¬ CONS[$CHECKING, CONS[a, list]]; attr[1] ¬ attr[2] ¬ FALSE; }; SELECT ORD[attr[1]]*2+ORD[attr[2]] FROM 3 => {AddChecking[$CHECKED]}; 1 => {AddChecking[$TRUSTED]}; 0 => {AddChecking[$UNCHECKED]}; ENDCASE => NULL; }; IF attr = ALL[FALSE] THEN RETURN [NIL]; SELECT name FROM mwconst => {Means[1, $FLOATINGPOINT]}; size => { SELECT attr FROM [FALSE, FALSE, FALSE] => RETURN[LIST[$UNITS, $BITS]]; [TRUE, FALSE, FALSE] => RETURN[LIST[$UNITS, $BYTES]]; [FALSE, TRUE, FALSE] => RETURN[LIST[$UNITS, $ADDRESSUNITS]]; [TRUE, TRUE, FALSE] => RETURN[LIST[$UNITS, $WORDS]]; ENDCASE => NULL; }; inline, block => { Checking[] }; body => { Means[3, $INLINE]; Checking[] }; programTC => { Means[3, $CEDAR]; Means[1, $MONITOR] }; procTC => { Means[3, $SAFE] }; monitoredTC, recordTC => { IF NOT attr[3] THEN SIGNAL Huh[NIL]; attr[3] ¬ FALSE; Means[1, $MACHINEDEPENDENT]; }; enumeratedTC => { Means[2, $MACHINEDEPENDENT] }; sequenceTC, arrayTC => { Means[3, $MACHINEDEPENDENT]; Means[3, $PACKED] }; typedecl, decl => { Means[2, $PUBLIC]; Means[1, $CONSTANT] }; variantTC => { Means[1, $MACHINEDEPENDENT] }; refTC => { Means[3, $READONLY] }; ENDCASE => NULL; Means[3, $ATTRBIT3]; Means[2, $ATTRBIT2]; Means[1, $ATTRBIT1]; RETURN [list]; }; Bp: PROC [p: PutTreeOptions] = { IO.PutChar[p.stream, ' ]; IF p.structure THEN StructuredStreams.Bp[p.stream, p.breakCondition, 1]; }; PutTreeOptions: TYPE = REF PutTreeOptionsRep; PutTreeOptionsRep: TYPE = RECORD [stream: IO.STREAM, structure: BOOL ¬ FALSE, breakCondition: UnparserBuffer.BreakCondition ¬ united, idcount: INT ¬ 0, skipAttributes: LIST OF ATOM ¬ NIL]; PutTree: PUBLIC PROC [stream: IO.STREAM, tree: Tree, structure: BOOL ¬ FALSE, breakCondition: UnparserBuffer.BreakCondition ¬ united, sourceFrom: ROPE ¬ NIL, skipAttributes: LIST OF ATOM ¬ NIL] = { IF sourceFrom # NIL THEN { IF structure THEN StructuredStreams.Begin[stream]; IO.PutF[stream, "(%lsource-file%l %g) ", [rope["n"]], [rope["N"]], [rope[Convert.RopeFromRope[sourceFrom]]]]; IF structure THEN StructuredStreams.End[stream]; IF structure THEN StructuredStreams.Bp[stream, breakCondition, 1]; }; PutTreeInternal[NEW[PutTreeOptionsRep ¬ [stream, structure, breakCondition, 0, skipAttributes]], tree]; }; PutTreeNode: PROC [p: PutTreeOptions, node: REF MPTree.Node, nodeName: ATOM, attributes: Attributes] = { IO.PutChar[p.stream, '(]; PutName[p, IF nodeName = NIL OR AtomFromNodeName[node.name] = nodeName THEN RopeFromNodeName[node.name] ELSE Atom.GetPName[nodeName]]; Bp[p]; PutAttributes[p, attributes]; FOR i: NAT IN [1..node.sonLimit) DO IO.PutChar[p.stream, ' ]; Bp[p]; PutTreeInternal[p, node.son[i]]; ENDLOOP; IO.PutChar[p.stream, ')]; }; PutHTNode: PROC [p: PutTreeOptions, ht: REF MPLeaves.HTNode, nodeName: ATOM, attributes: Attributes] = { IO.PutChar[p.stream, '(]; PutName[p, IF nodeName = NIL OR nodeName = $ID THEN "id" ELSE Atom.GetPName[nodeName]]; Bp[p]; PutAttributes[p, attributes]; Bp[p]; IO.PutF1[p.stream, "\"%g\"", IO.rope[ht.name]]; IO.PutChar[p.stream, ')]; IF (p.idcount ¬ p.idcount+1) MOD 10 = 0 THEN { WITH ProcessProps.GetProp[$StdOut] SELECT FROM log: IO.STREAM => { IO.PutChar[log, '.]; IF p.idcount MOD 100 = 0 THEN IO.PutChar[log, ' ]; }; ENDCASE => NULL; }; }; PutRopeNode: PROC [p: PutTreeOptions, rope: ROPE, attributes: Attributes] = { IO.PutF1[p.stream, "\"%g\"", IO.rope[rope]]; <> <> <> <> <> <> }; PutLTNode: PROC [p: PutTreeOptions, lit: REF MPLeaves.LTNode, nodeName: ATOM, attributes: Attributes] = { IO.PutChar[p.stream, '(]; PutName[p, IF nodeName = NIL OR nodeName = $LITERAL THEN "literal" ELSE Atom.GetPName[nodeName]]; IO.PutChar[p.stream, ' ]; PutAttributes[p, attributes]; IO.PutChar[p.stream, ' ]; WITH lit.value SELECT FROM c: REF CHAR => IO.PutF1[p.stream, "#\\%g", IO.char[c­]]; i: REF INT => IO.Put1[p.stream, IO.int[i­]]; i: REF INTEGER => IO.Put1[p.stream, IO.int[i­]]; i: REF DINT => IO.Put1[p.stream, IO.dint[i­]]; i: REF CARDINAL => IO.Put1[p.stream, IO.card[i­]]; i: REF CARD => IO.Put1[p.stream, IO.card[i­]]; i: REF DCARD => IO.Put1[p.stream, IO.dcard[i­]]; a: REF ATOM => IO.PutF1[p.stream, "|%g|", IO.rope[Atom.GetPName[a­]]]; r: REF REAL => IO.PutRope[p.stream, lit.literal]; r: REF ROPE => IO.PutRope[p.stream, lit.literal]; ENDCASE => {Huh[lit]; IO.PutRope[p.stream, lit.literal]}; IO.PutChar[p.stream, ')]; }; PutAttributes: PROC [p: PutTreeOptions, attributes: Attributes] = { RemoveProps: PROC [lora: LIST OF REF ANY] RETURNS [LIST OF REF ANY] = { IF lora = NIL THEN RETURN [NIL] ELSE { residual: LIST OF REF ANY = RemoveProps[lora.rest.rest]; FOR each: LIST OF ATOM ¬ p.skipAttributes, each.rest UNTIL each = NIL DO IF lora.first = each.first THEN RETURN [residual]; ENDLOOP; IF residual = lora.rest.rest THEN RETURN [lora]; RETURN [CONS[lora.first, CONS[lora.rest.first, residual]]] }; }; IF p.structure THEN StructuredStreams.Begin[p.stream]; PutLORA[p, RemoveProps[attributes]]; -- for now IF p.structure THEN StructuredStreams.End[p.stream]; }; PutLORA: PROC [p: PutTreeOptions, lora: LIST OF REF ANY] = { n: INT ¬ 0; IO.PutChar[p.stream, '(]; FOR each: LIST OF REF ANY ¬ lora, each.rest UNTIL each = NIL DO IF n # 0 THEN { Bp[p] }; PutTreeInternal[p, each.first]; n ¬ n + 1; ENDLOOP; IO.PutChar[p.stream, ')]; }; PutName: PROC [p: PutTreeOptions, name: ROPE] = { IF p.structure THEN IO.PutF1[p.stream, "%l", [rope["n"]]]; IO.PutChar[p.stream, ':]; -- make them commonlisp keywords IO.PutRope[p.stream, name]; IF p.structure THEN IO.PutF1[p.stream, "%l", [rope["N"]]]; }; PutTreeInternal: PROC [p: PutTreeOptions, tree: Tree] = { IF p.structure THEN StructuredStreams.Begin[p.stream]; WITH tree SELECT FROM lora: LIST OF REF ANY => { <> PutLORA[p, lora]; }; atom: ATOM => { <> escape: BOOL = NOT AllUpperCase[Atom.GetPName[atom]]; IF escape THEN IO.PutChar[p.stream, '|]; IO.PutChar[p.stream, ':]; -- make them commonlisp keywords IO.PutRope[p.stream, Atom.GetPName[atom]]; IF escape THEN IO.PutChar[p.stream, '|]; }; refINT: REF INT => { <> IO.Put1[p.stream, IO.int[refINT­]]; }; refDINT: REF DINT => { <> IO.Put1[p.stream, IO.dint[refDINT­]]; }; refCARD: REF CARD => { <> IO.Put1[p.stream, IO.card[refCARD­]]; }; refDCARD: REF DCARD => { <> IO.Put1[p.stream, IO.dcard[refDCARD­]]; }; rope: ROPE => { PutRopeNode[p, rope, NIL]; }; aNode: AttributedNode => { WITH aNode.syntaxNode SELECT FROM node: REF MPTree.Node => { PutTreeNode[p, node, aNode.syntaxNodeName, aNode.attributes]; }; ht: REF MPLeaves.HTNode => { PutHTNode[p, ht, aNode.syntaxNodeName, aNode.attributes]; }; lit: REF MPLeaves.LTNode => { PutLTNode[p, lit, aNode.syntaxNodeName, aNode.attributes]; }; rope: ROPE => { IO.PutChar[p.stream, '(]; PutName[p, "id"]; Bp[p]; PutAttributes[p, aNode.attributes]; Bp[p]; IO.PutF1[p.stream, "\"%g\"", IO.rope[rope]]; IO.PutChar[p.stream, ')]; }; ENDCASE => Huh[aNode.syntaxNode]; }; node: REF MPTree.Node => { PutTreeNode[p, node, NIL, DecodeAttr[node.name, node.attr]]; }; ht: REF MPLeaves.HTNode => { PutHTNode[p, ht, NIL, SourceLocAttribute[ht.index]]; }; lit: REF MPLeaves.LTNode => { PutLTNode[p, lit, NIL, SourceLocAttribute[lit.index]]; }; ENDCASE => { IF tree = NIL THEN IO.PutRope[p.stream, "NIL"] ELSE IO.Put1[stream: p.stream, value: [refAny[tree]]]; }; IF p.structure THEN StructuredStreams.End[p.stream]; }; SourceLocAttribute: PROC [sourceLoc: INT] RETURNS [Attributes] = { IF sourceLoc = INT.LAST THEN RETURN [NIL] ELSE RETURN [LIST[$AT, NEW[INT ¬ sourceLoc]]] }; AddAttributeNodes: PUBLIC PROC [tree: Tree] RETURNS [Tree] = { Wrap: PROC [t: Tree, name: ATOM, attributes: Attributes] RETURNS [Tree] = { aNode: AttributedNode ¬ NEW[AttributedNodeRep ¬ [attributes: attributes, syntaxNodeName: name, syntaxNode: t]]; RETURN [aNode]; }; IF tree = NIL THEN RETURN [NIL]; WITH tree SELECT FROM node: REF MPTree.Node => { IF node.name = $optionTC THEN { <> check: [2..2] ~ node.sonLimit; aNode: AttributedNode ~ NARROW[AddAttributeNodes[node.son[1]]]; name: ATOM ¬ NIL; value: REF ¬ NIL; intval: INT ¬ 0; SELECT node.subInfo FROM $packedOption => {name ¬ $PACKING; value ¬ $PACKED}; $msbitOption => {name ¬ $ENDIAN; value ¬ $MSBIT}; $lsbitOption => {name ¬ $ENDIAN; value ¬ $LSBIT}; $nativeOption => {name ¬ $ENDIAN; value ¬ $NATIVE}; $word8Option => {name ¬ $BITSPERWORD; intval ¬ 8}; $word16Option => {name ¬ $BITSPERWORD; intval ¬ 16}; $word32Option => {name ¬ $BITSPERWORD; intval ¬ 32}; $word64Option => {name ¬ $BITSPERWORD; intval ¬ 64}; ENDCASE; IF name # NIL THEN { IF value = NIL THEN value ¬ NEW[INT ¬ intval]; aNode.attributes ¬ CONS[name, CONS[value, aNode.attributes]]; }; RETURN [aNode] } ELSE { attributes: Attributes = DecodeAttr[node.name, node.attr]; FOR i: NAT IN [1..node.sonLimit) DO node.son[i] ¬ AddAttributeNodes[node.son[i]]; ENDLOOP; RETURN [Wrap[node, AtomFromNodeName[node.name], attributes]]; }; }; rope: ROPE => RETURN [Wrap[tree, $ID, NIL]]; ht: REF MPLeaves.HTNode => RETURN [Wrap[tree, $ID, SourceLocAttribute[ht.index]]]; lit: REF MPLeaves.LTNode => RETURN [Wrap[tree, $LITERAL, SourceLocAttribute[lit.index]]]; ENDCASE => { Huh[tree] }; RETURN [Wrap[tree, $ID, NIL]] }; WalkTree: PROC [tree: Tree] = { <> WITH tree SELECT FROM node: REF MPTree.Node => { n: NAT = node.sonLimit-1; -- number of sons True: TYPE = BOOL[TRUE..TRUE]; SELECT node.name FROM module => { check: True = (n=6); directory: Tree = node.son[1]; imports: Tree = node.son[2]; exports: Tree = node.son[3]; shares: Tree = node.son[4]; locks: Tree = node.son[5]; decl: Tree = node.son[6]; }; diritem => { check: True = (n=3); directoryItem: Tree = node.son[1]; from: Tree = node.son[2]; usingList: Tree = node.son[3]; }; lambda => { check: True = (n=2); decl: Tree = node.son[1]; body: Tree = node.son[2]; }; decl => { <> check: True = (n=3); identifier: Tree = node.son[1]; type: Tree = node.son[2]; value: Tree = node.son[3]; }; open => { check: True = (n=2); items: Tree = node.son[1]; -- an item with two (name, value) components, or list of same scope: Tree = node.son[2]; }; definitionTC => { <> check: True = (n=0); }; programTC => { <> check: True = (n=2); arguments: Tree = node.son[1]; returns: Tree = node.son[2]; }; monitoredTC => { <> check: True = (n=1); fieldList: Tree = node.son[1]; }; recordTC => { <> check: True = (n=1); fieldList: Tree = node.son[1]; -- often a list of decls }; unionTC => { <> check: True = (n=2); commonPart: Tree = node.son[1]; -- at least the tag field variants: Tree = node.son[2]; -- a list of typedecl nodes, with variantTC nodes for the types }; implicitTC => { <> check: True = (n=0); }; variantTC => { <> <> check: True = (n=1); fieldList: Tree = node.son[1]; }; sequenceTC => { <> check: True = (n=2); domainLimit: Tree = node.son[1]; -- a decl rangeType: Tree = node.son[2]; -- a type }; longTC, refTC, pointerTC => { check: True = (n=1); applyTo: Tree = node.son[1]; }; procTC, processTC => { <> check: True = (n=2); arguments: Tree = node.son[1]; returns: Tree = node.son[2]; }; errorTC, signalTC => { <> check: True = (n=2); arguments: Tree = node.son[1]; returns: Tree = node.son[2]; }; enumeratedTC => { <> check: True = (n=1); list: Tree = node.son[1]; }; listTC => { check: True = (n=1); elementType: Tree = node.son[1]; }; linkTC => { <> check: True = (n=0); }; anyTC => { <> check: True = (n=0); }; zoneTC => { <> check: True = (n=0); }; opaqueTC => { check: True = (n=1); x: Tree = node.son[1]; -- This is probably the size, if supplied }; arrayTC => { check: True = (n=2); domainType: Tree = node.son[1]; rangeType: Tree = node.son[2]; }; subrangeTC => { check: True = (n=2); baseType: Tree = node.son[1]; range: Tree = node.son[2]; -- should be an interval }; intCC, intCO, intOC, intOO => { <> check: True = (n=2); lower: Tree = node.son[1]; includeLower: BOOL = node.name=intCC OR node.name=intCO; upper: Tree = node.son[2]; includeUpper: BOOL = node.name=intCC OR node.name=intOC; }; inline => { <> <> check: True = (n=1); code: Tree = node.son[1]; -- a list of byte constants }; body => { <> check: True = (n=4); open: Tree = node.son[1]; declarations: Tree = node.son[2]; bodyContents: Tree = node.son[3]; exits: Tree = node.son[4]; }; block => { <> check: True = (n=2); declarations: Tree = node.son[1]; bodyContents: Tree = node.son[2]; }; entry, internal => { <> check: True = (n=1); body: Tree = node.son[1]; }; enable => { <> check: True = (n=2); catch: Tree = node.son[1]; block: Tree = node.son[2]; }; label => { <> check: True = (n=2); block: Tree = node.son[1]; labelledClauses: Tree = node.son[2]; -- a two-element item (or list of same?) }; goto => { <> check: True = (n=1); target: Tree = node.son[1]; -- an identifier }; typedecl => { <> check: True = (n=3); identifier: Tree = node.son[1]; type: Tree = node.son[2]; initialValue: Tree = node.son[3]; }; dot => { <> <> <> <> <> check: True = (n=2); outer: Tree = node.son[1]; inner: Tree = node.son[2]; }; apply => { <> <> <> <> <> nSons: [2..3] = n; operator: Tree = node.son[1]; operand: Tree = node.son[2]; catch: Tree = IF n = 3 THEN node.son[3] ELSE NIL; }; catch => { check: True = (n=2); items: Tree = node.son[1]; xx: Tree = node.son[2]; }; continue => { check: True = (n=0); }; return, resume => { <> check: True = (n=1); returnValue: Tree = node.son[1]; }; uparrow => { <> check: True = (n=1); pointer: Tree = node.son[1]; }; do => { check: True = (n=6); loopControl: Tree = node.son[1]; whileTest: Tree = node.son[2]; xxx: Tree = node.son[3]; -- probably decls bodyContents: Tree = node.son[4]; xxxxx: Tree = node.son[5]; -- probably funny stuff I don't use repeatFinished: Tree = node.son[6]; IF xxx#NIL OR xxxxx#NIL THEN Huh[node]; }; upthru, downthru => { <> check: True = (n=3); loopVariable: Tree = node.son[1]; -- may be a decl range: Tree = node.son[2]; xxx: Tree = node.son[3]; IF xxx#NIL THEN Huh[node]; }; forseq => { <> check: True = (n=3); loopVariable: Tree = node.son[1]; -- may be a decl initialValue: Tree = node.son[2]; nextValue: Tree = node.son[3]; }; loop, exit => { <> check: True = (n=0); }; fork, wait, broadcast, notify => { check: True = (n=1); what: Tree = node.son[1]; }; free => { check: True = (n=3); zone: Tree = node.son[1]; pointer: Tree = node.son[2]; whatsit: Tree = node.son[3]; }; if, ifx => { <> check: True = (n=3); test: Tree = node.son[1]; truePart: Tree = node.son[2]; falsePart: Tree = node.son[3]; }; bind, bindx => { < x; a:B => x ENDCASE...>> <> check: True = (n=4); expression: Tree = node.son[1]; xx: Tree = node.son[2]; items: Tree = node.son[3]; endcase: Tree = node.son[4]; }; case, casex => { <