diff options
Diffstat (limited to 'src/interp/i-syscmd.boot.pamphlet')
-rw-r--r-- | src/interp/i-syscmd.boot.pamphlet | 3103 |
1 files changed, 3103 insertions, 0 deletions
diff --git a/src/interp/i-syscmd.boot.pamphlet b/src/interp/i-syscmd.boot.pamphlet new file mode 100644 index 00000000..e846b570 --- /dev/null +++ b/src/interp/i-syscmd.boot.pamphlet @@ -0,0 +1,3103 @@ +\documentclass{article} +\usepackage{axiom} + +\title{\File{src/interp/i-syscmd.boot} Pamphlet} +\author{The Axiom Team} + +\begin{document} +\maketitle +\begin{abstract} +\end{abstract} +\eject +\tableofcontents +\eject + +\begin{verbatim} +This file contains the BOOT code for the Axiom system command +and synonym processing facility. The code for )trace is in the file +TRACE BOOT. The list of system commands is $SYSCOMMANDS which is +initialized in SETQ LISP. + +\end{verbatim} + +\section{Filenames change} + +It appears that probe-file is now case-sensitive. In order to get around +this we include the file extensions in both upper and lower case in the +search lists. Lower case names are preferred. + +\section{handleNoParseCommands} + +The system commands given by the global variable +[[|$noParseCommands|]]\cite{1} require essentially no +preprocessing/parsing of their arguments. Here we dispatch the +functions which implement these commands. + +There are four standard commands which receive arguments -- [[lisp]], +[[synonym]], [[system]] and [[boot]]. There are five standard commands +which do not receive arguments -- [[quit]], [[fin]], [[pquit]], +[[credits]] and [[copyright]]. As these commands do not necessarily +exhaust those mentioned in [[|$noParseCommands|]], we provide a +generic dispatch based on two conventions: commands which do not +require an argument name themselves, those which do have their names +prefixed by [[np]]. + +<<handleNoParseCommands>>= +handleNoParseCommands(unab, string) == + string := stripSpaces string + spaceIndex := SEARCH('" ", string) + unab = "lisp" => + if (null spaceIndex) then + sayKeyedMsg("S2IV0005", NIL) + nil + else nplisp(stripLisp string) + unab = "boot" => + if (null spaceIndex) then + sayKeyedMsg("S2IV0005", NIL) + nil + else npboot(SUBSEQ(string, spaceIndex+1)) + unab = "system" => + if (null spaceIndex) then + sayKeyedMsg("S2IV0005", NIL) + nil + else npsystem(unab, string) + unab = "synonym" => + npsynonym(unab, (null spaceIndex => '""; SUBSEQ(string, spaceIndex+1))) + null spaceIndex => + FUNCALL unab + member(unab, '( quit _ + fin _ + pquit _ + credits _ + copyright )) => + sayKeyedMsg("S2IV0005", NIL) + nil + funName := INTERN CONCAT('"np",STRING unab) + FUNCALL(funName, SUBSEQ(string, spaceIndex+1)) + +@ +\section{TRUENAME change} +This change was made to make the open source Axiom work with the +new aldor compiler.z +This used to read: +\begin{verbatim} + STRCONC(TRUENAME(STRCONC(GETENV('"AXIOM"),'"/compiler/bin/")),"axiomxl ", asharpArgs, '" ", namestring args) +\end{verbatim} +but now reads: +<<remove TRUENAME>>= + STRCONC(STRCONC(GETENV('"ALDORROOT"),'"/bin/"),_ + "aldor ", asharpArgs, '" ", namestring args) +@ +Notice that we've introduced the [[ALDORROOT]] shell variable. +This will have to be pushed down from the top level Makefile. + +\section{License} +<<license>>= +-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. +-- 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. + +@ +<<*>>= +<<license>> + +--% Utility Variable Initializations + +SETANDFILEQ($cacheAlist,nil) +SETANDFILEQ($reportCompilation,nil) +SETANDFILEQ($compileRecurrence,true) +SETANDFILEQ($errorReportLevel,'warning) +SETANDFILEQ($sourceFileTypes,'(INPUT SPAD BOOT LISP LISP370 META)) + +SETANDFILEQ($SYSCOMMANDS,[CAR x for x in $systemCommands]) + + +SETANDFILEQ($whatOptions, '( _ + operations _ + categories _ + domains _ + packages _ + commands _ + synonyms _ + things _ + )) + +SETANDFILEQ($clearOptions, '( _ + modes _ + operations _ + properties _ + types _ + values _ + )) + +SETANDFILEQ($displayOptions, '( _ + abbreviations _ + all _ + macros _ + modes _ + names _ + operations _ + properties _ + types _ + values _ + )) + +SETANDFILEQ($countAssoc,'( (cache countCache) )) + +--% Top level system command + +initializeSystemCommands() == + l := $systemCommands + $SYSCOMMANDS := NIL + while l repeat + $SYSCOMMANDS := CONS(CAAR l, $SYSCOMMANDS) + l := CDR l + $SYSCOMMANDS := NREVERSE $SYSCOMMANDS + +systemCommand [[op,:argl],:options] == + $options: local:= options + $e:local := $CategoryFrame + fun := selectOptionLC(op,$SYSCOMMANDS,'commandError) + argl and (argl.0 = '_?) and fun ^= 'synonym => + helpSpad2Cmd [fun] + fun := selectOption(fun,commandsForUserLevel $systemCommands, + 'commandUserLevelError) + FUNCALL(fun, argl) + +commandsForUserLevel l == --[a for [a,:b] in l | satisfiesUserLevel(a)] + c := nil + for [a,:b] in l repeat + satisfiesUserLevel b => c := [a,:c] + reverse c + +synonymsForUserLevel l == + -- l is a list of synonyms, and this returns a sublist of applicable + -- synonyms at the current user level. + $UserLevel = 'development => l + nl := NIL + for syn in reverse l repeat + cmd := STRING2ID_-N(CDR syn,1) + null selectOptionLC(cmd,commandsForUserLevel + $systemCommands,NIL) => nil + nl := [syn,:nl] + nl + +satisfiesUserLevel x == + x = 'interpreter => true + $UserLevel = 'interpreter => false + x = 'compiler => true + $UserLevel = 'compiler => false + true + +unAbbreviateKeyword x == + x' :=selectOptionLC(x,$SYSCOMMANDS,'commandErrorIfAmbiguous) + if not x' then + x' := 'system + SETQ(LINE, CONCAT('")system ", SUBSTRING(LINE, 1, #LINE-1))) + $currentLine := LINE + selectOption(x',commandsForUserLevel $systemCommands, + 'commandUserLevelError) + +hasOption(al,opt) == + optPname:= PNAME opt + found := NIL + for pair in al while not found repeat + stringPrefix?(PNAME CAR pair,optPname) => found := pair + found + +selectOptionLC(x,l,errorFunction) == + selectOption(DOWNCASE object2Identifier x,l,errorFunction) + +selectOption(x,l,errorFunction) == + member(x,l) => x --exact spellings are always OK + null IDENTP x => + errorFunction => FUNCALL(errorFunction,x,u) + nil + u := [y for y in l | stringPrefix?(PNAME x,PNAME y)] + u is [y] => y + errorFunction => FUNCALL(errorFunction,x,u) + nil + +terminateSystemCommand() == TERSYSCOMMAND() + +commandUserLevelError(x,u) == userLevelErrorMessage("command",x,u) + +optionUserLevelError(x,u) == userLevelErrorMessage("option",x,u) + +userLevelErrorMessage(kind,x,u) == + null u => + sayKeyedMsg("S2IZ0007",[$UserLevel,kind]) + terminateSystemCommand() + commandAmbiguityError(kind,x,u) + +commandError(x,u) == commandErrorMessage("command",x,u) + +optionError(x,u) == commandErrorMessage("option",x,u) + +commandErrorIfAmbiguous(x, u) == + null u => nil + SETQ($OLDLINE, LINE) + commandAmbiguityError("command", x, u) + +commandErrorMessage(kind,x,u) == + SETQ ($OLDLINE,LINE) + null u => + sayKeyedMsg("S2IZ0008",[kind,x]) + terminateSystemCommand() + commandAmbiguityError(kind,x,u) + +commandAmbiguityError(kind,x,u) == + sayKeyedMsg("S2IZ0009",[kind,x]) + for a in u repeat sayMSG ['" ",:bright a] + terminateSystemCommand() + +--% Utility for access to original command line + +getSystemCommandLine() == + p := STRPOS('")",$currentLine,0,NIL) + line := if p then SUBSTRING($currentLine,p,NIL) else $currentLine + maxIndex:= MAXINDEX line + for i in 0..maxIndex while (line.i^=" ") repeat index:= i + if index=maxIndex then line := '"" + else line := SUBSTRING(line,index+2,nil) + line + +------------ start of commands ------------------------------------------ + +--% )abbreviations + +abbreviations l == abbreviationsSpad2Cmd l + +abbreviationsSpad2Cmd l == + null l => helpSpad2Cmd '(abbreviations) + abopts := '(query domain category package remove) + + quiet := nil + for [opt] in $options repeat + opt := selectOptionLC(opt,'(quiet),'optionError) + opt = 'quiet => quiet := true + + l is [opt,:al] => + key := opOf CAR al + type := selectOptionLC(opt,abopts,'optionError) + type is 'query => + null al => listConstructorAbbreviations() + constructor := abbreviation?(key) => abbQuery(constructor) + abbQuery(key) + type is 'remove => + DELDATABASE(key,'ABBREVIATION) + ODDP SIZE al => sayKeyedMsg("S2IZ0002",[type]) + repeat + null al => return 'fromLoop + [a,b,:al] := al + mkUserConstructorAbbreviation(b,a,type) + SETDATABASE(b,'ABBREVIATION,a) + SETDATABASE(b,'CONSTRUCTORKIND,type) + null quiet => + sayKeyedMsg("S2IZ0001",[a,type,opOf b]) + nil + nil + +listConstructorAbbreviations() == + x := UPCASE queryUserKeyedMsg("S2IZ0056",NIL) + MEMQ(STRING2ID_-N(x,1),'(Y YES)) => + whatSpad2Cmd '(categories) + whatSpad2Cmd '(domains) + whatSpad2Cmd '(packages) + sayKeyedMsg("S2IZ0057",NIL) + +--% )clear + +clear l == clearSpad2Cmd l + +clearSpad2Cmd l == + -- new version which changes the environment and updates history + $clearExcept: local := nil + if $options then $clearExcept := + "and"/[selectOptionLC(opt,'(except),'optionError) = + 'except for [opt,:.] in $options] + null l => + optList:= "append"/[['%l,'" ",x] for x in $clearOptions] + sayKeyedMsg("S2IZ0010",[optList]) + arg := selectOptionLC(first l,'(all completely scaches),NIL) + arg = 'all => clearCmdAll() + arg = 'completely => clearCmdCompletely() + arg = 'scaches => clearCmdSortedCaches() + $clearExcept => clearCmdExcept(l) + clearCmdParts(l) + updateCurrentInterpreterFrame() + +clearCmdSortedCaches() == + $lookupDefaults: local := false + for [.,.,:domain] in HGET($ConstructorCache,'SortedCache) repeat + pair := compiledLookupCheck('clearCache,[$Void],domain) + SPADCALL pair + +clearCmdCompletely() == + clearCmdAll() + $localExposureData := COPY_-SEQ $localExposureDataDefault + $xdatabase := NIL + $CatOfCatDatabase := NIL + $DomOfCatDatabase := NIL + $JoinOfCatDatabase := NIL + $JoinOfDomDatabase := NIL + $attributeDb := NIL + $functionTable := NIL + sayKeyedMsg("S2IZ0013",NIL) + clearClams() + clearConstructorCaches() + $existingFiles := MAKE_-HASHTABLE 'UEQUAL + sayKeyedMsg("S2IZ0014",NIL) + RECLAIM() + sayKeyedMsg("S2IZ0015",NIL) + NIL + +clearCmdAll() == + clearCmdSortedCaches() + ------undo special variables------ + $frameRecord := nil + $previousBindings := nil + $variableNumberAlist := nil + untraceMapSubNames _/TRACENAMES + $InteractiveFrame := LIST LIST NIL + resetInCoreHist() + if $useInternalHistoryTable + then $internalHistoryTable := NIL + else deleteFile histFileName() + $IOindex := 1 + updateCurrentInterpreterFrame() + $currentLine := '")clear all" --restored 3/94; needed for undo (RDJ) + clearMacroTable() + if $frameMessages then sayKeyedMsg("S2IZ0011",[$interpreterFrameName]) + else sayKeyedMsg("S2IZ0012",NIL) + +clearCmdExcept(l is [opt,:vl]) == + --clears elements of vl of all options EXCEPT opt + for option in $clearOptions | + ^stringPrefix?(object2String opt,object2String option) + repeat clearCmdParts [option,:vl] + +clearCmdParts(l is [opt,:vl]) == + -- clears the bindings indicated by opt of all variables in vl + + option:= selectOptionLC(opt,$clearOptions,'optionError) + option:= INTERN PNAME option + + -- the option can be plural but the key in the alist is sometimes + -- singular + + option := + option = 'types => 'mode + option = 'modes => 'mode + option = 'values => 'value + option + + null vl => sayKeyedMsg("S2IZ0055",NIL) + pmacs := getParserMacroNames() + imacs := getInterpMacroNames() + if vl='(all) then + vl := ASSOCLEFT CAAR $InteractiveFrame + vl := REMDUP(append(vl, pmacs)) + $e : local := $InteractiveFrame + for x in vl repeat + clearDependencies(x,true) + if option='properties and x in pmacs then clearParserMacro(x) + if option='properties and x in imacs and ^(x in pmacs) then + sayMessage ['" You cannot clear the definition of the system-defined macro ", + fixObjectForPrinting x,"."] + p1 := ASSOC(x,CAAR $InteractiveFrame) => + option='properties => + if isMap x then + (lm := get(x,'localModemap,$InteractiveFrame)) => + PAIRP lm => untraceMapSubNames [CADAR lm] + NIL + for p2 in CDR p1 repeat + prop:= CAR p2 + recordOldValue(x,prop,CDR p2) + recordNewValue(x,prop,NIL) + SETF(CAAR $InteractiveFrame,deleteAssoc(x,CAAR $InteractiveFrame)) + p2:= ASSOC(option,CDR p1) => + recordOldValue(x,option,CDR p2) + recordNewValue(x,option,NIL) + RPLACD(p2,NIL) + nil + +--% )close + +queryClients () == + -- Returns the number of active scratchpad clients + sockSendInt($SessionManager, $QueryClients) + sockGetInt $SessionManager + + +close args == + $saturn => + sayErrorly('"Obsolete system command", _ + ['" The )close system command is obsolete in this version of AXIOM.", + '" Please use Close from the File menu instead."]) + quiet:local:= false + null $SpadServer => + throwKeyedMsg('"S2IZ0071", []) + numClients := queryClients() + numClients > 1 => + sockSendInt($SessionManager, $CloseClient) + sockSendInt($SessionManager, $currentFrameNum) + closeInterpreterFrame(NIL) + for [opt,:.] in $options repeat + fullopt := selectOptionLC(opt, '(quiet), 'optionError) + fullopt = 'quiet => + quiet:=true + quiet => + sockSendInt($SessionManager, $CloseClient) + sockSendInt($SessionManager, $currentFrameNum) + closeInterpreterFrame(NIL) + x := UPCASE queryUserKeyedMsg('"S2IZ0072", nil) + MEMQ(STRING2ID_-N(x,1), '(YES Y)) => + BYE() + nil + +--% )constructor + +constructor args == + sayMessage '" Not implemented yet." + NIL + +--% )compiler + +compiler args == + $newConlist: local := nil --reset by compDefineLisplib and astran + null args and null $options and null _/EDITFILE => helpSpad2Cmd '(compiler) + if null args then args := [_/EDITFILE] + + -- first see if the user has explicitly specified the compiler + -- to use. + + optlist := '(new old translate constructor) + haveNew := nil + haveOld := nil + for opt in $options while ^(haveNew and haveOld) repeat + [optname,:optargs] := opt + fullopt := selectOptionLC(optname,optlist,nil) + fullopt = 'new => haveNew := true + fullopt = 'translate => haveOld := true + fullopt = 'constructor => haveOld := true + fullopt = 'old => haveOld := true + + haveNew and haveOld => throwKeyedMsg("S2IZ0081", nil) + + af := pathname args + aft := pathnameType af +-- Whats this for? MCD/PAB 21-9-95 +-- if haveNew and (null(aft) or (aft = '"")) then +-- af := pathname [af, '"as"] +-- aft = '"as" +-- if haveOld and (null(aft) or (aft = '"")) then +-- af := pathname [af, '"spad"] +-- aft = '"spad" + + haveNew or (aft = '"as") => + not (af1 := $FINDFILE (af, '(as))) => + throwKeyedMsg("S2IL0003",[NAMESTRING af]) + compileAsharpCmd [af1] + haveOld or (aft = '"spad") => + not (af1 := $FINDFILE (af, '(spad))) => + throwKeyedMsg("S2IL0003",[NAMESTRING af]) + compileSpad2Cmd [af1] + aft = '"lsp" => + not (af1 := $FINDFILE (af, '(lsp))) => + throwKeyedMsg("S2IL0003",[NAMESTRING af]) + compileAsharpLispCmd [af1] + aft = '"NRLIB" => + not (af1 := $FINDFILE (af, '(NRLIB))) => + throwKeyedMsg("S2IL0003",[NAMESTRING af]) + compileSpadLispCmd [af1] + aft = '"ao" => + not (af1 := $FINDFILE (af, '(ao))) => + throwKeyedMsg("S2IL0003",[NAMESTRING af]) + compileAsharpCmd [af1] + aft = '"al" => -- archive library of .ao files + not (af1 := $FINDFILE (af, '(al))) => + throwKeyedMsg("S2IL0003",[NAMESTRING af]) + compileAsharpArchiveCmd [af1] + + -- see if we something with the appropriate file extension + -- lying around + + af1 := $FINDFILE (af, '(as spad ao asy)) + + af1 and pathnameType(af1) = '"as" => compileAsharpCmd [af1] + af1 and pathnameType(af1) = '"ao" => compileAsharpCmd [af1] + af1 and pathnameType(af1) = '"spad" => compileSpad2Cmd [af1] + af1 and pathnameType(af1) = '"asy" => compileAsharpArchiveCmd [af1] + + -- maybe /EDITFILE has some stuff that can help us + ef := pathname _/EDITFILE + ef := mergePathnames(af,ef) + + ef = af => throwKeyedMsg("S2IZ0039", nil) + af := ef + + pathnameType(af) = '"as" => compileAsharpCmd args + pathnameType(af) = '"ao" => compileAsharpCmd args + pathnameType(af) = '"spad" => compileSpad2Cmd args + + -- see if we something with the appropriate file extension + -- lying around + af1 := $FINDFILE (af, '(as spad ao asy)) + + af1 and pathnameType(af1) = '"as" => compileAsharpCmd [af1] + af1 and pathnameType(af1) = '"ao" => compileAsharpCmd [af1] + af1 and pathnameType(af1) = '"spad" => compileSpad2Cmd [af1] + af1 and pathnameType(af1) = '"asy" => compileAsharpArchiveCmd [af1] + + throwKeyedMsg("S2IZ0039", nil) + +compileAsharpCmd args == + compileAsharpCmd1 args + terminateSystemCommand() + spadPrompt() + +compileAsharpCmd1 args == + -- Assume we entered from the "compiler" function, so args ^= nil + -- and is a file with file extension .as or .ao + + path := pathname args + pathType := pathnameType path + (pathType ^= '"as") and (pathType ^= '"ao") => throwKeyedMsg("S2IZ0083", nil) + ^PROBE_-FILE path => throwKeyedMsg("S2IL0003",[namestring args]) + + SETQ(_/EDITFILE, path) + updateSourceFiles path + + optList := '( _ + new _ + old _ + translate _ + onlyargs _ + moreargs _ + quiet _ + nolispcompile _ + noquiet _ + library _ + nolibrary _ + ) + + beQuiet := false -- be verbose here + doLibrary := true -- so a )library after compilation + doCompileLisp := true -- do compile generated lisp code + + moreArgs := NIL + onlyArgs := NIL + + for opt in $options repeat + [optname,:optargs] := opt + fullopt := selectOptionLC(optname,optList,nil) + + fullopt = 'new => nil + fullopt = 'old => error "Internal error: compileAsharpCmd got )old" + fullopt = 'translate => error "Internal error: compileAsharpCmd got )translate" + + fullopt = 'quiet => beQuiet := true + fullopt = 'noquiet => beQuiet := false + + fullopt = 'nolispcompile => doCompileLisp := false + + fullopt = 'moreargs => moreArgs := optargs + fullopt = 'onlyargs => onlyArgs := optargs + + fullopt = 'library => doLibrary := true + fullopt = 'nolibrary => doLibrary := false + + throwKeyedMsg("S2IZ0036",[STRCONC('")",object2String optname)]) + + tempArgs := + pathType = '"ao" => + -- want to strip out -Fao + (p := STRPOS('"-Fao", $asharpCmdlineFlags, 0, NIL)) => + p = 0 => SUBSTRING($asharpCmdlineFlags, 5, NIL) + STRCONC(SUBSTRING($asharpCmdlineFlags, 0, p), '" ", + SUBSTRING($asharpCmdlineFlags, p+5, NIL)) + $asharpCmdlineFlags + $asharpCmdlineFlags + + asharpArgs := + onlyArgs => + s := "" + for a in onlyArgs repeat + s := STRCONC(s, '" ", object2String a) + s + moreArgs => + s := tempArgs + for a in moreArgs repeat + s := STRCONC(s, '" ", object2String a) + s + tempArgs + + if ^beQuiet then sayKeyedMsg("S2IZ0038A",[namestring args, asharpArgs]) + + command := +<<remove TRUENAME>> + rc := OBEY command + + if (rc = 0) and doCompileLisp then + lsp := fnameMake('".", pathnameName args, '"lsp") + if fnameReadable?(lsp) then + if ^beQuiet then sayKeyedMsg("S2IZ0089", [namestring lsp]) + compileFileQuietly(lsp) + else + sayKeyedMsg("S2IL0003", [namestring lsp]) + + if rc = 0 and doLibrary then + -- do we need to worry about where the compilation output went? + if ^beQuiet then sayKeyedMsg("S2IZ0090", [ pathnameName path ]) + withAsharpCmd [ pathnameName path ] + else if ^beQuiet then + sayKeyedMsg("S2IZ0084", nil) + + extendLocalLibdb $newConlist + +compileAsharpArchiveCmd args == + -- Assume we entered from the "compiler" function, so args ^= nil + -- and is a file with file extension .al. We also assume that + -- the name is fully qualified. + + path := pathname args + ^PROBE_-FILE path => throwKeyedMsg("S2IL0003",[namestring args]) + + -- here is the plan: + -- 1. extract the file name and try to make a directory based + -- on that name. + -- 2. cd to that directory and ar x the .al file + -- 3. for each .ao file that shows up, compile it + -- 4. delete the generated .ao files + + -- First try to make the directory in the current directory + + dir := fnameMake('".", pathnameName path, '"axldir") + exists := PROBE_-FILE dir + isDir := directoryp namestring dir + exists and isDir ^= 1=> + throwKeyedMsg("S2IL0027",[namestring dir, namestring args]) + + if isDir ^= 1 then + cmd := STRCONC('"mkdir ", namestring dir) + rc := OBEY cmd + rc ^= 0 => throwKeyedMsg("S2IL0027",[namestring dir, namestring args]) + + curDir := $CURRENT_-DIRECTORY + + -- cd to that directory and try to unarchive the .al file + + cd [ object2Identifier namestring dir ] + + cmd := STRCONC( '"ar x ", namestring path ) + rc := OBEY cmd + rc ^= 0 => + cd [ object2Identifier namestring curDir ] + throwKeyedMsg("S2IL0028",[namestring dir, namestring args]) + + -- Look for .ao files + + asos := DIRECTORY '"*.ao" + null asos => + cd [ object2Identifier namestring curDir ] + throwKeyedMsg("S2IL0029",[namestring dir, namestring args]) + + -- Compile the .ao files + + for aso in asos repeat + compileAsharpCmd1 [ namestring aso ] + + -- Reset the current directory + + cd [ object2Identifier namestring curDir ] + + terminateSystemCommand() + spadPrompt() + +compileAsharpLispCmd args == + -- Assume we entered from the "compiler" function, so args ^= nil + -- and is a file with file extension .lsp + + path := pathname args + ^PROBE_-FILE path => throwKeyedMsg("S2IL0003",[namestring args]) + + optList := '( _ + quiet _ + noquiet _ + library _ + nolibrary _ + ) + + beQuiet := false -- be verbose here + doLibrary := true -- so a )library after compilation + + for opt in $options repeat + [optname,:optargs] := opt + fullopt := selectOptionLC(optname,optList,nil) + + fullopt = 'quiet => beQuiet := true + fullopt = 'noquiet => beQuiet := false + + fullopt = 'library => doLibrary := true + fullopt = 'nolibrary => doLibrary := false + + throwKeyedMsg("S2IZ0036",[STRCONC('")",object2String optname)]) + + lsp := fnameMake(pathnameDirectory path, pathnameName path, pathnameType path) + if fnameReadable?(lsp) then + if ^beQuiet then sayKeyedMsg("S2IZ0089", [namestring lsp]) + compileFileQuietly(lsp) + else + sayKeyedMsg("S2IL0003", [namestring lsp]) + + if doLibrary then + -- do we need to worry about where the compilation output went? + if ^beQuiet then sayKeyedMsg("S2IZ0090", [ pathnameName path ]) + withAsharpCmd [ pathnameName path ] + else if ^beQuiet then + sayKeyedMsg("S2IZ0084", nil) + terminateSystemCommand() + spadPrompt() + +compileSpadLispCmd args == + -- Assume we entered from the "compiler" function, so args ^= nil + -- and is a file with file extension .NRLIB + + path := pathname fnameMake(first args, '"code", '"lsp") + ^PROBE_-FILE path => throwKeyedMsg("S2IL0003",[namestring args]) + + optList := '( _ + quiet _ + noquiet _ + library _ + nolibrary _ + ) + + beQuiet := false -- be verbose here + doLibrary := true -- so a )library after compilation + + for opt in $options repeat + [optname,:optargs] := opt + fullopt := selectOptionLC(optname,optList,nil) + + fullopt = 'quiet => beQuiet := true + fullopt = 'noquiet => beQuiet := false + + fullopt = 'library => doLibrary := true + fullopt = 'nolibrary => doLibrary := false + + throwKeyedMsg("S2IZ0036",[STRCONC('")",object2String optname)]) + + lsp := fnameMake(pathnameDirectory path, pathnameName path, pathnameType path) + if fnameReadable?(lsp) then + if ^beQuiet then sayKeyedMsg("S2IZ0089", [namestring lsp]) + --compileFileQuietly(lsp) + RECOMPILE_-LIB_-FILE_-IF_-NECESSARY lsp + else + sayKeyedMsg("S2IL0003", [namestring lsp]) + + if doLibrary then + -- do we need to worry about where the compilation output went? + if ^beQuiet then sayKeyedMsg("S2IZ0090", [ pathnameName path ]) + LOCALDATABASE([ pathnameName first args ],[]) + else if ^beQuiet then + sayKeyedMsg("S2IZ0084", nil) + terminateSystemCommand() + spadPrompt() + +withAsharpCmd args == + $options: local := nil + LOCALDATABASE(args, $options) + +--% )copyright -- display copyright notice + +summary l == + OBEY STRCONC ('"cat ",getEnv('"AXIOM"),'"/lib/summary") +copyright () == + OBEY STRCONC ('"cat ",getEnv('"AXIOM"),'"/lib/copyright") + +--% )credits -- display credit list + +credits() == + for i in CREDITS repeat + PRINC(i) + TERPRI() + +--% )display + +display l == displaySpad2Cmd l + +displaySpad2Cmd l == + $e: local := $EmptyEnvironment + l is [opt,:vl] and opt ^= "?" => + option := selectOptionLC(opt,$displayOptions,'optionError) => + + -- the option may be given in the plural but the property in + -- the alist is sometimes singular + + option := + option = 'all => + l := ['properties] + 'properties + (option = 'modes) or (option = 'types) => + l := ['type, :vl] + 'type + option = 'values => + l := ['value, :vl] + 'value + option + + option = 'abbreviations => + null vl => listConstructorAbbreviations() + for v in vl repeat abbQuery(opOf v) + + option = 'operations => displayOperations vl + option = 'macros => displayMacros vl + option = 'names => displayWorkspaceNames() + displayProperties(option,l) + optList:= [:['%l,'" ",x] for x in $displayOptions] + msg := [:bright '" )display",'"keyword arguments are", + :bright optList,'%l,'" or abbreviations thereof."] + sayMessage msg + +displayMacros names == + imacs := getInterpMacroNames() + pmacs := getParserMacroNames() + macros := + null names => APPEND (imacs, pmacs) + names + macros := REMDUP macros + + null macros => sayBrightly '" There are no Axiom macros." + + -- first do user defined ones + + first := true + for macro in macros repeat + macro in pmacs => + if first then + sayBrightly ['%l,'"User-defined macros:"] + first := NIL + displayParserMacro macro + macro in imacs => 'iterate + sayBrightly ([" ",'%b, macro, '%d, " is not a known Axiom macro."]) + + -- now system ones + + first := true + for macro in macros repeat + macro in imacs => + macro in pmacs => 'iterate + if first then + sayBrightly ['%l,'"System-defined macros:"] + first := NIL + displayMacro macro + macro in pmacs => 'iterate + NIL + +getParserMacroNames() == + REMDUP [CAR mac for mac in getParserMacros()] + +--------------------> NEW DEFINITION (override in patches.lisp.pamphlet) +clearParserMacro(macro) == + -- first see if it is one + not IFCDR ASSOC(macro, ($pfMacros)) => NIL + $pfMacros := REMALIST($pfMacros, macro) + +displayMacro name == + m := isInterpMacro name + null m => + sayBrightly ['" ",:bright name,'"is not an interpreter macro."] + -- $op is needed in the output routines. + $op : local := STRCONC('"macro ",object2String name) + [args,:body] := m + args := + null args => nil + null rest args => first args + ['Tuple,:args] + mathprint ['MAP,[args,:body]] + +displayWorkspaceNames() == + imacs := getInterpMacroNames() + pmacs := getParserMacroNames() + sayMessage '"Names of User-Defined Objects in the Workspace:" + names := MSORT append(getWorkspaceNames(),pmacs) + if null names + then sayBrightly " * None *" + else sayAsManyPerLineAsPossible [object2String x for x in names] + imacs := SETDIFFERENCE(imacs,pmacs) + if imacs then + sayMessage '"Names of System-Defined Objects in the Workspace:" + sayAsManyPerLineAsPossible [object2String x for x in imacs] + + +getWorkspaceNames() == + NMSORT [n for [n,:.] in CAAR $InteractiveFrame | + (n ^= "--macros--" and n^= "--flags--")] + +displayOperations l == + null l => + x := UPCASE queryUserKeyedMsg("S2IZ0058",NIL) + if MEMQ(STRING2ID_-N(x,1),'(Y YES)) + then for op in allOperations() repeat reportOpSymbol op + else sayKeyedMsg("S2IZ0059",NIL) + nil + for op in l repeat reportOpSymbol op + +interpFunctionDepAlists() == + $e : local := $InteractiveFrame + deps := getFlag "$dependencies" + $dependentAlist := [[NIL,:NIL]] + $dependeeAlist := [[NIL,:NIL]] + for [dependee,dependent] in deps repeat + $dependentAlist := PUTALIST($dependentAlist,dependee, + CONS(dependent,GETALIST($dependentAlist,dependee))) + $dependeeAlist := PUTALIST($dependeeAlist,dependent, + CONS(dependee,GETALIST($dependeeAlist,dependent))) + +fixObjectForPrinting(v) == + v' := object2Identifier v + EQ(v',"%") => '"\%" + v' in $msgdbPrims => STRCONC('"\",PNAME v') + v + +displayProperties(option,l) == + $dependentAlist : local + $dependeeAlist : local + [opt,:vl]:= (l or ['properties]) + imacs := getInterpMacroNames() + pmacs := getParserMacroNames() + macros := REMDUP append(imacs, pmacs) + if vl is ['all] or null vl then + vl := MSORT append(getWorkspaceNames(),macros) + if $frameMessages then sayKeyedMsg("S2IZ0065",[$interpreterFrameName]) + null vl => + null $frameMessages => sayKeyedMsg("S2IZ0066",NIL) + sayKeyedMsg("S2IZ0067",[$interpreterFrameName]) + interpFunctionDepAlists() + for v in vl repeat + isInternalMapName(v) => 'iterate + pl := getIProplist(v) + option = 'flags => getAndSay(v,"flags") + option = 'value => displayValue(v,getI(v,'value),nil) + option = 'condition => displayCondition(v,getI(v,"condition"),nil) + option = 'mode => displayMode(v,getI(v,'mode),nil) + option = 'type => displayType(v,getI(v,'value),nil) + option = 'properties => + v = "--flags--" => nil + pl is [['cacheInfo,:.],:.] => nil + v1 := fixObjectForPrinting(v) + sayMSG ['"Properties of",:bright prefix2String v1,'":"] + null pl => + v in pmacs => + sayMSG '" This is a user-defined macro." + displayParserMacro v + isInterpMacro v => + sayMSG '" This is a system-defined macro." + displayMacro v + sayMSG '" none" + propsSeen:= nil + for [prop,:val] in pl | ^MEMQ(prop,propsSeen) and val repeat + prop in '(alias generatedCode IS_-GENSYM mapBody localVars) => + nil + prop = 'condition => + displayCondition(prop,val,true) + prop = 'recursive => + sayMSG '" This is recursive." + prop = 'isInterpreterFunction => + sayMSG '" This is an interpreter function." + sayFunctionDeps v where + sayFunctionDeps x == + if dependents := GETALIST($dependentAlist,x) then + null rest dependents => + sayMSG ['" The following function or rule ", + '"depends on this:",:bright first dependents] + sayMSG + '" The following functions or rules depend on this:" + msg := ["%b",'" "] + for y in dependents repeat msg := ['" ",y,:msg] + sayMSG [:nreverse msg,"%d"] + if dependees := GETALIST($dependeeAlist,x) then + null rest dependees => + sayMSG ['" This depends on the following function ", + '"or rule:",:bright first dependees] + sayMSG + '" This depends on the following functions or rules:" + msg := ["%b",'" "] + for y in dependees repeat msg := ['" ",y,:msg] + sayMSG [:nreverse msg,"%d"] + prop = 'isInterpreterRule => + sayMSG '" This is an interpreter rule." + sayFunctionDeps v + prop = 'localModemap => + displayModemap(v,val,true) + prop = 'mode => + displayMode(prop,val,true) + prop = 'value => + val => displayValue(v,val,true) + sayMSG ['" ",prop,'": ",val] + propsSeen:= [prop,:propsSeen] + sayKeyedMsg("S2IZ0068",[option]) + terminateSystemCommand() + +displayModemap(v,val,giveVariableIfNil) == + for mm in val repeat g(v,mm,giveVariableIfNil) where + g(v,mm,giveVariableIfNil) == + [[local,:signature],fn,:.]:= mm + local='interpOnly => nil + varPart:= (giveVariableIfNil => nil; ['" of",:bright v]) + prefix:= [" Compiled function type",:varPart,": "] + sayBrightly concat(prefix,formatSignature signature) + +displayMode(v,mode,giveVariableIfNil) == + null mode => nil + varPart:= (giveVariableIfNil => nil; [" of",:bright fixObjectForPrinting v]) + sayBrightly concat(" Declared type or mode", + varPart,": ",prefix2String mode) + +displayCondition(v,condition,giveVariableIfNil) == + varPart:= (giveVariableIfNil => nil; [" of",:bright v]) + condPart:= condition or 'true + sayBrightly concat(" condition",varPart,": ",pred2English condPart) + +getAndSay(v,prop) == + val:= getI(v,prop) => sayMSG [" ",val,'%l] + sayMSG [" none",'%l] + +displayType($op,u,omitVariableNameIfTrue) == + null u => + sayMSG ['" Type of value of ", + fixObjectForPrinting PNAME $op,'": (none)"] + type := prefix2String objMode(u) + if ATOM type then type := [type] + sayMSG concat ['" Type of value of ",fixObjectForPrinting PNAME $op,'": ",:type] + NIL + +displayValue($op,u,omitVariableNameIfTrue) == + null u => sayMSG [" Value of ",fixObjectForPrinting PNAME $op,'": (none)"] + expr := objValUnwrap(u) + expr is [op,:.] and (op = 'MAP) or objMode(u) = $EmptyMode => + displayRule($op,expr) + label:= + omitVariableNameIfTrue => + rhs := '"): " + '"Value (has type " + rhs := '": " + STRCONC('"Value of ", PNAME $op,'": ") + labmode := prefix2String objMode(u) + if ATOM labmode then labmode := [labmode] + GETDATABASE(expr,'CONSTRUCTORKIND) = 'domain => + sayMSG concat('" ",label,labmode,rhs,form2String expr) + mathprint ['CONCAT,label,:labmode,rhs, + outputFormat(expr,objMode(u))] + NIL + +--% )edit + +edit l == editSpad2Cmd l + +editSpad2Cmd l == + l:= + null l => _/EDITFILE + CAR l + l := pathname l + oldDir := pathnameDirectory l + fileTypes := + pathnameType l => [pathnameType l] + $UserLevel = 'interpreter => '("input" "INPUT" "spad" "SPAD") + $UserLevel = 'compiler => '("input" "INPUT" "spad" "SPAD") + '("input" "INPUT" "spad" "SPAD" "boot" "BOOT" "lisp" "LISP" "meta" "META") + ll := + oldDir = '"" => pathname $FINDFILE (pathnameName l, fileTypes) + l + l := pathname ll + SETQ(_/EDITFILE,l) + rc := editFile l + updateSourceFiles l + rc + +--% )help + +help l == helpSpad2Cmd l + +helpSpad2Cmd args == + -- try to use new stuff first + if newHelpSpad2Cmd(args) then return nil + + sayKeyedMsg("S2IZ0025",[args]) + nil + +newHelpSpad2Cmd args == + if null args then args := ["?"] + # args > 1 => + sayKeyedMsg("S2IZ0026",NIL) + true + sarg := PNAME first args + if sarg = '"?" then args := ['help] + else if sarg = '"%" then args := ['history] + else if sarg = '"%%" then args := ['history] + arg := selectOptionLC(first args,$SYSCOMMANDS,nil) + if null arg then arg := first args + if arg = 'compiler then arg := 'compile + + -- see if new help file exists + + narg := PNAME arg + null (helpFile := MAKE_-INPUT_-FILENAME [narg,'HELPSPAD,'_*]) => NIL + + $useFullScreenHelp => + OBEY STRCONC('"$AXIOM/lib/SPADEDIT ",namestring helpFile) + true + + filestream := MAKE_-INSTREAM(helpFile) + repeat + line := read_-line(filestream,false) + NULL line => + SHUT filestream + return true + SAY line + true + +--% +--% )frame +--% + +$frameRecord := nil --Initial setting for frame record +$previousBindings := nil + +frame l == frameSpad2Cmd l + +frameName(frame) == CAR frame + +frameNames() == [frameName f for f in $interpreterFrameRing] + +frameEnvironment fname == + -- extracts the environment portion of a frame + -- if fname is not a valid frame name then the empty environment + -- is returned + fname = frameName first $interpreterFrameRing => $InteractiveFrame + ifr := rest $interpreterFrameRing + e := LIST LIST NIL + while ifr repeat + [f,:ifr] := ifr + if fname = frameName f then + e := CADR f + ifr := NIL + e + +frameSpad2Cmd args == + frameArgs := '(drop import last names new next) + $options => throwKeyedMsg("S2IZ0016",['")frame"]) + null(args) => helpSpad2Cmd ['frame] + arg := selectOptionLC(first args,frameArgs,'optionError) + args := rest args + if args is [a] then args := a + if ATOM args then args := object2Identifier args + arg = 'drop => + args and PAIRP(args) => throwKeyedMsg("S2IZ0017",[args]) + closeInterpreterFrame(args) + arg = 'import => importFromFrame args + arg = 'last => previousInterpreterFrame() + arg = 'names => displayFrameNames() + arg = 'new => + args and PAIRP(args) => throwKeyedMsg("S2IZ0017",[args]) + addNewInterpreterFrame(args) + arg = 'next => nextInterpreterFrame() + + NIL + +addNewInterpreterFrame(name) == + null name => throwKeyedMsg("S2IZ0018",NIL) + updateCurrentInterpreterFrame() + -- see if we already have one by that name + for f in $interpreterFrameRing repeat + name = frameName(f) => throwKeyedMsg("S2IZ0019",[name]) + initHistList() + $interpreterFrameRing := CONS(emptyInterpreterFrame(name), + $interpreterFrameRing) + updateFromCurrentInterpreterFrame() + _$ERASE histFileName() + +emptyInterpreterFrame(name) == + LIST(name, -- frame name + LIST LIST NIL, -- environment + 1, -- $IOindex + $HiFiAccess, -- $HiFiAccess + $HistList, -- $HistList + $HistListLen, -- $HistListLen + $HistListAct, -- $HistListAct + $HistRecord, -- $HistRecord + NIL, -- $internalHistoryTable + COPY_-SEQ $localExposureDataDefault -- $localExposureData + ) + +closeInterpreterFrame(name) == + -- if name = NIL then it means the current frame + null rest $interpreterFrameRing => + name and (name ^= $interpreterFrameName) => + throwKeyedMsg("S2IZ0020",[$interpreterFrameName]) + throwKeyedMsg("S2IZ0021",NIL) + if null name then $interpreterFrameRing := rest $interpreterFrameRing + else -- find the frame + found := nil + ifr := NIL + for f in $interpreterFrameRing repeat + found or (name ^= frameName(f)) => ifr := CONS(f,ifr) + found := true + not found => throwKeyedMsg("S2IZ0022",[name]) + _$ERASE makeHistFileName(name) + $interpreterFrameRing := nreverse ifr + updateFromCurrentInterpreterFrame() + +previousInterpreterFrame() == + updateCurrentInterpreterFrame() + null rest $interpreterFrameRing => NIL -- nothing to do + [:b,l] := $interpreterFrameRing + $interpreterFrameRing := NCONC2([l],b) + updateFromCurrentInterpreterFrame() + +nextInterpreterFrame() == + updateCurrentInterpreterFrame() + null rest $interpreterFrameRing => NIL -- nothing to do + $interpreterFrameRing := + NCONC2(rest $interpreterFrameRing,[first $interpreterFrameRing]) + updateFromCurrentInterpreterFrame() + + +createCurrentInterpreterFrame() == + LIST($interpreterFrameName, -- frame name + $InteractiveFrame, -- environment + $IOindex, -- $IOindex + $HiFiAccess, -- $HiFiAccess + $HistList, -- $HistList + $HistListLen, -- $HistListLen + $HistListAct, -- $HistListAct + $HistRecord, -- $HistRecord + $internalHistoryTable, -- $internalHistoryTable + $localExposureData -- $localExposureData + ) + + +updateFromCurrentInterpreterFrame() == + [$interpreterFrameName, _ + $InteractiveFrame, _ + $IOindex, _ + $HiFiAccess, _ + $HistList, _ + $HistListLen, _ + $HistListAct, _ + $HistRecord, _ + $internalHistoryTable, _ + $localExposureData _ + ] := first $interpreterFrameRing + if $frameMessages then + sayMessage ['" Current interpreter frame is called",:bright + $interpreterFrameName] + NIL + + +updateCurrentInterpreterFrame() == + RPLACA($interpreterFrameRing,createCurrentInterpreterFrame()) + updateFromCurrentInterpreterFrame() + NIL + +initializeInterpreterFrameRing() == + $interpreterFrameName := 'initial + $interpreterFrameRing := [emptyInterpreterFrame($interpreterFrameName)] + updateFromCurrentInterpreterFrame() + NIL + + +changeToNamedInterpreterFrame(name) == + updateCurrentInterpreterFrame() + frame := findFrameInRing(name) + null frame => NIL + $interpreterFrameRing := [frame,:NREMOVE($interpreterFrameRing, frame)] + updateFromCurrentInterpreterFrame() + +makeInitialModemapFrame() == COPY $InitialModemapFrame + +findFrameInRing(name) == + val := NIL + for frame in $interpreterFrameRing repeat + CAR frame = name => + val := frame + return frame + val + +displayFrameNames() == + fs := "append"/[ ['%l,'" ",:bright frameName f] for f in + $interpreterFrameRing] + sayKeyedMsg("S2IZ0024",[fs]) + +importFromFrame args == + -- args should have the form [frameName,:varNames] + if args and atom args then args := [args] + null args => throwKeyedMsg("S2IZ0073",NIL) + [fname,:args] := args + not member(fname,frameNames()) => + throwKeyedMsg("S2IZ0074",[fname]) + fname = frameName first $interpreterFrameRing => + throwKeyedMsg("S2IZ0075",NIL) + fenv := frameEnvironment fname + null args => + x := UPCASE queryUserKeyedMsg("S2IZ0076",[fname]) + MEMQ(STRING2ID_-N(x,1),'(Y YES)) => + vars := NIL + for [v,:props] in CAAR fenv repeat + v = "--macros" => + for [m,:.] in props repeat vars := cons(m,vars) + vars := cons(v,vars) + importFromFrame [fname,:vars] + sayKeyedMsg("S2IZ0077",[fname]) + for v in args repeat + plist := GETALIST(CAAR fenv,v) + plist => + -- remove anything with the same name in the current frame + clearCmdParts ['propert,v] + for [prop,:val] in plist repeat + putHist(v,prop,val,$InteractiveFrame) + (m := get("--macros--",v,fenv)) => + putHist("--macros--",v,m,$InteractiveFrame) + sayKeyedMsg("S2IZ0079",[v,fname]) + sayKeyedMsg("S2IZ0078",[fname]) + + + +--% )history + +++ vm/370 filename type component +SETANDFILEQ($historyFileType,'axh) + +++ vm/370 filename name component +SETANDFILEQ($oldHistoryFileName,'last) +SETANDFILEQ($internalHistoryTable,NIL) + +++ t means keep history in core +SETANDFILEQ($useInternalHistoryTable, true) + +history l == + l or null $options => sayKeyedMsg("S2IH0006",NIL) + historySpad2Cmd() + + +makeHistFileName(fname) == + makePathname(fname,$historyFileType,$historyDirectory) + +oldHistFileName() == + makeHistFileName($oldHistoryFileName) + +histFileName() == + makeHistFileName($interpreterFrameName) + + +histInputFileName(fn) == + null fn => + makePathname($interpreterFrameName,'INPUT,$historyDirectory) + makePathname(fn,'INPUT,$historyDirectory) + + +initHist() == + $useInternalHistoryTable => initHistList() + oldFile := oldHistFileName() + newFile := histFileName() + -- see if history directory is writable + histFileErase oldFile + if MAKE_-INPUT_-FILENAME newFile then $REPLACE(oldFile,newFile) + $HiFiAccess:= 'T + initHistList() + +initHistList() == + -- creates $HistList as a circular list of length $HistListLen + -- and $HistRecord + $HistListLen:= 20 + $HistList:= LIST NIL + li:= $HistList + for i in 1..$HistListLen repeat li:= CONS(NIL,li) + RPLACD($HistList,li) + $HistListAct:= 0 + $HistRecord:= NIL + +historySpad2Cmd() == + -- history is a system command which can call resetInCoreHist + -- and changeHistListLen, and restore last session + histOptions:= + '(on off yes no change reset restore write save show file memory) + opts:= [ [selectOptionLC(opt,histOptions,'optionError),:optargs] + for [opt,:optargs] in $options] + for [opt,:optargs] in opts repeat + opt in '(on yes) => + $HiFiAccess => sayKeyedMsg("S2IH0007",NIL) + $IOindex = 1 => -- haven't done anything yet + $HiFiAccess:= 'T + initHistList() + sayKeyedMsg("S2IH0008",NIL) + x := UPCASE queryUserKeyedMsg("S2IH0009",NIL) + MEMQ(STRING2ID_-N(x,1),'(Y YES)) => + histFileErase histFileName() + $HiFiAccess:= 'T + $options := nil + clearSpad2Cmd '(all) + sayKeyedMsg("S2IH0008",NIL) + initHistList() + sayKeyedMsg("S2IH0010",NIL) + opt in '(off no) => + null $HiFiAccess => sayKeyedMsg("S2IH0011",NIL) + $HiFiAccess:= NIL + disableHist() + sayKeyedMsg("S2IH0012",NIL) + opt = 'file => setHistoryCore NIL + opt = 'memory => setHistoryCore true + opt = 'reset => resetInCoreHist() + opt = 'save => saveHistory optargs + opt = 'show => showHistory optargs + opt = 'change => changeHistListLen first optargs + opt = 'restore => restoreHistory optargs + opt = 'write => writeInputLines(optargs,1) + 'done + + +setHistoryCore inCore == + inCore = $useInternalHistoryTable => + sayKeyedMsg((inCore => "S2IH0030"; "S2IH0029"),NIL) + not $HiFiAccess => + $useInternalHistoryTable := inCore + inCore => sayKeyedMsg("S2IH0032",NIL) + sayKeyedMsg("S2IH0031",NIL) + inCore => + $internalHistoryTable := NIL + if $IOindex ^= 0 then + -- actually put something in there + l := LENGTH RKEYIDS histFileName() + for i in 1..l repeat + vec:= UNWIND_-PROTECT(readHiFi(i),disableHist()) + $internalHistoryTable := CONS([i,:vec],$internalHistoryTable) + histFileErase histFileName() + $useInternalHistoryTable := true + sayKeyedMsg("S2IH0032",NIL) + $HiFiAccess:= 'NIL + histFileErase histFileName() + str := RDEFIOSTREAM ['(MODE . OUTPUT),['FILE,:histFileName()]] + for [n,:rec] in reverse $internalHistoryTable repeat + SPADRWRITE(object2Identifier n,rec,str) + RSHUT str + $HiFiAccess:= 'T + $internalHistoryTable := NIL + $useInternalHistoryTable := NIL + sayKeyedMsg("S2IH0031",NIL) + + +writeInputLines(fn,initial) == + -- writes all input lines into file histInputFileName() + not $HiFiAccess => sayKeyedMsg("S2IH0013",NIL) -- history not on + null fn => + throwKeyedMsg("S2IH0038", nil) -- missing file name + maxn := 72 + breakChars := [" ","+"] + for i in initial..$IOindex - 1 repeat + vecl := CAR readHiFi i + if STRINGP vecl then vecl := [vecl] + for vec in vecl repeat + n := SIZE vec + while n > maxn repeat + -- search backwards for a blank + done := nil + for j in 1..maxn while ^done repeat + k := 1 + maxn - j + MEMQ(vec.k,breakChars) => + svec := STRCONC(SUBSTRING(vec,0,k+1),UNDERBAR) + lineList := [svec,:lineList] + done := true + vec := SUBSTRING(vec,k+1,NIL) + n := SIZE vec + -- in case we can't find a breaking point + if ^done then n := 0 + lineList := [vec,:lineList] + file := histInputFileName(fn) + histFileErase file + inp:= DEFIOSTREAM(['(MODE . OUTPUT),['FILE,:file]],255,0) + for x in removeUndoLines NREVERSE lineList repeat WRITE_-LINE(x,inp) + -- see file "undo" for definition of removeUndoLines + if fn ^= 'redo then sayKeyedMsg("S2IH0014",[namestring file]) + SHUT inp + NIL + + +resetInCoreHist() == + -- removes all pointers from $HistList + $HistListAct:= 0 + for i in 1..$HistListLen repeat + $HistList:= CDR $HistList + RPLACA($HistList,NIL) + +changeHistListLen(n) == + -- changes the length of $HistList. n must be nonnegative + NULL INTEGERP n => sayKeyedMsg("S2IH0015",[n]) + dif:= n-$HistListLen + $HistListLen:= n + l:= CDR $HistList + if dif > 0 then + for i in 1..dif repeat l:= CONS(NIL,l) + if dif < 0 then + for i in 1..-dif repeat l:= CDR l + if $HistListAct > n then $HistListAct:= n + RPLACD($HistList,l) + 'done + +updateHist() == + -- updates the history file and calls updateInCoreHist + null $IOindex => nil + startTimingProcess 'history + updateInCoreHist() + if $HiFiAccess then + UNWIND_-PROTECT(writeHiFi(),disableHist()) + $HistRecord:= NIL + $IOindex:= $IOindex+1 + updateCurrentInterpreterFrame() + $mkTestInputStack := nil + $currentLine := nil + stopTimingProcess 'history + +updateInCoreHist() == + -- updates $HistList and $IOindex + $HistList:= CDR($HistList) + RPLACA($HistList,NIL) + if $HistListAct < $HistListLen then $HistListAct:= $HistListAct+1 + +putHist(x,prop,val,e) == + -- records new value to $HistRecord and old value to $HistList + -- then put is called with e + if not (x='%) then recordOldValue(x,prop,get(x,prop,e)) + if $HiFiAccess then recordNewValue(x,prop,val) + putIntSymTab(x,prop,val,e) + +histFileErase file == + --OBEY STRCONC('"rm -rf ", file) + PROBE_-FILE(file) and DELETE_-FILE(file) + + + +recordNewValue(x,prop,val) == + startTimingProcess 'history + recordNewValue0(x,prop,val) + stopTimingProcess 'history + +recordNewValue0(x,prop,val) == + -- writes (prop . val) into $HistRecord + -- updateHist writes this stuff out into the history file + p1:= ASSQ(x,$HistRecord) => + p2:= ASSQ(prop,CDR p1) => + RPLACD(p2,val) + RPLACD(p1,CONS(CONS(prop,val),CDR p1)) + p:= CONS(x,list CONS(prop,val)) + $HistRecord:= CONS(p,$HistRecord) + +recordOldValue(x,prop,val) == + startTimingProcess 'history + recordOldValue0(x,prop,val) + stopTimingProcess 'history + +recordOldValue0(x,prop,val) == + -- writes (prop . val) into $HistList + p1:= ASSQ(x,CAR $HistList) => + not ASSQ(prop,CDR p1) => + RPLACD(p1,CONS(CONS(prop,val),CDR p1)) + p:= CONS(x,list CONS(prop,val)) + RPLACA($HistList,CONS(p,CAR $HistList)) + +undoInCore(n) == + -- undoes the last n>0 steps using $HistList + -- resets $InteractiveFrame + li:= $HistList + for i in n..$HistListLen repeat li:= CDR li + undoChanges(li) + n:= $IOindex-n-1 + n>0 and + $HiFiAccess => + vec:= CDR UNWIND_-PROTECT(readHiFi(n),disableHist()) + val:= ( p:= ASSQ('%,vec) ) and ( p1:= ASSQ('value,CDR p) ) and + CDR p1 + sayKeyedMsg("S2IH0019",[n]) + $InteractiveFrame:= putHist('%,'value,val,$InteractiveFrame) + updateHist() + +undoChanges(li) == + -- undoes all changes of list 'li' + if not CDR li = $HistList then undoChanges CDR li + for p1 in CAR li repeat + x:= CAR p1 + for p2 in CDR p1 repeat + putHist(x,CAR p2,CDR p2,$InteractiveFrame) + +undoFromFile(n) == + -- makes a clear and redoes all the assignments until step n + for [x,:varl] in CAAR $InteractiveFrame repeat + for p in varl repeat + [prop,:val]:= p + val => + if not (x='%) then recordOldValue(x,prop,val) + if $HiFiAccess then recordNewValue(x,prop,val) + RPLACD(p,NIL) + for i in 1..n repeat + vec:= UNWIND_-PROTECT(CDR readHiFi(i),disableHist()) + for p1 in vec repeat + x:= CAR p1 + for p2 in CDR p1 repeat + $InteractiveFrame:= putHist(x,CAR p2,CDR p2,$InteractiveFrame) + val:= ( p:= ASSQ('%,vec) ) and ( p1:= ASSQ('value,CDR p) ) and CDR p1 + $InteractiveFrame:= putHist('%,'value,val,$InteractiveFrame) + updateHist() + +saveHistory(fn) == + $seen: local := MAKE_-HASHTABLE 'EQ + not $HiFiAccess => sayKeyedMsg("S2IH0016",NIL) + not $useInternalHistoryTable and + null MAKE_-INPUT_-FILENAME histFileName() => sayKeyedMsg("S2IH0022",NIL) + null fn => + throwKeyedMsg("S2IH0037", nil) + savefile := makeHistFileName(fn) + inputfile := histInputFileName(fn) + writeInputLines(fn,1) + histFileErase savefile + + if $useInternalHistoryTable + then + saveStr := RDEFIOSTREAM ['(MODE . OUTPUT),['FILE,:savefile]] + for [n,:rec] in reverse $internalHistoryTable repeat + val := SPADRWRITE0(object2Identifier n,rec,saveStr) + val = 'writifyFailed => + sayKeyedMsg("S2IH0035", [n, inputfile]) -- unable to save step + RSHUT saveStr + sayKeyedMsg("S2IH0018",[namestring(savefile)]) -- saved hist file named + nil + +restoreHistory(fn) == + -- uses fn $historyFileType to recover an old session + -- if fn = NIL, then use $oldHistoryFileName + if null fn then fn' := $oldHistoryFileName + else if fn is [fn'] and IDENTP(fn') then fn' := fn' + else throwKeyedMsg("S2IH0023",[fn']) + restfile := makeHistFileName(fn') + null MAKE_-INPUT_-FILENAME restfile => + sayKeyedMsg("S2IH0024",[namestring(restfile)]) -- no history file + + -- if clear is changed to be undoable, this should be a reset-clear + $options: local := nil + clearSpad2Cmd '(all) + + curfile := histFileName() + histFileErase curfile + _$FCOPY(restfile,curfile) + + l:= LENGTH RKEYIDS curfile + $HiFiAccess:= 'T + oldInternal := $useInternalHistoryTable + $useInternalHistoryTable := NIL + if oldInternal then $internalHistoryTable := NIL + for i in 1..l repeat + vec:= UNWIND_-PROTECT(readHiFi(i),disableHist()) + if oldInternal then $internalHistoryTable := + CONS([i,:vec],$internalHistoryTable) + LINE:= CAR vec + for p1 in CDR vec repeat + x:= CAR p1 + for p2 in CDR p1 repeat + $InteractiveFrame:= putHist(x,CAR p2,CDR p2,$InteractiveFrame) + updateInCoreHist() + $e := $InteractiveFrame + for [a,:.] in CAAR $InteractiveFrame repeat + get(a,'localModemap,$InteractiveFrame) => + rempropI(a,'localModemap) + rempropI(a,'localVars) + rempropI(a,'mapBody) + $IOindex:= l+1 + $useInternalHistoryTable := oldInternal + sayKeyedMsg("S2IH0025",[namestring(restfile)]) + clearCmdSortedCaches() + nil + + +-- the following used to be the show command when that was used to +-- show history. +showHistory(arg) == + -- arg can be of form + -- NIL show at most last 20 input lines + -- (n) show at most last n input lines + -- (lit) where lit is an abbreviation for 'input or 'both + -- if 'input, same as NIL + -- if 'both, show last 5 input and outputs + -- (n lit) show last n input lines + last n output lines + -- if lit expands to 'both + $evalTimePrint: local:= 0 + $printTimeSum: local:= 0 + -- ugh!!! these are needed for timedEvaluateStream + -- displays the last n steps, default n=20 + not $HiFiAccess => sayKeyedMsg("S2IH0026",['show]) + showInputOrBoth := 'input + n := 20 + nset := nil + if arg then + arg1 := CAR arg + if INTEGERP arg1 then + n := arg1 + nset := true + KDR arg => arg1 := CADR arg + arg1 := NIL + arg1 => + arg2 := selectOptionLC(arg1,'(input both),nil) + if arg2 + then ((showInputOrBoth := arg2) = 'both) and (null nset) => n:= 5 + else sayMSG + concat('" ",bright arg1,'"is an invalid argument.") + if n >= $IOindex then n:= $IOindex-1 + mini:= $IOindex-n + maxi:= $IOindex-1 + showInputOrBoth = 'both => + UNWIND_-PROTECT(showInOut(mini,maxi),setIOindex(maxi+1)) + showInput(mini,maxi) + +setIOindex(n) == + -- set $IOindex to n + $IOindex:= n + +showInput(mini,maxi) == + -- displays all input lines from mini to maxi + for ind in mini..maxi repeat + vec:= UNWIND_-PROTECT(readHiFi(ind),disableHist()) + if ind<10 then TAB 2 else if ind<100 then TAB 1 + l := CAR vec + STRINGP l => + sayMSG ['" [",ind,'"] ",CAR vec] + sayMSG ['" [",ind,'"] " ] + for ln in l repeat + sayMSG ['" ", ln] + +showInOut(mini,maxi) == + -- displays all steps from mini to maxi + for ind in mini..maxi repeat + vec:= UNWIND_-PROTECT(readHiFi(ind),disableHist()) + sayMSG [CAR vec] + Alist:= ASSQ('%,CDR vec) => + triple:= CDR ASSQ('value,CDR Alist) + $IOindex:= ind + spadPrint(objValUnwrap triple,objMode triple) + +fetchOutput(n) == + -- result is the output of step n + (n = -1) and (val := getI("%",'value)) => val + $HiFiAccess => + n:= + n < 0 => $IOindex+n + n + n >= $IOindex => throwKeyedMsg("S2IH0001",[n]) + n < 1 => throwKeyedMsg("S2IH0002",[n]) + vec:= UNWIND_-PROTECT(readHiFi(n),disableHist()) + Alist:= ASSQ('%,CDR vec) => + val:= CDR ASSQ('value,CDR Alist) => val + throwKeyedMsg("S2IH0003",[n]) + throwKeyedMsg("S2IH0003",[n]) + throwKeyedMsg("S2IH0004",NIL) + +readHiFi(n) == + -- reads the file using index n + if $useInternalHistoryTable + then + pair := assoc(n,$internalHistoryTable) + ATOM pair => keyedSystemError("S2IH0034",NIL) + vec := QCDR pair + else + HiFi:= RDEFIOSTREAM ['(MODE . INPUT),['FILE,:histFileName()]] + vec:= SPADRREAD(object2Identifier n,HiFi) + RSHUT HiFi + vec + +writeHiFi() == + -- writes the information of the current step out to history file + if $useInternalHistoryTable + then + $internalHistoryTable := CONS([$IOindex,$currentLine,:$HistRecord], + $internalHistoryTable) + else + HiFi:= RDEFIOSTREAM ['(MODE . OUTPUT),['FILE,:histFileName()]] + SPADRWRITE(object2Identifier $IOindex, CONS($currentLine,$HistRecord),HiFi) + RSHUT HiFi + +disableHist() == + -- disables the history mechanism if an error occurred in the protected + -- piece of code + not $HiFiAccess => histFileErase histFileName() + NIL + +writeHistModesAndValues() == + for [a,:.] in CAAR $InteractiveFrame repeat + x := get(a,'value,$InteractiveFrame) => + putHist(a,'value,x,$InteractiveFrame) + x := get(a,'mode,$InteractiveFrame) => + putHist(a,'mode,x,$InteractiveFrame) + NIL + +SPADRREAD(vec, stream) == + dewritify rread(vec, stream, nil) + +--% Lisplib output transformations +-- Some types of objects cannot be saved by LISP/VM in lisplibs. +-- These functions transform an object to a writable form and back. +-- SMW +SPADRWRITE(vec, item, stream) == + val := SPADRWRITE0(vec, item, stream) + val = 'writifyFailed => + throwKeyedMsg("S2IH0036", nil) ; cannot save value to file + item + +SPADRWRITE0(vec, item, stream) == + val := safeWritify item + val = 'writifyFailed => val + rwrite(vec, val, stream) + item + +safeWritify ob == + CATCH('writifyTag, writify ob) + +writify ob == + not ScanOrPairVec(function(unwritable?), ob) => ob + $seen: local := MAKE_-HASHTABLE 'EQ + $writifyComplained: local := false + + writifyInner ob where + writifyInner ob == + null ob => nil + (e := HGET($seen, ob)) => e + + PAIRP ob => + qcar := QCAR ob + qcdr := QCDR ob + (name := spadClosure? ob) => + d := writifyInner QCDR ob + nob := ['WRITIFIED_!_!, 'SPADCLOSURE, d, name] + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + nob + (ob is ['LAMBDA_-CLOSURE, ., ., x, :.]) and x => + THROW('writifyTag, 'writifyFailed) + nob := CONS(qcar, qcdr) + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + qcar := writifyInner qcar + qcdr := writifyInner qcdr + QRPLACA(nob, qcar) + QRPLACD(nob, qcdr) + nob + VECP ob => + isDomainOrPackage ob => + d := mkEvalable devaluate ob + nob := ['WRITIFIED_!_!, 'DEVALUATED, writifyInner d] + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + nob + n := QVMAXINDEX ob + nob := MAKE_-VEC(n+1) + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + for i in 0..n repeat + QSETVELT(nob, i, writifyInner QVELT(ob,i)) + nob + ob = 'WRITIFIED_!_! => + ['WRITIFIED_!_!, 'SELF] + -- In CCL constructors are also compiled functions, so we + -- need this line: + constructor? ob => ob + COMPILED_-FUNCTION_-P ob => + THROW('writifyTag, 'writifyFailed) + HASHTABLEP ob => + nob := ['WRITIFIED_!_!] + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + keys := HKEYS ob + QRPLACD(nob, + ['HASHTABLE, + HASHTABLE_-CLASS ob, + writifyInner keys, + [writifyInner HGET(ob,k) for k in keys]]) + nob + PLACEP ob => + nob := ['WRITIFIED_!_!, 'PLACE] + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + nob + -- The next three types cause an error on de-writifying. + -- Create an object of the right shape, nonetheless. + READTABLEP ob => + THROW('writifyTag, 'writifyFailed) + -- Default case: return the object itself. + STRINGP ob => + EQ(ob, $NullStream) => ['WRITIFIED_!_!, 'NULLSTREAM] + EQ(ob, $NonNullStream) => ['WRITIFIED_!_!, 'NONNULLSTREAM] + ob + FLOATP ob => + ob = READ_-FROM_-STRING STRINGIMAGE ob => ob + ['WRITIFIED_!_!, 'FLOAT, ob,: + MULTIPLE_-VALUE_-LIST INTEGER_-DECODE_-FLOAT ob] + ob + + +unwritable? ob == + PAIRP ob or VECP ob => false -- first for speed + COMPILED_-FUNCTION_-P ob or HASHTABLEP ob => true + PLACEP ob or READTABLEP ob => true + FLOATP ob => true + false + +-- Create a full isomorphic object which can be saved in a lisplib. +-- Note that dewritify(writify(x)) preserves UEQUALity of hashtables. +-- HASHTABLEs go both ways. +-- READTABLEs cannot presently be transformed back. + +writifyComplain s == + $writifyComplained = true => nil + $writifyComplained := true + sayKeyedMsg("S2IH0027",[s]) + +spadClosure? ob == + fun := QCAR ob + not (name := BPINAME fun) => nil + vec := QCDR ob + not VECP vec => nil + name + +dewritify ob == + (not ScanOrPairVec(function is?, ob) + where is? a == a = 'WRITIFIED_!_!) => ob + + $seen: local := MAKE_-HASHTABLE 'EQ + + dewritifyInner ob where + dewritifyInner ob == + null ob => nil + e := HGET($seen, ob) => e + + PAIRP ob and CAR ob = 'WRITIFIED_!_! => + type := ob.1 + type = 'SELF => + 'WRITIFIED_!_! + type = 'BPI => + oname := ob.2 + f := + INTP oname => EVAL GENSYMMER oname + SYMBOL_-FUNCTION oname + not COMPILED_-FUNCTION_-P f => + error '"A required BPI does not exist." + #ob > 3 and HASHEQ f ^= ob.3 => + error '"A required BPI has been redefined." + HPUT($seen, ob, f) + f + type = 'HASHTABLE => + nob := MAKE_-HASHTABLE ob.2 + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + for k in ob.3 for e in ob.4 repeat + HPUT(nob, dewritifyInner k, dewritifyInner e) + nob + type = 'DEVALUATED => + nob := EVAL dewritifyInner ob.2 + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + nob + type = 'SPADCLOSURE => + vec := dewritifyInner ob.2 + name := ob.3 + not FBOUNDP name => + error STRCONC('"undefined function: ", SYMBOL_-NAME name) + nob := CONS(SYMBOL_-FUNCTION name, vec) + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + nob + type = 'PLACE => + nob := READ MAKE_-INSTREAM NIL + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + nob + type = 'READTABLE => + error '"Cannot de-writify a read table." + type = 'NULLSTREAM => $NullStream + type = 'NONNULLSTREAM => $NonNullStream + type = 'FLOAT => + [fval, signif, expon, sign] := CDDR ob + fval := SCALE_-FLOAT( FLOAT(signif, fval), expon) + sign<0 => -fval + fval + error '"Unknown type to de-writify." + + PAIRP ob => + qcar := QCAR ob + qcdr := QCDR ob + nob := CONS(qcar, qcdr) + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + QRPLACA(nob, dewritifyInner qcar) + QRPLACD(nob, dewritifyInner qcdr) + nob + VECP ob => + n := QVMAXINDEX ob + nob := MAKE_-VEC(n+1) + HPUT($seen, ob, nob) + HPUT($seen, nob, nob) + for i in 0..n repeat + QSETVELT(nob, i, dewritifyInner QVELT(ob,i)) + nob + -- Default case: return the object itself. + ob + +ScanOrPairVec(f, ob) == + $seen: local := MAKE_-HASHTABLE 'EQ + + CATCH('ScanOrPairVecAnswer, ScanOrInner(f, ob)) where + ScanOrInner(f, ob) == + HGET($seen, ob) => nil + PAIRP ob => + HPUT($seen, ob, true) + ScanOrInner(f, QCAR ob) + ScanOrInner(f, QCDR ob) + nil + VECP ob => + HPUT($seen, ob, true) + for i in 0..#ob-1 repeat ScanOrInner(f, ob.i) + nil + FUNCALL(f, ob) => + THROW('ScanOrPairVecAnswer, true) + nil + + + + + +--% )load + +load args == loadSpad2Cmd args + +loadSpad2Cmd args == + sayKeyedMsg("S2IU0003", nil) + NIL +-- load1(args,$forceDatabaseUpdate) + +--load1(args,$forceDatabaseUpdate) == -- $ var is now local +-- null args => helpSpad2Cmd '(load) +-- loadfun := 'loadLib +-- justWondering := nil +-- compiler := 'old +-- doExpose := true +-- $forceDatabaseUpdate := true -- BMT request, 5/14/90 +-- for [opt,:.] in $options repeat +-- fullopt := selectOptionLC(opt, +-- '(cond update query new noexpose noupdate), +-- 'optionError) +-- fullopt = 'cond => loadfun := 'loadLibIfNotLoaded +-- fullopt = 'query => justWondering := true +-- fullopt = 'update => $forceDatabaseUpdate := true +-- fullopt = 'noexpose => doExpose := false +-- fullopt = 'noupdate => $forceDatabaseUpdate := false +-- if $forceDatabaseUpdate then clearClams() +-- for lib in args repeat +-- lib := object2Identifier lib +-- justWondering => +-- GETL(lib,'LOADED) => sayKeyedMsg("S2IZ0028",[lib]) +-- sayKeyedMsg("S2IZ0029",[lib]) +-- null GETDATABASE(lib,'OBJECT) and +-- null (lib := GETDATABASE(lib,'CONSTRUCTOR)) => +-- sayKeyedMsg("S2IL0020", [namestring [lib,$spadLibFT,"*"]]) +-- null FUNCALL(loadfun,lib) => +-- sayKeyedMsg("S2IZ0029",[lib]) +-- sayKeyedMsg("S2IZ0028",[lib]) +-- if doExpose and +-- not isExposedConstructor(lib) then +-- setExposeAddConstr([lib]) +-- 'EndOfLoad + +reportCount () == + centerAndHighlight(" Current Count Settings ",$LINELENGTH,specialChar 'hbar) + SAY " " + sayBrightly [:bright " cache",fillerSpaces(30,'".")," ",$cacheCount] + if $cacheAlist then + for [a,:b] in $cacheAlist repeat + aPart:= linearFormatName a + n:= sayBrightlyLength aPart + sayBrightly concat(" ",aPart," ",fillerSpaces(32-n,'".")," ",b) + SAY " " + sayBrightly [:bright " stream",fillerSpaces(29,'".")," ",$streamCount] + +--% )quit + +pquit() == pquitSpad2Cmd() + +pquitSpad2Cmd() == + $saturn => + sayErrorly('"Obsolete system command", _ + ['" The )pquit system command is obsolete in this version of AXIOM.", + '" Please select Exit from the File Menu instead."]) + $quitCommandType :local := 'protected + quitSpad2Cmd() + +quit() == quitSpad2Cmd() + +quitSpad2Cmd() == + $saturn => + sayErrorly('"Obsolete system command", _ + ['" The )quit system command is obsolete in this version of AXIOM.", + '" Please select Exit from the File Menu instead."]) + $quitCommandType ^= 'protected => leaveScratchpad() + x := UPCASE queryUserKeyedMsg("S2IZ0031",NIL) + MEMQ(STRING2ID_-N(x,1),'(Y YES)) => leaveScratchpad() + sayKeyedMsg("S2IZ0032",NIL) + TERSYSCOMMAND () + +leaveScratchpad () == BYE() + +--% )read + +read l == readSpad2Cmd l + +readSpad2Cmd l == + ---$saturn => + --- sayErrorly('"Obsolete system command", _ + --- ['" The )read system command is obsolete in this version of AXIOM.", + --- '" Please use Open from the File menu instead."]) + $InteractiveMode : local := true + quiet := nil + ifthere := nil + for [opt,:.] in $options repeat + fullopt := selectOptionLC(opt,'(quiet test ifthere),'optionError) + fullopt = 'ifthere => ifthere := true + fullopt = 'quiet => quiet := true + + ef := pathname _/EDITFILE + if pathnameTypeId(ef) = 'SPAD then + ef := makePathname(pathnameName ef,'"*",'"*") + if l then + l := mergePathnames(pathname l,ef) + else + l := ef + devFTs := '("input" "INPUT" "boot" "BOOT" "lisp" "LISP") + fileTypes := + $UserLevel = 'interpreter => '("input" "INPUT") + $UserLevel = 'compiler => '("input" "INPUT") + devFTs + ll := $FINDFILE (l, fileTypes) + if null ll then + ifthere => return nil -- be quiet about it + throwKeyedMsg("S2IL0003",[namestring l]) + ll := pathname ll + ft := pathnameType ll + upft := UPCASE ft + null member(upft,fileTypes) => + fs := namestring l + member(upft,devFTs) => throwKeyedMsg("S2IZ0033",[fs]) + throwKeyedMsg("S2IZ0034",[fs]) + SETQ(_/EDITFILE,ll) + if upft = '"BOOT" then $InteractiveMode := nil + _/READ(ll,quiet) + +--% )savesystem +savesystem l == + #l ^= 1 or not(SYMBOLP CAR l) => helpSpad2Cmd '(savesystem) + SPAD_-SAVE SYMBOL_-NAME CAR l + +--% )show + +show l == showSpad2Cmd l + +showSpad2Cmd l == + l = [NIL] => helpSpad2Cmd '(show) + $showOptions : local := '(attributes operations) + if null $options then $options := '((operations)) + $e : local := $InteractiveFrame + $env : local := $InteractiveFrame + l is [constr] => + constr in '(Union Record Mapping) => + constr = 'Record => + sayKeyedMsg("S2IZ0044R",[constr, '")show Record(a: Integer, b: String)"]) + constr = 'Mapping => + sayKeyedMsg("S2IZ0044M",NIL) + sayKeyedMsg("S2IZ0045T",[constr, '")show Union(a: Integer, b: String)"]) + sayKeyedMsg("S2IZ0045U",[constr, '")show Union(Integer, String)"]) + constr is ['Mapping, :.] => + sayKeyedMsg("S2IZ0044M",NIL) + reportOperations(constr,constr) + reportOperations(l,l) + +reportOperations(oldArg,u) == + -- u might be an uppercased version of oldArg + $env:local := [[NIL]] + $eval:local := true --generate code-- don't just type analyze + $genValue:local := true --evaluate all generated code + null u => nil + $doNotAddEmptyModeIfTrue: local:= true + u = $quadSymbol => + sayBrightly ['" mode denotes", :bright '"any", "type"] + u = "%" => + sayKeyedMsg("S2IZ0063",NIL) + sayKeyedMsg("S2IZ0064",NIL) + u isnt ['Record,:.] and u isnt ['Union,:.] and + null(isNameOfType u) and u isnt ['typeOf,.] => + if ATOM oldArg then oldArg := [oldArg] + sayKeyedMsg("S2IZ0063",NIL) + for op in oldArg repeat + sayKeyedMsg("S2IZ0062",[opOf op]) + (v := isDomainValuedVariable u) => reportOpsFromUnitDirectly0 v + unitForm:= + atom u => opOf unabbrev u + unabbrev u + atom unitForm => reportOpsFromLisplib0(unitForm,u) + unitForm' := evaluateType unitForm + tree := mkAtree removeZeroOneDestructively unitForm + (unitForm' := isType tree) => reportOpsFromUnitDirectly0 unitForm' + sayKeyedMsg("S2IZ0041",[unitForm]) + +reportOpsFromUnitDirectly0 D == + $useEditorForShowOutput => + reportOpsFromUnitDirectly1 D + reportOpsFromUnitDirectly D + +reportOpsFromUnitDirectly1 D == + showFile := pathname ['SHOW,'LISTING,$listingDirectory] + _$ERASE showFile + $sayBrightlyStream : fluid := + DEFIOSTREAM([['FILE,:showFile], '(MODE . OUTPUT)],255,0) + sayShowWarning() + reportOpsFromUnitDirectly D + SHUT $sayBrightlyStream + editFile showFile + +sayShowWarning() == + sayBrightly + '"Warning: this is a temporary file and will be deleted the next" + sayBrightly + '" time you use )show. Rename it and FILE if you wish to" + sayBrightly + '" save the contents." + sayBrightly '"" + +reportOpsFromLisplib0(unitForm,u) == + $useEditorForShowOutput => reportOpsFromLisplib1(unitForm,u) + reportOpsFromLisplib(unitForm,u) + +reportOpsFromLisplib1(unitForm,u) == + showFile := pathname ['SHOW,'LISTING,$listingDirectory] + _$ERASE showFile + $sayBrightlyStream : fluid := + DEFIOSTREAM([['FILE,:showFile], '(MODE . OUTPUT)],255,0) + sayShowWarning() + reportOpsFromLisplib(unitForm,u) + SHUT $sayBrightlyStream + editFile showFile + +reportOpsFromUnitDirectly unitForm == + isRecordOrUnion := unitForm is [a,:.] and a in '(Record Union) + unit:= evalDomain unitForm + top:= CAR unitForm + kind:= GETDATABASE(top,'CONSTRUCTORKIND) + + sayBrightly concat('%b,formatOpType unitForm, + '%d,'"is a",'%b,kind,'%d, '"constructor.") + if not isRecordOrUnion then + abb := GETDATABASE(top,'ABBREVIATION) + sourceFile := GETDATABASE(top,'SOURCEFILE) + sayBrightly ['" Abbreviation for",:bright top,'"is",:bright abb] + verb := + isExposedConstructor top => '"is" + '"is not" + sayBrightly ['" This constructor",:bright verb, + '"exposed in this frame."] + sayBrightly ['" Issue",:bright STRCONC('")edit ", + namestring sourceFile),'"to see algebra source code for", + :bright abb,'%l] + + for [opt] in $options repeat + opt := selectOptionLC(opt,$showOptions,'optionError) + opt = 'attributes => + centerAndHighlight('"Attributes",$LINELENGTH,specialChar 'hbar) + isRecordOrUnion => + sayBrightly '" Records and Unions have no attributes." + sayBrightly '"" + attList:= REMDUP MSORT [x for [x,:.] in unit.2] + say2PerLine [formatAttribute x for x in attList] + NIL + opt = 'operations => + $commentedOps: local := 0 + --new form is (<op> <signature> <slotNumber> <condition> <kind>) + centerAndHighlight('"Operations",$LINELENGTH,specialChar 'hbar) + sayBrightly '"" + if isRecordOrUnion + then + constructorFunction:= GETL(top,"makeFunctionList") or + systemErrorHere '"reportOpsFromUnitDirectly" + [funlist,.]:= FUNCALL(constructorFunction,"$",unitForm, + $CategoryFrame) + sigList := REMDUP MSORT [[[a,b],true,[c,0,1]] for + [a,b,c] in funlist] + else + sigList:= REMDUP MSORT getOplistForConstructorForm unitForm + say2PerLine [formatOperation(x,unit) for x in sigList] + if $commentedOps ^= 0 then + sayBrightly + ['"Functions that are not yet implemented are preceded by", + :bright '"--"] + sayBrightly '"" + NIL + +reportOpsFromLisplib(op,u) == + null(fn:= constructor? op) => sayKeyedMsg("S2IZ0054",[u]) + argml := + (s := getConstructorSignature op) => KDR s + NIL + typ:= GETDATABASE(op,'CONSTRUCTORKIND) + nArgs:= #argml + argList:= KDR GETDATABASE(op,'CONSTRUCTORFORM) + functorForm:= [op,:argList] + argml:= EQSUBSTLIST(argList,$FormalMapVariableList,argml) + functorFormWithDecl:= [op,:[[":",a,m] for a in argList for m in argml]] + sayBrightly concat(bright form2StringWithWhere functorFormWithDecl, + '" is a",bright typ,'"constructor") + sayBrightly ['" Abbreviation for",:bright op,'"is",:bright fn] + verb := + isExposedConstructor op => '"is" + '"is not" + sayBrightly ['" This constructor",:bright verb, + '"exposed in this frame."] + sourceFile := GETDATABASE(op,'SOURCEFILE) + sayBrightly ['" Issue",:bright STRCONC('")edit ", + namestring sourceFile), + '"to see algebra source code for",:bright fn,'%l] + + for [opt] in $options repeat + opt := selectOptionLC(opt,$showOptions,'optionError) + opt = 'layout => + dc1 fn + opt = 'views => sayBrightly ['"To get",:bright '"views", + '"you must give parameters of constructor"] + opt = 'attributes => + centerAndHighlight('"Attributes",$LINELENGTH,specialChar 'hbar) + sayBrightly '"" + attList:= REMDUP MSORT [x for [x,:.] in + GETDATABASE(op,'ATTRIBUTES)] + null attList => sayBrightly + concat('%b,form2String functorForm,'%d,"has no attributes.",'%l) + say2PerLine [formatAttribute x for x in attList] + NIL + opt = 'operations => displayOperationsFromLisplib functorForm + nil + +displayOperationsFromLisplib form == + [name,:argl] := form + kind := GETDATABASE(name,'CONSTRUCTORKIND) + centerAndHighlight('"Operations",$LINELENGTH,specialChar 'hbar) + opList:= GETDATABASE(name,'OPERATIONALIST) + null opList => reportOpsFromUnitDirectly form + opl:=REMDUP MSORT EQSUBSTLIST(argl,$FormalMapVariableList,opList) + ops:= nil + for x in opl repeat + ops := [:ops,:formatOperationAlistEntry(x)] + say2PerLine ops + nil + +--% )synonym + +synonym(:l) == synonymSpad2Cmd() -- always passed a null list + +synonymSpad2Cmd() == + line := getSystemCommandLine() + if line = '"" then printSynonyms(NIL) + else + pair := processSynonymLine line + if $CommandSynonymAlist then + PUTALIST($CommandSynonymAlist,CAR pair, CDR pair) + else $CommandSynonymAlist := [pair] + terminateSystemCommand() + +processSynonymLine line == + key := STRING2ID_-N (line, 1) + value := removeKeyFromLine line where + removeKeyFromLine line == + line := dropLeadingBlanks line + mx := MAXINDEX line + for i in 0..mx repeat + line.i = " " => + return (for j in (i+1)..mx repeat + line.j ^= " " => return (SUBSTRING (line, j, nil))) + [key, :value] + + +--% +--% )undo +--% + +$undoFlag := true --Default setting for undo is "on" + + +undo(l) == +--undo takes one option ")redo" which simply reads "redo.input", +-- a file created by every normal )undo command (see below) + undoWhen := 'after + if $options is [[key]] then + stringPrefix?(s := PNAME key,'"redo") => + $options := nil --clear $options so that "read" won't see them + read '(redo_.input) + not stringPrefix?(s,'"before") => + userError '"only option to undo is _")redo_"" + undoWhen := 'before + n := + null l => -1 + first l + if IDENTP n then + n := PARSE_-INTEGER PNAME n + if not FIXP n then userError '"undo argument must be an integer" + $InteractiveFrame := undoSteps(undoCount n,undoWhen) + nil + +recordFrame(systemNormal) == + null $undoFlag => nil --do nothing if facility is turned off + currentAlist := KAR $frameRecord + delta := diffAlist(CAAR $InteractiveFrame,$previousBindings) + if systemNormal = 'system then + null delta => return nil --do not record + delta := ['systemCommand,:delta] + $frameRecord := [delta,:$frameRecord] + $previousBindings := --copy all but the individual properties + [CONS(CAR x,[CONS(CAR y,CDR y) for y in CDR x]) for x in CAAR $InteractiveFrame] + first $frameRecord + +diffAlist(new,old) == +--record only those properties which are different + for (pair := [name,:proplist]) in new repeat + -- name has an entry both in new and old world + -- (1) if the old world had no proplist for that variable, then + -- record NIL as the value of each new property + -- (2) if the old world does have a proplist for that variable, then + -- a) for each property with a value: give the old value + -- b) for each property missing: give NIL as the old value + oldPair := ASSQ(name,old) => + null (oldProplist := CDR oldPair) => + --record old values of new properties as NIL + acc := [[name,:[[prop] for [prop,:.] in proplist]],:acc] + deltas := nil + for (propval := [prop,:val]) in proplist repeat + null (oldPropval := ASSOC(prop,oldProplist)) => --missing property + deltas := [[prop],:deltas] + EQ(CDR oldPropval,val) => 'skip + deltas := [oldPropval,:deltas] + deltas => acc := [[name,:NREVERSE deltas],:acc] + acc := [[name,:[[prop] for [prop,:.] in proplist]],:acc] +--record properties absent on new list (say, from a )cl all) + for (oldPair := [name,:r]) in old repeat + r and null LASSQ(name,new) => + acc := [oldPair,:acc] + -- name has an entry both in new and old world + -- (1) if the new world has no proplist for that variable + -- (a) if the old world does, record the old proplist + -- (b) if the old world does not, record nothing + -- (2) if the new world has a proplist for that variable, it has + -- been handled by the first loop. + res := NREVERSE acc + if BOUNDP '$reportUndo and $reportUndo then reportUndo res + res + +reportUndo acc == + for [name,:proplist] in acc repeat + sayBrightly STRCONC("Properties of ",PNAME name,'" ::") + curproplist := LASSOC(name,CAAR $InteractiveFrame) + for [prop,:value] in proplist repeat + sayBrightlyNT ['" ",prop,'" was: "] + pp value + sayBrightlyNT ['" ",prop,'" is: "] + pp LASSOC(prop,curproplist) + +clearFrame() == + clearCmdAll() + $frameRecord := nil + $previousBindings := nil + + +--======================================================================= +-- Undoing previous m commands +--======================================================================= +undoCount(n) == --computes the number of undo's, given $IOindex +--pp ["IOindex = ",$IOindex] + m := + n >= 0 => $IOindex - n - 1 + -n + m >= $IOindex => userError STRCONC('"Magnitude of undo argument must be less than step number (",STRINGIMAGE $IOindex,'").") + m + + +undoSteps(m,beforeOrAfter) == +-- undoes m previous commands; if )before option, then undo one extra at end +--Example: if $IOindex now is 6 and m = 2 then general layout of $frameRecord, +-- after the call to recordFrame below will be: +-- (<change for systemcommands> +-- (<change for #5> <change for system commands> +-- (<change for #4> <change for system commands> +-- (<change for #3> <change for system commands> +-- <change for #2> <change for system commands> +-- <change for #1> <change for system commands>) where system +-- command entries are optional and identified by (systemCommand . change). +-- For a ")undo 3 )after", m = 2 and undoStep swill restore the environment +-- up to, but not including <change for #3>. +-- An "undo 3 )before" will additionally restore <change for #3>. +-- Thus, the later requires one extra undo at the end. + writeInputLines('redo,$IOindex - m) + recordFrame('normal) --do NOT mark this as a system command change + --do this undo FIRST (i=0 case) + env := COPY CAAR $InteractiveFrame + for i in 0..m for framelist in tails $frameRecord repeat + env := undoSingleStep(first framelist,env) + framelist is [.,['systemCommand,:systemDelta],:.] => +-- pp '"===============> AHA <=============" + framelist := rest framelist --undoing system commands given + env := undoSingleStep(systemDelta,env) -- before command line + lastTailSeen := framelist + if beforeOrAfter = 'before then --do one additional undo for )before + env := undoSingleStep(first rest lastTailSeen,env) + $frameRecord := rest $frameRecord --flush the effect of extra recordFrame + $InteractiveFrame := LIST LIST env + + +undoSingleStep(changes,env) == +--Each change is a name-proplist pair. For each change: +-- (1) if there exists a proplist in env, then for each prop-value change: +-- (a) if the prop exists in env, RPLAC in the change value +-- (b) otherwise, CONS it onto the front of prop-values for that name +-- (2) add change to the front of env +-- pp '"----Undoing 1 step--------" +-- pp changes + for (change := [name,:changeList]) in changes repeat + if LASSOC('localModemap,changeList) then + changeList := undoLocalModemapHack changeList + pairlist := ASSQ(name,env) => + proplist := CDR pairlist => + for (pair := [prop,:value]) in changeList repeat + node := ASSQ(prop,proplist) => RPLACD(node,value) + RPLACD(proplist,[CAR proplist,:CDR proplist]) + RPLACA(proplist,pair) + RPLACD(pairlist,changeList) + env := [change,:env] + env + +undoLocalModemapHack changeList == + [newPair for (pair := [name,:value]) in changeList | newPair] where newPair == + name = 'localModemap => [name] + pair + +removeUndoLines u == --called by writeInputLines + xtra := + STRINGP $currentLine => [$currentLine] + REVERSE $currentLine + xtra := [x for x in xtra | not stringPrefix?('")history",x)] + u := [:u, :xtra] + not (or/[stringPrefix?('")undo",x) for x in u]) => u + --(1) reverse the list + --(2) walk down the (reversed) list: when >n appears remove: + -- (a) system commands + -- (b) if n > 0: (replace n by n-1; remove a command; repeat (a-b)) + savedIOindex := $IOindex --save value + $IOindex := 1 + for y in tails u repeat + (x := first y).0 = char '_) => + stringPrefix?('")undo",s := trimString x) => --parse "undo )option" + s1 := trimString SUBSTRING(s,5,nil) + if s1 ^= '")redo" then + m := charPosition(char '_),s1,0) + code := + m < MAXINDEX s1 => s1.(m + 1) + char 'a + s2 := trimString SUBSTRING(s1,0,m) + n := + s1 = '")redo" => 0 + s2 ^= '"" => undoCount PARSE_-INTEGER s2 + -1 + RPLACA(y,CONCAT('">",code,STRINGIMAGE n)) + nil + $IOindex := $IOindex + 1 --referenced by undoCount + acc := nil + for y in tails NREVERSE u repeat + (x := first y).0 = char '_> => + code := x . 1 --code = a,b, or r + n := PARSE_-INTEGER SUBSTRING(x,2,nil) --n = number of undo steps + y := rest y --kill >n line + while y repeat + c := first y + c.0 = char '_) or c.0 = char '_> => y := rest y --kill system commands + n = 0 => return nil --including undos + n := n - 1 + y := rest y --kill command + y and code^= char 'b => acc := [c,:acc] --add last unless )before + acc := [x,:acc] + $IOindex := savedIOindex + acc + + + + +--% )what + + +what l == whatSpad2Cmd l + +whatSpad2Cmd l == + $e:local := $EmptyEnvironment + null l => reportWhatOptions() + [key0,:args] := l + key := selectOptionLC(key0,$whatOptions,nil) + null key => sayKeyedMsg("S2IZ0043",NIL) + args := [fixpat p for p in args] where + fixpat x == + x is [x',:.] => DOWNCASE x' + DOWNCASE x + key = 'things => + for opt in $whatOptions repeat + not MEMQ(opt,'(things)) => whatSpad2Cmd [opt,:args] + key = 'categories => + filterAndFormatConstructors('category,'"Categories",args) + key = 'commands => + whatCommands(args) + key = 'domains => + filterAndFormatConstructors('domain,'"Domains",args) + key = 'operations => + apropos args + key = 'packages => + filterAndFormatConstructors('package,'"Packages",args) + key = 'synonyms => + printSynonyms(args) + +filterAndFormatConstructors(constrType,label,patterns) == + centerAndHighlight(label,$LINELENGTH,specialChar 'hbar) + l := filterListOfStringsWithFn(patterns,whatConstructors constrType, + function CDR) + if patterns then + null l => + sayMessage ['" No ",label,'" with names matching patterns:", + '%l,'" ",'%b,:blankList patterns,'%d] + sayMessage [label,'" with names matching patterns:", + '%l,'" ",'%b,:blankList patterns,'%d] + l => pp2Cols l + +whatConstructors constrType == + -- here constrType should be one of 'category, 'domain, 'package + MSORT [CONS(GETDATABASE(con,'ABBREVIATION), STRING(con)) + for con in allConstructors() + | GETDATABASE(con,'CONSTRUCTORKIND) = constrType] + +apropos l == + -- l is a list of operation name fragments + -- this displays all operation names containing these fragments + ops := + null l => allOperations() + filterListOfStrings([(DOWNCASE STRINGIMAGE p) for p in l],allOperations()) + ops => + sayMessage '"Operations whose names satisfy the above pattern(s):" + sayAsManyPerLineAsPossible MSORT ops + sayKeyedMsg("S2IF0011",[first ops]) + sayMessage '" There are no operations containing those patterns" + NIL + + +printSynonyms(patterns) == + centerAndHighlight("System Command Synonyms",$LINELENGTH,specialChar 'hbar) + ls := filterListOfStringsWithFn(patterns, [[STRINGIMAGE a,:b] + for [a,:b] in synonymsForUserLevel $CommandSynonymAlist], + function CAR) + printLabelledList(ls,'"user",'"synonyms",'")",patterns) + nil + +printLabelledList(ls,label1,label2,prefix,patterns) == + -- prefix goes before each element on each side of the list, eg, + -- ")" + null ls => + null patterns => + sayMessage ['" No ",label1,'"-defined ",label2,'" in effect."] + sayMessage ['" No ",label1,'"-defined ",label2,'" satisfying patterns:", + '%l,'" ",'%b,:blankList patterns,'%d] + if patterns then + sayMessage [label1,'"-defined ",label2,'" satisfying patterns:", + '%l,'" ",'%b,:blankList patterns,'%d] + for [syn,:comm] in ls repeat + if SUBSTRING(syn,0,1) = '"|" then syn := SUBSTRING(syn,1,NIL) + if syn = '"%i" then syn := '"%i " + wid := MAX(30 - (entryWidth syn),1) + sayBrightly concat('%b,prefix,syn,'%d, + fillerSpaces(wid,'"."),'" ",prefix,comm) + sayBrightly '"" + +whatCommands(patterns) == + label := STRCONC("System Commands for User Level: ", + STRINGIMAGE $UserLevel) + centerAndHighlight(label,$LINELENGTH,specialChar 'hbar) + l := filterListOfStrings(patterns, + [(STRINGIMAGE a) for a in commandsForUserLevel $systemCommands]) + if patterns then + null l => + sayMessage ['"No system commands at this level matching patterns:", + '%l,'" ",'%b,:blankList patterns,'%d] + sayMessage ['"System commands at this level matching patterns:", + '%l,'" ",'%b,:blankList patterns,'%d] + if l then + sayAsManyPerLineAsPossible l + SAY " " + patterns => nil -- don't be so verbose + sayKeyedMsg("S2IZ0046",NIL) + nil + +reportWhatOptions() == + optList1:= "append"/[['%l,'" ",x] for x in $whatOptions] + sayBrightly + ['%b,'" )what",'%d,'"argument keywords are",'%b,:optList1,'%d,'%l, + '" or abbreviations thereof.",'%l, + '%l,'" Issue",'%b,'")what ?",'%d,'"for more information."] + +filterListOfStrings(patterns,names) == + -- names and patterns are lists of strings + -- returns: list of strings in names that contains any of the strings + -- in patterns + (null patterns) or (null names) => names + names' := NIL + for name in reverse names repeat + satisfiesRegularExpressions(name,patterns) => + names' := [name,:names'] + names' + +filterListOfStringsWithFn(patterns,names,fn) == + -- names and patterns are lists of strings + -- fn is something like CAR or CADR + -- returns: list of strings in names that contains any of the strings + -- in patterns + (null patterns) or (null names) => names + names' := NIL + for name in reverse names repeat + satisfiesRegularExpressions(FUNCALL(fn,name),patterns) => + names' := [name,:names'] + names' + +satisfiesRegularExpressions(name,patterns) == + -- this is a first cut + nf := true + dname := DOWNCASE COPY name + for pattern in patterns while nf repeat + -- use @ as a wildcard + STRPOS(pattern,dname,0,'"@") => nf := nil + null nf + +--% )with ... defined in daase.lisp (boot won't parse it) + +--% )workfiles + +workfiles l == workfilesSpad2Cmd l + +workfilesSpad2Cmd args == + args => throwKeyedMsg("S2IZ0047",NIL) + deleteFlag := nil + for [type,:.] in $options repeat + type1 := selectOptionLC(type,'(boot lisp meta delete),nil) + null type1 => throwKeyedMsg("S2IZ0048",[type]) + type1 = 'delete => deleteFlag := true + for [type,:flist] in $options repeat + type1 := selectOptionLC(type,'(boot lisp meta delete),nil) + type1 = 'delete => nil + for file in flist repeat + fl := pathname [file,type1,'"*"] + deleteFlag => SETQ($sourceFiles,delete(fl,$sourceFiles)) + null (MAKE_-INPUT_-FILENAME fl) => sayKeyedMsg("S2IZ0035",[namestring fl]) + updateSourceFiles fl + SAY " " + centerAndHighlight(" User-specified work files ",$LINELENGTH,specialChar 'hbar) + SAY " " + null $sourceFiles => SAY '" no files specified" + SETQ($sourceFiles,SORTBY('pathnameType,$sourceFiles)) + for fl in $sourceFiles repeat sayBrightly [" " ,namestring fl] + +--% )zsystemdevelopment + +zsystemdevelopment l == zsystemDevelopmentSpad2Cmd l + +zsystemDevelopmentSpad2Cmd l == zsystemdevelopment1 (l,$InteractiveMode) + +zsystemdevelopment1(l,im) == + $InteractiveMode : local := im + fromopt := nil + -- cycle through once to see if )from is mentioned + for [opt,:optargs] in $options repeat + opt1 := selectOptionLC(opt,'(from),nil) + opt1 = 'from => fromopt := [['FROM,:optargs]] + for [opt,:optargs] in $options repeat + if null optargs then optargs := l + newopt := APPEND(optargs,fromopt) + opt1 := selectOptionLC(opt,'(from),nil) + opt1 = 'from => nil + opt = "c" => _/D_,1 (newopt ,_/COMP(),NIL,NIL) + opt = "d" => _/D_,1 (newopt ,'DEFINE,NIL,NIL) + opt = "dt" => _/D_,1 (newopt ,'DEFINE,NIL,true) + opt = "ct" => _/D_,1 (newopt ,_/COMP(),NIL,true) + opt = "ctl" => _/D_,1 (newopt ,_/COMP(),NIL,'TRACELET) + opt = "ec" => _/D_,1 (newopt ,_/COMP(),true,NIL) + opt = "ect" => _/D_,1 (newopt ,_/COMP(),true,true) + opt = "e" => _/D_,1 (newopt ,NIL,true,NIL) + opt = "version" => version() + opt = "pause" => + conStream := DEFIOSTREAM ('((DEVICE . CONSOLE) (QUAL . V)),120,0) + NEXT conStream + SHUT conStream + opt = "update" or opt = "patch" => + $InteractiveMode := nil + upf := [KAR optargs or _/VERSION, KADR optargs or _/WSNAME, + KADDR optargs or '_*] + fun := (opt = "patch" => '_/UPDATE_-LIB_-1; '_/UPDATE_-1) + CATCH('FILENAM, FUNCALL(fun, upf)) + sayMessage '" Update/patch is completed." + null optargs => + sayBrightly ['" An argument is required for",:bright opt] + sayMessage ['" Unknown option:",:bright opt," ",'%l, + '" Available options are", _ + :bright '"c ct e ec ect cls pause update patch compare record"] + +--% Synonym File Reader + +--------------------> NEW DEFINITION (override in util.lisp.pamphlet) +processSynonyms() == + p := STRPOS('")",LINE,0,NIL) + fill := '"" + if p + then + line := SUBSTRING(LINE,p,NIL) + if p > 0 then fill := SUBSTRING(LINE,0,p) + else + p := 0 + line := LINE + to := STRPOS ('" ", line, 1, nil) + if to then to := to - 1 + synstr := SUBSTRING (line, 1, to) + syn := STRING2ID_-N (synstr, 1) + null (fun := LASSOC (syn, $CommandSynonymAlist)) => NIL + to := STRPOS('")",fun,1,NIL) + if to and to ^= SIZE(fun)-1 then + opt := STRCONC('" ",SUBSTRING(fun,to,NIL)) + fun := SUBSTRING(fun,0,to-1) + else opt := '" " + if (SIZE synstr) > (SIZE fun) then + for i in (SIZE fun)..(SIZE synstr) repeat + fun := CONCAT (fun, '" ") +-- $currentLine := STRCONC(fill,RPLACSTR(line, 1, SIZE synstr, fun),opt) + cl := STRCONC(fill,RPLACSTR(line, 1, SIZE synstr, fun),opt) + SETQ(LINE,cl) + SETQ(CHR,LINE.(p+1)) + processSynonyms () + +-- functions for interfacing to system commands from algebra code +-- common lisp dependent + +tabsToBlanks s == + k := charPosition($charTab,s,0) + n := #s + k < n => + k = 0 => tabsToBlanks SUBSTRING(s,1,nil) + STRCONC(SUBSTRING(s,0,k),$charBlank, tabsToBlanks SUBSTRING(s,k + 1,nil)) + s + +doSystemCommand string == + string := CONCAT('")", EXPAND_-TABS string) + LINE: fluid := string + processSynonyms() + string := LINE + string:=SUBSTRING(string,1,nil) + string = '"" => nil + tok:=getFirstWord(string) + tok => + unab := unAbbreviateKeyword tok + member(unab, $noParseCommands) => + handleNoParseCommands(unab, string) + optionList := splitIntoOptionBlocks string + member(unab, $tokenCommands) => + handleTokensizeSystemCommands(unab, optionList) + handleParsedSystemCommands(unab, optionList) + nil + nil + +<<handleNoParseCommands>> + +npboot str == + sex := string2BootTree str + FORMAT(true, '"~&~S~%", sex) + $ans := EVAL sex + FORMAT(true, '"~&Value = ~S~%", $ans) + +stripLisp str == + found := false + strIndex := 0 + lispStr := '"lisp" + for c0 in 0..#str-1 for c1 in 0..#lispStr-1 repeat + (char str.c0) ^= (char lispStr.c1) => + return nil + strIndex := c0+1 + SUBSEQ(str, strIndex) + + +nplisp str == + $ans := EVAL READ_-FROM_-STRING str + FORMAT(true, '"~&Value = ~S~%", $ans) + +npsystem(unab, str) == + spaceIndex := SEARCH('" ", str) + null spaceIndex => + sayKeyedMsg('"S2IZ0080", [str]) + sysPart := SUBSEQ(str, 0, spaceIndex) + -- The following is a hack required by the fact that unAbbreviateKeyword + -- returns the word "system" for unknown words + null SEARCH(sysPart, STRING unab) => + sayKeyedMsg('"S2IZ0080", [sysPart]) + command := SUBSEQ(str, spaceIndex+1) + OBEY command + +npsynonym(unab, str) == + npProcessSynonym(str) + +tokenSystemCommand(unabr, tokList) == + systemCommand tokList + +tokTran tok == + STRINGP tok => + #tok = 0 => nil + isIntegerString tok => READ_-FROM_-STRING tok + STRING tok.0 = '"_"" => + SUBSEQ(tok, 1, #tok-1) + INTERN tok + tok + +isIntegerString tok == + for i in 0..#tok-1 repeat + val := DIGIT_-CHAR_-P tok.i + not val => return nil + val + +splitIntoOptionBlocks str == + inString := false + optionBlocks := nil + blockStart := 0 + parenCount := 0 + for i in 0..#str-1 repeat + STRING str.i = '"_"" => + inString := not inString + if STRING str.i = '"(" and not inString + then parenCount := parenCount + 1 + if STRING str.i = '")" and not inString + then parenCount := parenCount - 1 + STRING str.i = '")" and not inString and parenCount = -1 => + block := stripSpaces SUBSEQ(str, blockStart, i) + blockList := [block, :blockList] + blockStart := i+1 + parenCount := 0 + blockList := [stripSpaces SUBSEQ(str, blockStart), :blockList] + nreverse blockList + +dumbTokenize str == + -- split into tokens delimted by spaces, taking quoted strings into account + inString := false + tokenList := nil + tokenStart := 0 + previousSpace := false + for i in 0..#str-1 repeat + STRING str.i = '"_"" => + inString := not inString + previousSpace := false + STRING str.i = '" " and not inString => + previousSpace => nil + token := stripSpaces SUBSEQ(str, tokenStart, i) + tokenList := [token, :tokenList] + tokenStart := i+1 + previousSpace := true + previousSpace := false + tokenList := [stripSpaces SUBSEQ(str, tokenStart), :tokenList] + nreverse tokenList + +handleParsedSystemCommands(unabr, optionList) == + restOptionList := [dumbTokenize opt for opt in CDR optionList] + parcmd := [parseSystemCmd CAR optionList, + :[[tokTran tok for tok in opt] for opt in restOptionList]] + systemCommand parcmd + +parseSystemCmd opt == + spaceIndex := SEARCH('" ", opt) + spaceIndex => + commandString := stripSpaces SUBSEQ(opt, 0, spaceIndex) + argString := stripSpaces SUBSEQ(opt, spaceIndex) + command := tokTran commandString + pform := parseFromString argString + [command, pform] + [tokTran tok for tok in dumbTokenize opt] + +--------------------> NEW DEFINITION (override in osyscmd.boot.pamphlet) +parseFromString(s) == + $useNewParser => + ncParseFromString s + $InteractiveMode :local := true + $BOOT: local := NIL + $SPAD: local := true + $e:local := $InteractiveFrame + string2SpadTree s + +handleTokensizeSystemCommands(unabr, optionList) == + optionList := [dumbTokenize opt for opt in optionList] + parcmd := [[tokTran tok for tok in opt] for opt in optionList] + parcmd => tokenSystemCommand(unabr, parcmd) + +getFirstWord string == + spaceIndex := SEARCH('" ", string) + null spaceIndex => string + stripSpaces SUBSEQ(string, 0, spaceIndex) + +ltrace l == trace l + +--------------------> NEW DEFINITION (see intint.lisp.pamphlet) +stripSpaces str == + STRING_-TRIM([char '" "], str) + +npProcessSynonym(str) == + if str = '"" then printSynonyms(NIL) + else + pair := processSynonymLine str + if $CommandSynonymAlist then + PUTALIST($CommandSynonymAlist,CAR pair, CDR pair) + else $CommandSynonymAlist := [pair] + terminateSystemCommand() + + + + +@ +\eject +\begin{thebibliography}{99} +\bibitem{1} [[src/interp/setq.lisp.pamphlet]] +\end{thebibliography} +\end{document} |