aboutsummaryrefslogtreecommitdiff
path: root/src/interp/pspad2.boot
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/pspad2.boot')
-rw-r--r--src/interp/pspad2.boot663
1 files changed, 663 insertions, 0 deletions
diff --git a/src/interp/pspad2.boot b/src/interp/pspad2.boot
new file mode 100644
index 00000000..e5af3357
--- /dev/null
+++ b/src/interp/pspad2.boot
@@ -0,0 +1,663 @@
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+-- Copyright (C) 2007, Gabriel Dos Reis.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+-- - Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+--
+-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+-- names of its contributors may be used to endorse or promote products
+-- derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+)package "BOOT"
+
+--======================================================================
+-- Constructor Transformation Functions
+--======================================================================
+formatDeftranForm(form,tlist) ==
+ [ttype,:atypeList] := tlist
+ if form is [":",f,t] then
+ form := f
+ ttype := t
+ if form is ['elt,a,b] then ----> a.b ====> apply(b,a)
+ form :=
+ isTypeProbably? a =>
+ atypeList := REVERSE atypeList
+ ["$$", b, a]
+ ["apply",a, b]
+ op := KAR form
+ argl := KDR form
+ if or/[t for t in atypeList] then
+ form := [op,:[(t => [":",a,t]; a) for a in argl for t in atypeList]]
+ if ttype then form := [":",form,ttype]
+ form
+
+formatDeftran(u,SEQflag) ==
+ u is ['Join,:x] => formatDeftranJoin(u,SEQflag)
+ u is ['CATEGORY,kind,:l,x] => formatDeftran(['with,['SEQ,:l,['exit,n,x]]],SEQflag)
+ u is ['CAPSULE,:l,x] => formatDeftranCapsule(l,x,SEQflag)
+ u is [op,:.] and MEMQ(op,'(rep per)) => formatDeftranRepper(u,SEQflag)
+ u is [op,:.] and MEMQ(op,'(_: _:_: _pretend _@)) =>
+ formatDeftranColon(u,SEQflag)
+ u is ['PROGN,:l,x] => formatDeftran(['SEQ,:l,['exit,1,x]],SEQflag)
+ u is ['SEQ,:l,[.,n,x]] =>
+ v := [:l,x]
+ a := "APPEND"/[formatDeftranSEQ(x,true) for x in l]
+ b := formatDeftranSEQ(x,false)
+ if b is [:.,c] and c = '(void) then b := DROP(-1, b)
+ [:m,y] := [:a,:b]
+ ['SEQ,:m,['exit,n,y]]
+-- u is ['not,arg] and (op := LASSOC(KAR arg,'((_= . _^_=) (_< . _>_=)))) =>
+-- formatDeftran([op,:CDR arg],nil)
+ u is ["^",a] => formatDeftran(['not,a],SEQflag)
+ u is ["exquo",a,b] => formatDeftran(['xquo,a,b],SEQflag)
+ u is ['IF,a,b,c] =>
+ a := formatDeftran(a,nil)
+ b := formatDeftran(b,nil)
+ c := formatDeftran(c,nil)
+ null SEQflag and $insideDEF =>
+ [:y,last] := formatDeftranIf(a,b,c)
+ ['SEQ,:y,['exit,1,last]]
+ ['IF,a,b,c]
+ u is ['Union,:argl] =>
+ ['Union,:[x for a in argl
+ | x := (STRINGP a => [":",INTERN a,'Branch]; formatDeftran(a,nil))]]
+ u is [op,:itl,body] and MEMQ(op,'(REPEAT COLLECT)) and
+ ([nitl,:nbody] := formatDeftranREPEAT(itl,body)) =>
+ formatDeftran([op,:nitl,nbody],SEQflag)
+ u is [":",a,b] => [":",formatDeftran(a,nil),formatDeftran(markMacroTran(b),nil)]
+ u is ["DEF",:.] => formatCapsuleFunction(u)
+ u is [op,:argl]=>[formatDeftran(op,nil),:[formatDeftran(x,nil) for x in argl]]
+ u = 'nil => 'empty
+ u
+
+formatCapsuleFunction ["DEF",form,tlist,b,body] ==
+ $insideDEF : local := true
+ ["DEF", formatDeftran(form,nil),tlist,b,formatDeftran(body,nil)]
+
+formatDeftranCapsule(l,x,SEQflag) ==
+ $insideCAPSULE: local := true
+ formatDeftran(['SEQ,:l,['exit,1,x]],SEQflag)
+
+formatDeftranRepper([op,a],SEQflag) ==
+ a is [op1,b] and MEMQ(op1,'(rep per)) =>
+ op = op1 => formatDeftran(a,SEQflag)
+ formatDeftran(b,SEQflag)
+ a is ["::",b,t] =>
+ b := formatDeftran(b,SEQflag)
+ t := formatDeftran(t,SEQflag)
+ a := ["::",b,t]
+ op = 'per and t = "$" or op = 'rep and t = 'Rep => a
+ [op,a]
+ a is ['SEQ,:r] => ['SEQ,:[formatSeqRepper(op,x) for x in r]]
+ a is ['IF,p,b,c] =>
+ formatDeftran(['IF,p,[op,b],[op, c]], SEQflag)
+ a is ['LET,a,b] => formatDeftran(['LET,a,[op,b]],SEQflag)
+ a is ['not,[op,a,b]] and (op1 := LASSOC(op,$pspadRelationAlist)) =>
+ formatDeftran [op1,a,b]
+ a is ['return,n,r] =>
+ MEMQ(opOf r,'(true false)) => a
+ ['return,n,[op,formatDeftran(r,SEQflag)]]
+ a is ['error,:.] => a
+ [op,formatDeftran(a,SEQflag)]
+
+formatDeftranColon([op,a,t],SEQflag) == --op is one of : :: pretend @
+ a := formatDeftran(a,SEQflag)
+ t := formatDeftran(t,SEQflag)
+ a is ["UNCOERCE",b] => b
+ a is [op1,b,t1] and t1 = t and MEMQ(op,'(_: _:_: _pretend _@)) =>
+ op1 = "pretend" or op = "pretend" => ["pretend",b,t]
+ null SEQflag and op1 = ":" or op = ":" => ["pretend",b,t]
+ a
+ a is [=op,b,t1] =>
+ t1 = t => a
+ [op,b,t]
+ t = "$" =>
+ a is ['rep,b] => b
+ a is ['per,b] => a
+ [op,a,t]
+ t = "Rep" =>
+ a is ['per,b] => b
+ a is ['rep,b] => a
+ [op,a,t]
+ [op,a,t]
+
+formatSeqRepper(op,x) ==
+ x is ['exit,n,y] => ['exit,n,[op,formatDeftran(y,nil)]]
+ x is ["=>",a,b] => ["=>",formatDeftran(a,nil),[op,formatDeftran(b,nil)]]
+ atom x => x
+ [formatSeqRepper(op,y) for y in x]
+
+formatDeftranJoin(u,SEQflag) ==
+ ['Join,:cats,lastcat] := u
+ lastcat is ['CATEGORY,kind,:l,x] =>
+ cat :=
+ CDR cats => ['Join,:cats]
+ first cats
+ formatDeftran(['with,cat,['SEQ,:l,['exit,1,x]]],SEQflag)
+ u
+
+formatENUM ['MyENUM, x] == format "'" and format x and format "'"
+
+formatDeftranREPEAT(itl,body) ==
+--do nothing unless "itl" contains UNTIL statements
+ u := [x for x in itl | x is ["UNTIL",p]] or return nil
+ nitl := SETDIFFERENCE(itl,u)
+ pred := MKPF([p for ['UNTIL,p] in u],'or)
+ cond := ['IF,pred,['leave,n,nil],'noBranch]
+ nbody :=
+ body is ['SEQ,:l,[.,n,x]] => ['SEQ,:l,x,['exit,n,cond]]
+ ['SEQ,body,['exit,n,cond]]
+ [nitl,:nbody]
+
+formatDeftranSEQ(x,flag) ==
+ u := formatDeftran(x,flag)
+ u is ['SEQ,:.] => rest u
+ [u]
+
+formatDeftranIf(a,b,c) ==
+ b = 'noBranch =>
+ a is [op,:r] and (al := '((_= . _~_=) (_< . _>_=) (_> . _<_=));
+ iop := LASSOC(op, al) or rassoc(op, al)) =>
+ [["=>",[iop, :r],c]]
+ a is [op,r] and MEMQ(op,'(NOT not NULL null)) =>
+ [["=>", r, c]]
+ [["=>", ['not, a], c]]
+ post :=
+ c = 'noBranch => nil
+ c is ['SEQ,:.] => CDR c
+ [c]
+ [["=>",a,b],:post]
+
+formatWHERE ["where",a,b] ==
+ $insideTypeExpression: local := nil
+ $insideCAPSULE: local := false
+ tryBreak(formatLeft("format",a,"where","Led") and format " where ",b,"where","Led")
+
+--======================================================================
+-- Special Handlers: Categories
+--======================================================================
+formatATTRIBUTE ['ATTRIBUTE,att] == format att
+
+formatDeftranCategory ['CATEGORY,kind,:items,item] == ["SEQ",:items,["exit",1,item]]
+
+formatCategory ['Category] == format " " and format "Category"
+
+formatCATEGORY cat ==
+ con := opOf $form
+ $comments: local := SUBST('_$,'_%,GETDATABASE(con,'DOCUMENTATION))
+ $insideEXPORTS : local := true
+ format ["with",formatDeftranCategory cat]
+
+formatSIGNATURE ['SIGNATURE,op,types,:r] ==
+ MEMQ('constant,r) => format op and format ": " and (u := format first types) and
+ formatSC() and formatComments(u,op,types)
+ format op and format ": " and (u := format ['Mapping,:types]) and formatSC() and
+ formatComments(u,op,types)
+
+formatDefault ["default",a] ==
+ $insideCategoryIfTrue : local := false
+ $insideCAPSULE: local := true
+ $insideTypeExpression: local := false
+ tryBreak(format "default ",a,"with","Nud")
+--======================================================================
+-- Special Handlers: Control Structures
+--======================================================================
+formatUNCOERCE ['UNCOERCE,x] == format x
+
+formatIF ['IF,a,b,c] ==
+ c = 'noBranch => formatIF2(a,b,"if ")
+ b = 'noBranch => formatIF ['IF,['not,a],c,'noBranch]
+ formatIF2(a,b,"if ") and newLine() and formatIF3 c
+
+formatIF2(a,b,prefix) ==
+ tryBreakNB(format prefix and format a and format " then ",b,"then","Nud")
+
+formatIF3 x ==
+ x is ['IF,a,b,c] =>
+ c = 'noBranch => tryBreak(format "else if "
+ and format a and format " then ",b,"then","Nud")
+ formatIF2(a,b,"else if ") and newLine() and formatIF3 c
+ tryBreak(format "else ",x,"else","Nud")
+
+formatBlock(l,x) ==
+ null l => format x
+ $pilesAreOkHere: local
+ format "{ " and format first l and
+ (and/[formatSC() and format y for y in rest l])
+ and formatSC() and format x and format " }"
+
+formatExit ["exit",.,u] == format u
+
+formatvoid ["void"] == format "()"
+
+formatLeave ["leave",.,u] == format "break"
+
+formatCOLLECT u == formatSpill("formatCOLLECT1",u)
+
+formatCOLLECT1 ["COLLECT",:iteratorList,body] ==
+ $pilesAreOkHere: local
+ format "[" and format body and format " " and
+ formatSpill("formatIteratorTail",iteratorList)
+
+formatIteratorTail iteratorList ==
+ formatIterator first iteratorList and
+ (and/[format " " and formatIterator x for x in rest iteratorList]) and format "]"
+
+--======================================================================
+-- Special Handlers: Keywords
+--======================================================================
+
+formatColon [":",a,b] ==
+ b is ['with,c,:d] => formatColonWith(a,c,d)
+ if not $insideTypeExpression then
+ insideCat() => nil
+ format
+ $insideDEF => "local "
+ "default "
+ op :=
+ $insideCAPSULE and not $insideDEF => ": "
+ insideCat() => ": "
+ ":"
+ b := (atom b => b; markMacroTran b)
+ a is ['LISTOF,:c] => formatComma c and format ": " and formatLocal1 b
+ formatInfix(op,[a, b],formatOpBindingPower(":","Led","left"),
+ formatOpBindingPower(":","Led","right"))
+
+formatColonWith(form,a,b) ==
+ con := opOf $form
+ $comments: local := SUBST('_$,'_%,GETDATABASE(con,'DOCUMENTATION))
+ $insideEXPORTS : local := true
+ $pilesAreOkHere: local := true
+ $insideTypeExpression : local := false
+ b => tryBreak(formatDefForm form and format ": "
+ and format a and format " with ",first b,"with","Led")
+ tryBreak(formatDefForm form and format ": with ",a,"with","Nud")
+
+formatCOND ["COND",:l] ==
+ originalC:= $c
+ and/[x is [a,[.,.,b]] for x in l] =>
+ (originalC=$m or indent() and newLine()) and first l is [a,[.,.,b]] and
+ formatIfExit(a,b) and
+ (and/[newLine() and formatIfExit(a,b) for [a,[.,.,b]] in rest l]) and (originalC=$m or undent()) and originalC
+ formatIfThenElse l
+
+formatPROGN ["PROGN",:l] ==
+ l is [:u,x] => formatPiles(u,x)
+ error '"formatPROGN"
+
+formatELT ["ELT",a,b] == formatApplication [a,b]
+
+formatCONS ["CONS",a,b] ==
+ $pilesAreOkHere: local
+ format "[" and formatConstructItem a and formatTail b
+
+formatTail x ==
+ null x => format "]"
+ format "," and formatTail1 x
+
+formatTail1 x ==
+ x is ["CONS",a,b] => formatConstructItem a and formatTail b
+ x is ["APPEND",a,b] =>
+ null b => formatConstructItem a and format "]"
+ format ":" and formatConstructItem a and formatTail b
+ format ":" and formatConstructItem x and format "]"
+
+-- x = "." => format " "
+formatConstructItem x == format x
+
+formatLET ["LET",a,b] ==
+ $insideTypeExpression: local := true
+ a = "Rep" or atom a and constructor? opOf b =>
+ tryBreakNB(formatAtom a and format " == ",b,":=","Led")
+ tryBreakNB((IDENTP a => formatAtom a; format a) and format " := ",b,":=","Led")
+
+formatIfExit(a,b) ==
+ --called from SCOND or COND only
+ $numberOfSpills: local:= 0
+ curMargin:= $m
+ curMarginStack:= $currentMarginStack
+ $doNotResetMarginIfTrue:= true
+ format a and format " => " and formatRight("formatCut",b,"=>","Led") =>
+ ($currentMarginStack:= curMarginStack; $m:= curMargin)
+
+formatIfThenElse x == formatSpill("formatIf1",x)
+
+formatIf1 x ==
+ x is [[a,:r],:c] and null c =>
+ b:=
+ r is [:l,s] and l => ['SEQ,:l,['exit,.,s]]
+ first r
+ isTrue a => format b
+ format "if " and format a and format " then " and format b
+ format "if " and format a and
+ (try
+ (format " then " and format b and format " else "
+ and formatIfThenElse c) or spillLine()
+ and format " then " and format b and
+-- ($c:= $m:= $m+6) and
+ ($numberOfSpills:= $numberOfSpills-1)
+ and spillLine() and format " else " and formatIfThenElse c)
+
+formatQUOTE ["QUOTE",x] == format "('" and format x and format ")"
+
+formatMI ["MI",a,b] == format a
+
+formatMapping ['Mapping,target,:sources] ==
+ $noColonDeclaration: local := true
+ formatTuple ['Tuple,:sources] and format " -> " and format target
+
+formatTuple ['Tuple,:types] ==
+ null types => format "()"
+ null rest types => format first types
+ formatFunctionCallTail types
+
+formatConstruct(['construct,:u]) ==
+ format "[" and (null u or format first u and
+ "and"/[format "," and formatCut x for x in rest u]) and format "]"
+
+formatNextConstructItem x ==
+ try format x or ($m := $m + 2) and newLine() and format x
+
+formatREPEAT ["REPEAT",:iteratorList,body] ==
+ tryBreakNB(null iteratorList or (formatIterator first iteratorList and
+ (and/[format " " and formatIterator x for x in rest iteratorList]) and format " ")
+ and format "repeat ",body,"repeat","Led")
+
+formatFATARROW ["=>",a,b] == tryBreak(format a and format " => ",b,"=>","Led")
+
+formatMap ["+->",a,b] ==
+ $noColonDeclaration: local := true
+ tryBreak(format a and format " +-> ", b, "+->","Led")
+
+formatREDUCE ["REDUCE",op,.,u] == formatReduce1(op,u)
+
+formatreduce ["reduce",op,u] == formatReduce1(op,u)
+
+formatReduce1(op,u) ==
+ if STRINGP op then op := INTERN op
+ id := LASSOC(op,
+ '((_+ Zero)(_* One)(append . NIL)(gcd Zero) (lcm One) (strconc . "")(lcm One)))
+ formatFunctionCall
+ id => ['reduce,op,u,id]
+ ['reduce,op,u]
+
+formatIterator u ==
+ $noColonDeclaration : local := true
+ u is ["IN",x,y] =>
+ format "for " and formatLeft("format",x,"in","Led") and format " in " and
+ formatRight("format",y,"in","Led")
+ u is ["WHILE",x] => format "while " and formatRight("format",x,"while","Nud")
+ u is ["UNTIL",x] => format "until " and formatRight("format",x,"until","Nud")
+ u is ["|",x] => format "| " and formatRight("format",x,"|","Led")
+ u is ["STEP",i,init,step,:v] =>
+ final := IFCAR v
+ format "for " and formatLeft("format",i,"in","Led") and format " in " and
+ (seg := ['SEGMENT,init,final]) and (formatStepOne? step => format seg; formatBy ['by,seg,step])
+ error "formatIterator"
+
+formatStepOne? step ==
+ step = 1 or step = '(One) => true
+ step is [op,n,.] and MEMQ(op,'(_:_: _@)) => n = 1 or n = '(One)
+ false
+
+formatBy ['by,seg,step] == format seg and format " by " and format step
+
+formatSCOND ["SCOND",:l] ==
+ $pilesAreOkHere =>
+ --called from formatPileLine or formatBlock
+ --if from formatPileLine
+ initialC:= $c
+ and/[x is [a,["exit",.,b]] for x in l] =>
+ first l is [a,["exit",.,b]] and formatIfExit(a,b) and
+ (and/[newLine() and formatIfExit(a,b) for [a,["exit",.,b]] in rest l]) and initialC
+ formatIfThenElse l and initialC
+ and/[x is [a,["exit",.,b]] for x in l] =>
+ first l is [a,["exit",.,b]] and formatIfExit(a,b) and
+ (and/[format "; " and formatIfExit(a,b) for [a,["exit",.,b]] in rest l]) and $c
+ --warning: and/(...) returns T if there are no entries
+ formatIfThenElse l
+
+formatSEGMENT ["SEGMENT",a,b] ==
+ $pilesAreOkHere: local
+ (if pspadBindingPowerOf("right",a)<750 then formatPren a else format a) and
+ formatInfixOp ".." and
+ (null b and $c or
+ (if 750>pspadBindingPowerOf("left",b) then formatPren b else format b))
+
+formatSexpr x ==
+ atom x =>
+ null x or IDENTP x => consBuffer ident2PrintImage PNAME x
+ consBuffer x
+ spill("formatNonAtom",x)
+
+formatNonAtom x ==
+ format "_(" and formatSexpr first x and
+ (and/[format " " and formatSexpr y for y in rest x])
+ and (y:= LASTATOM x => format " . "
+ and formatSexpr y; true) and format "_)"
+
+formatCAPSULE ['CAPSULE,:l,x] ==
+ $insideCAPSULE: local := true
+ try formatBlock(l,x) or formatPiles(l,x) or spillLine() and formatBlock(l,x)
+
+formatPAREN [.,:argl] == formatFunctionCallTail argl
+
+formatSEQ ["SEQ",:l,[.,.,x]] ==
+ try formatBlock(l,x) or formatPiles(l,x) or spillLine() and formatBlock(l,x)
+
+--======================================================================
+-- Comment Handlers
+--======================================================================
+formatCOMMENT ["COMMENT",x,marg,startXY,endXY,commentStack] ==
+ $commentsToPrint:= [[marg,startXY,endXY,commentStack],:$commentsToPrint]
+ format x
+
+formatComments(u,op,types) ==
+ $numberOfSpills :local := $commentIndentation/2 - 1
+ not $insideEXPORTS => u
+ alist := LASSOC(op,$comments) or
+ sayBrightly ['"No documentation for ",op]
+ return u
+ ftypes := SUBLISLIS($FormalMapVariableList,rest $form,types)
+ consComments(LASSOC(ftypes,alist),'"++ ")
+ u
+
+consComments(s,plusPlus) ==
+ s is [word,:r] and null atom r => consComments(r, plusPlus)
+ s := first s
+ null s => nil
+ s := consCommentsTran s
+ indent() and newLine() or return nil
+ columnsLeft := $lineLength - $m - 2
+ while (m := MAXINDEX s) >= columnsLeft repeat
+ k := or/[i for i in (columnsLeft - 1)..1 by -1 | s.i = $charBlank]
+ k := (k => k + 1; columnsLeft)
+ piece := SUBSTRING(s,0,k)
+ formatDoCommentLine [plusPlus,piece]
+ s := SUBSTRING(s,k,nil)
+ formatDoCommentLine [plusPlus,s]
+ undent()
+ $m
+
+consCommentsTran s ==
+ m := MAXINDEX s
+ k := or/[i for i in 0..(m - 7) | substring?('"\spad{",s,i)] =>
+ r := charPosition(char '_},s,k + 6)
+ r = m + 1 => s
+ STRCONC(SUBSTRING(s,0,k),'"`",SUBSTRING(s,k+6,r-k-6),'"'",consCommentsTran SUBSTRING(s,r+1,nil))
+ s
+
+formatDoCommentLine line ==
+ $lineBuffer := consLineBuffer [nBlanks $c,:line]
+ $c := $m+2*$numberOfSpills
+
+--======================================================================
+-- Pile Handlers
+--======================================================================
+formatPreferPile y ==
+ y is ["SEQ",:l,[.,.,x]] =>
+ (u:= formatPiles(l,x)) => u
+ formatSpill("format",y)
+ formatSpill("format",y)
+
+formatPiles(l,x) ==
+ $insideTypeExpression : local := false
+ not $pilesAreOkHere => nil
+ originalC:= $c
+ lines:= [:l,x]
+ --piles must begin at margin
+ originalC=$m or indent() and newLine() or return nil
+ null (formatPileLine($m,first lines,false)) => nil
+ not (and/[formatPileLine($m,y,true) for y in rest lines]) => nil
+ (originalC=$m or undent()) and originalC --==> brace
+
+formatPileLine($m,x,newLineIfTrue) ==
+ if newLineIfTrue then newLine() or return nil
+ $numberOfSpills: local:= 0
+ $newLineWritten := nil
+ format x and (x is ['SIGNATURE,:.] or $rightBraceFlag => $c; formatSC())
+ and (x is ['DEF,:.] and optNewLine() or $c)
+
+--======================================================================
+-- Utility Functions
+--======================================================================
+nBlanks m == "STRCONC"/[char('_ ) for i in 1..m]
+
+isNewspadOperator op == GET(op,"Led") or GET(op,"Nud")
+
+isTrue x == x="true" or x is '(QUOTE T)
+
+nary2Binary(u,op) ==
+ u is [a,b,:t] => (t => nary2Binary([[op,a,b],:t],op); [op,a,b])
+ errhuh()
+
+string2PrintImage s ==
+ u:= GETSTR (2*SIZE s)
+ for i in 0..MAXINDEX s repeat
+ (if MEMQ(s.i,'(_( _{ _) _} _! _")) then
+ SUFFIX('__,u); u:= SUFFIX(s.i,u))
+ u
+
+ident2PrintImage s ==
+ m := MAXINDEX s
+ if m > 1 and s.(m - 1) = $underScore then s := STRCONC(SUBSTRING(s,0,m-1),s.m)
+ u:= GETSTR (2*SIZE s)
+ if not (ALPHA_-CHAR_-P s.(0) or s.(0)=char '"$") then SUFFIX('__,u)
+ u:= SUFFIX(s.(0),u)
+ for i in 1..MAXINDEX s repeat
+ if not (DIGITP s.i or ALPHA_-CHAR_-P s.i or ((c := s.i) = char '?)
+ or (c = char '_!)) then SUFFIX('__,u)
+ u:= SUFFIX(s.i,u)
+ INTERN u
+
+isIdentifier x ==
+ IDENTP x =>
+ s:= PNAME x
+ #s = 0 => nil
+ ALPHA_-CHAR_-P s.(0) => and/[s.i^=char '" " for i in 1..MAXINDEX s]
+ #s>1 =>
+ or/[ALPHA_-CHAR_-P s.i for i in 1..(m:= MAXINDEX s)] =>
+ and/[s.i^=char '" " for i in 1..m] => true
+
+isGensym x ==
+ s := STRINGIMAGE x
+ n := MAXINDEX s
+ s.0 = char '_G and and/[DIGITP s.i for i in 1..n]
+
+--======================================================================
+-- Macro Helpers
+--======================================================================
+tryToFit(s,x) ==
+--% try to format on current line; see macro try in file PSPADAUX LISP
+ --returns nil if unable to format stuff in x on a single line
+ x => ($back:= rest $back; $c)
+ restoreState()
+ nil
+
+restoreState(:options) ==
+ back := IFCAR options or $back
+ [
+ [$lineBuffer, $lineFragmentBuffer,$comments,$marginStack,$braceStack,$DEFdepth,
+ $bc,$c,$m,$commentsToPrint,$numberOfSpills,flags], :back]
+ := back
+ if null options then $back := back
+ [$newLineWritten, $autoLine, $rightBraceFlag,
+ $semicolonFlag,$insideDEF,$insideTypeExpression,$pilesAreOkHere,
+ $insideEXPORTS, $insideCAPSULE, $insideCategoryIfTrue,
+ $doNotResetMarginIfTrue,$noColonDeclaration]
+ := flags
+ nil
+
+saveState(:options) ==
+ flags :=
+ [$newLineWritten, $autoLine, $rightBraceFlag,
+ $semicolonFlag,$insideDEF,$insideTypeExpression,$pilesAreOkHere,
+ $insideEXPORTS, $insideCAPSULE, $insideCategoryIfTrue,
+ $doNotResetMarginIfTrue,$noColonDeclaration]
+ newState :=
+ [
+ [$lineBuffer, $lineFragmentBuffer,$comments,$marginStack,$braceStack,$DEFdepth,
+ $bc,$c,$m,$commentsToPrint,$numberOfSpills,flags], :$back]
+ if not KAR options then $back := newState
+ newState
+
+formatSC() ==
+ $pileStyle or $semicolonFlag => $c
+ format "; "
+
+wrapBraces(x,y,z) == y
+
+formatLB() ==
+ $pileStyle => $c
+ $numberOfSpills :=
+ $c > $lineLength / 2 => $braceIndentation/3 - 1
+ $braceIndentation/2 - 1
+ format "{"
+
+restoreC() == --used by macro "embrace"
+ originalC := CAR $braceStack
+ $braceStack := CDR $braceStack
+ formatRB originalC
+
+saveC() == --used by macro "embrace"
+ $braceStack := [$c,:$braceStack]
+
+saveD() == --used by macro "embrace"
+ $braceStack := [$c,:$braceStack]
+
+restoreD() == --used by macro "indentNB"
+ originalC := CAR $braceStack
+ $braceStack := CDR $braceStack
+ originalC
+
+formatRB(originalC) == --called only by restoreC
+ while $marginStack and $m > originalC repeat undent()
+ if $m < originalC then $marginStack := [originalC,:$marginStack]
+ $m := originalC
+ $pileStyle => $m
+ newLine() and format "}" and $m --==> brace
+