diff options
Diffstat (limited to 'macros/generic/basix/basix.tex')
-rw-r--r-- | macros/generic/basix/basix.tex | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/macros/generic/basix/basix.tex b/macros/generic/basix/basix.tex new file mode 100644 index 0000000000..1592ff5853 --- /dev/null +++ b/macros/generic/basix/basix.tex @@ -0,0 +1,474 @@ +% +% BaSiX (with the emphasis on SICK!) by Andrew Marc Greene +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Andrew's Affiliations +% +% Copyright (C) 1990 by Andrew Marc Greene +% <amgreene@mit.edu> +% MIT Project Athena +% Student Information Processing Board +% All rights reserved. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% BaSiX's Beginnings +% +\def\flageol{\catcode13=13} +\def\endflageol{\catcode13=5} +\def\struncat{\catcode`\$=12} +\def\strcat{\catcode`\$=11} +\flageol\let\eol +\endflageol +\newif\ifresult +%\newcount\xa\newcount\xb +\def\iw{\immediate\write16} +\def\empty{} +\def\gobble#1{} +\def\spc{ } +\def\itstrue{tt} +\def\itsfalse{tf} +\def\isnull#1{\resultfalse +\expandafter\ifx\csname empty#1\endcsname\empty\resulttrue\fi} +\newcount\matha\newcount\mathb +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Character-string Calls +% +\newcount\strtmp +\def\ascii#1{\strtmp`#1} +\def\chr#1{\begingroup\uccode65=#1\uppercase{\gdef\tmp{A}}\endgroup} +\def\strlen#1{\strtmp-2% don't count " " \iw tokens + \expandafter\if\stringP #1\let\next\strIter\strIter #1\iw\fi} +\def\strIter#1{\ifx\iw#1\let\next\relax\else\advance\strtmp by 1\relax + \fi\next} +\def\Flen{\expandafter\strlen\expandafter{\Pa}\return{\number\strtmp}} +\strcat +\def\F$chr${\expandafter\chr\expandafter{\Pa}\return{\tmp}} +\struncat +% first char only: +% \def\Fasc{\expandafter\asc\expandafter{\Pa}\return{\number\strtmp}} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Debugging Definitions +% +\def\debug{\tracingmacros=2} +\def\diw#1{} +\def\Cdebug{\let\diw\iw\tracingmacros=2 \endeval} +\def\Cnodebug{\def\diw##1{}\endeval} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Expression Evaluation +% +\def\expression{\let\afterexpression\afterscan\math} +% +% (math is a misnomer and should -> expr) +% +\newcount\parens\newcount\mathParams +\def\math{\parens=0\mathParams96\mathInit\matheval} +\def\mathRecurse{\advance\parens by 1\relax\mathParams96\mathInit\matheval} +\def\mathInit{\begingroup + \let\mathAcc\empty + \let\mathOpRel\empty + \let\mathOpAdd\empty + \let\mathOpMul\empty + \let\mathlhRef\empty} +% +\def\matheval{\after\mathbranch\scan} +% +\def\mathbranch{\diw{EXPRESS:\expandafter\noexpand\word:} +\let\next\matherr +\ifx\empty\word\let\next\mathHardEnd\else % Expr. end? +\expandafter\if\numberP\word\let\next\mathLiteral\diw{@@}\fi % Number? +\expandafter\if\stringP\word\let\next\mathLiteral\fi % String literal? +\expandafter\if\identifierP\word\let\next\mathIdentifier\fi % Identifier? +\expandafter\if\stringvarP\word\let\next\mathIdentifier\fi % :-( +\expandafter\if\macroP\word\let\next\mathMacro\fi % Macro? +\ifx\word\Oleft\let\next\mathRecurse\fi % Open paren? +\ifx\word\Oright\let\next\mathEndRecurse\fi % Close paren? +\ifx\word\Ocomma\let\next\mathComma\fi % Comma? +% +% Operator? +% +\ifx\word\Oplus\let\next\mathOp\diw{!+}\fi +\ifx\word\Ominus\let\next\mathOp\diw{!-}\fi +\ifx\word\Otimes\let\next\mathOp\diw{!*}\fi +\ifx\word\Odiv\let\next\mathOp\diw{!/}\fi +\ifx\word\Olt\let\next\mathOp\diw{!<}\fi +\ifx\word\Oeq\let\next\mathOp\diw{!=}\fi +\ifx\word\Ogt\let\next\mathOp\diw{!>}\fi +% +\fi\next} +% +\def\Oleft{(}\def\Oright{)}\def\Ocomma{,} +\def\Oplus{+}\def\Ominus{-}\def\Otimes{*}\def\Odiv{/} +\def\Olt{<}\def\Oeq{=}\def\Ogt{>} +% +% There's got to be a better way to do the above.... +% +\def\mathLiteral{\diw{MLIT}\ifx\empty\mathAcc\diw{ACCUMUL:\word:} +\expandafter\def\expandafter\mathAcc\expandafter +{\expandafter\expandafter\expandafter\empty\word} +\else +\diw{ACC has :\mathAcc: and word is :\word:} +\errmessage{Syntax Error: Two values with no operator}\fi\matheval} +% +% Operator stuff: (Need to add string support / error checking) +% +\def\mathAdd{\advance\matha by \mathb} +\def\mathSub{\advance\matha by -\mathb} +\def\mathMul{\multiply\matha by \mathb} +\def\mathDiv{\divide\matha by \mathb} +\def\mathEQ{\ifnum\matha=\mathb\matha-1\else\matha0\fi} +\def\mathGT{\ifnum\matha>\mathb\matha-1\else\matha0\fi} +\def\mathLT{\ifnum\matha<\mathb\matha-1\else\matha0\fi} +% +\def\mathFlushRel{\mathFlushAdd\ifx\empty\mathOpRel\else + \matha=\mathlhRel\relax\mathb=\mathAcc\relax\mathOpRel + \edef\mathAcc{\number\matha}\let\mathOpRel\empty\fi} +% +\def\mathFlushAdd{\mathFlushMul\ifx\empty\mathOpAdd\else + \matha=\mathlhAdd\relax\mathb=\mathAcc\relax\mathOpAdd + \edef\mathAcc{\number\matha}\let\mathOpAdd\empty\fi} +% +\def\mathFlushMul{\mathFlushRef\ifx\empty\mathOpMul\else + \matha=\mathlhMul\relax\mathb=\mathAcc\relax\mathOpMul + \edef\mathAcc{\number\matha}\let\mathOpMul\empty\fi} +% +\def\mathFlushRef{\ifx\empty\mathlhRef\else + \mathParam + \mathlhRef\let\mathlhRef\empty\fi} +% +\def\mathOp{% +\if\word+ + \mathFlushAdd\let\mathlhAdd\mathAcc\let\mathOpAdd\mathAdd\fi +\if\word- + \mathFlushAdd\let\mathlhAdd\mathAcc\let\mathOpAdd\mathSub\fi +\if\word* + \mathFlushMul\let\mathlhMul\mathAcc\let\mathOpMul\mathMul\fi +\if\word/ + \mathFlushMul\let\mathlhMul\mathAcc\let\mathOpMul\mathDiv\fi +\if\word= + \mathFlushRel\let\mathlhRel\mathAcc\let\mathOpRel\mathEQ\fi +\if\word> + \mathFlushRel\let\mathlhRel\mathAcc\let\mathOpRel\mathGT\fi +\if\word< + \mathFlushRel\let\mathlhRel\mathAcc\let\mathOpRel\mathLT\fi +\let\mathAcc\empty +\matheval} +% +\def\mathIdentifier{% +\expandafter\ifx\csname C\word\endcsname\relax +\expandafter\ifx\csname F\word\endcsname\relax +\expandafter\ifx\csname V\word\endcsname\relax +\let\next\matherr\diw{LOSING:\word:} +\else\let\next\mathVariable\fi +\else\let\next\mathFunction\fi +\else\let\next\mathCommand\fi\next} +% +\def\mathVariable{\expandafter\edef\expandafter\word\expandafter +{\csname V\word\endcsname}\mathbranch} +\def\mathCommand{\expandafter\mathHardEnd\word} +\def\mathFunction{\expandafter\let\expandafter\mathlhRef +\csname F\word\endcsname\matheval} +% +\def\mathParam{\advance\mathParams by 1\relax\chr\mathParams + \diw{PARAM:\tmp:\mathAcc:} + \expandafter\edef\csname P\tmp\endcsname{\mathAcc}} +\def\mathComma{\mathEnd\mathParam\mathInit\matheval} +\def\mathEndRecurse{\mathEnd\advance\parens by -1\matheval} +\def\mathEnd{\diw{MATHEND: ACC=\mathAcc:}\mathFlushRel + \xdef\mathtemp{\mathAcc}\endgroup\edef\mathAcc{\mathtemp}} +\def\mathHardEnd{\ifnum\parens>0\errmessage{Insufficient closeparens.}\relax + \let\next\endeval\else\let\next\mathFinal\fi\next} +\def\mathFinal{\mathEnd\let\value\mathAcc\endexpression} +\def\matherr{\errmessage{Syntax error: Unknown symbol \word}} +\def\endexpression{\afterexpression} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Linked List +% +\def\gotofirstline{\edef\lpointer{\csname L0\endcsname}} +\def\foreachline#1{\ifnum\lpointer<99999\edef\word{\lpointer}#1% +\edef\lpointer{\csname L\word\endcsname}\foreachline{#1}\fi} +% +% gotopast{#1} where #1 is a line number, will set \lpointer to +% the least value such that L(lpointer)>#1 +% +\def\gotopast#1{\def\lpointer{0}\def\target{#1}\gotopastloop} +% +\def\gotopastloop{\edef\tmp{\csname L\lpointer\endcsname}% +\ifnum\tmp<\target% +\edef\lpointer{\csname L\lpointer\endcsname}% +\let\next=\gotopastloop\else\let\next=\relax\fi +\next} +% +\flageol\def\addLineToLinkedList#1#2 +{\def#1{#2}\diw{Just stored #2 in \noexpand #1}% +% now put it into linked list... +\expandafter\ifx\csname L\word\endcsname\relax% if it isn't already there, +\gotopast{\word}% \def\lpointer{what-should-point-to-word} +\expandafter\edef\csname L\word\endcsname{\csname L\lpointer\endcsname}% +\expandafter\edef\csname L\lpointer\endcsname{\word}% +\fi\endeval +}\endflageol +\expandafter\def\csname L0\endcsname{99999} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Program Parser +% +\def\evalline{%\iw{EVALLINE :\word:}% +\csname C\word\endcsname} %error-checking? :-) +\def\evalerror{\errmessage{Unkonwn command. Sorry.}} +% +% \mandatory takes one argument and checks to see if the next +% non-whitespace token matches it. If not, an error is generated. +% +\def\mandatory#1{\def\tmp{#1}\mandatest} +\def\mandatest#1{\def\tmpp{#1}\ifx\tmp\tmpp\let\next\afterscan\else +\let\next\manderror\fi\next} +\def\manderror{\errmessage{\tmpp\spc read when \tmp\spc expected.}% +\afterscan} +% +% \parseline gets the first WORD of the next line. If it's a line +% number, \scanandstoreline is called; otherwise the line is executed. +% +\def\parseline{\after\firsttest\scan} +\def\firsttest{\expandafter\if\numberP\word +\let\next\grabandstoreline\else\let\next\evalline\fi\next} +\def\grabandstoreline{\diw{Grabbing line \word.}% +\expandafter\addLineToLinkedList\csname/\word\endcsname} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Syntactic Scanner +% +% The \scan routine reads the next WORD and then calls \afterscan. +% +% As syntactic sugar, one can write \after\foo to set \afterscan to +% \foo. +% +% Here are the rules governing WORD. Initial whitespace is +% discarded. The word is the next single character, unless that +% character is one of the following: +% +% A-Z or a-z: [A-Z,a-z][A-Z,a-z,0-9]*\$? +% 0-9: [0-9]+ +% ": "[^"]*" +% <,=,>: [<=>][<=>]? (one or two; not the same if two) +% +% Note that the string literal ignores spaces but may be abnormally +% terminated by an end-of-line. (I wasn't sure how to express that +% as a regexp). +% +% +\newif\ifscan % shall we continue scanning? +% +\def\scan{\def\word{}\futurelet\q\scanFirst} +% +\def\scanFirst{% Checks the first character to determine type. +\let\next\scanIter +\expandafter\if\spc\noexpand\q % Space -- ignore it + \let\next\scanSpace\else +\if\eol\noexpand\q % End of line -- no word here + \let\next\scanEnd\else +\ifcat A\noexpand\q % Then we have an identifier + \let\scanTest\scanIdentifier\else +\expandafter\if\digit\q + \let\scanTest\scanNumericConstant\else +\if"\noexpand\q + \let\scanTest\scanStringConstant\else +\expandafter\if\relationP\q + \let\scanTest\scanRelation +\else + \let\scanTest\scanfalse +\fi\fi\fi\fi\fi\fi\next} +% +\def\scanIter#1{\expandafter\def\expandafter\word\expandafter{\word #1} + \futurelet\q\scanContinueP} +\def\scanContinueP{\scanTest\ifscan\let\next\scanIter + \else\let\next\scanEnd\fi\next} +% +\def\scanSpace#1{\scan}% If the first char is a space, gobble it and try again. +\def\scanIdentifier{\ifcat A\noexpand\q\scantrue\else +\expandafter\if\digit\q\scantrue +\else\if$\noexpand\q\scantrue + \expandafter\def\expandafter\word\expandafter{\expandafter$\word} + \let\scanTest\scanfalse\else +\scanfalse\fi\fi\fi} +\def\scanEndString{\scanfalse} +\def\scanNumericConstant{\expandafter\if\digit\q\scantrue\else\scanfalse\fi} +\def\scanStringConstant{\scantrue\if"\q\let\scanTest\scanfalse\fi} +\def\scanRelation{\if<\q\scantrue\else\if>\q\scantrue\else\if=\q\scantrue +\else\scanfalse\fi\fi\fi} +% +\def\scanEnd#1{\relax\diw{SCANNED:\word:} +\afterscan #1}% dumps trailing spaces. +\def\after{\let\afterscan}% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Type Tests (Predicates for type determination) +% +\def\relationP#1{tf} % for now, only single-char relations +\def\identifierP#1{\expandafter\identifierTest #1\\} +\def\identifierTest#1#2\\{\ifcat A#1\itstrue\else\itsfalse\fi} +\def\stringvarP#1{\expandafter\stringvarTest #1\\} +\def\stringvarTest#1#2\\{\if$#1\itstrue\else\itsfalse\fi} +\def\stringP#1{\expandafter\stringTest #1\\} +\def\stringTest#1#2\\{\if #1"\itstrue\else\itsfalse\fi} +\def\numberP#1{\expandafter\numberTest #1\\} +\def\numberTest#1#2\\{\expandafter\if\digit #1\itstrue\else\itsfalse\fi} +\def\macroP#1{\expandafter\macroTest #1\\} +\def\macroTest#1#2\\{\expandafter\ifx #1\relax\itstrue\else\itsfalse\fi} +% +% \digit tests its single-token argument and returns tt if true, +% tf otherwise. +% +% +\def\digit#1{% +\if0\noexpand#1\itstrue\else +\if1\noexpand#1\itstrue\else +\if2\noexpand#1\itstrue\else +\if3\noexpand#1\itstrue\else +\if4\noexpand#1\itstrue\else +\if5\noexpand#1\itstrue\else +\if6\noexpand#1\itstrue\else +\if7\noexpand#1\itstrue\else +\if8\noexpand#1\itstrue\else +\if9\noexpand#1\itstrue\else\itsfalse +\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi +% 9 8 7 6 5 4 3 2 1 0 +} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% User Utilities. These are the commands that are called by the +% user. We could really use a better section name. :-) +% +% List (one line or all lines, for now) +% +\def\Clist{\after\listmain\scan} +\def\listmain{\isnull{\word}\ifresult\let\next\listalllines +\else\let\next\listoneline\fi\next} +\def\listline{\iw{\word\spc\csname/\word\endcsname}} +\def\listalllines{\gotofirstline\foreachline{\listline}\endeval} +\def\listoneline{\listline\endeval} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Different degrees of ``stop execution'' +% +\def\Csystem{\end} % exits to the system +\def\Cexit{}% \endflageol} % exits to TeX +\flageol% +\def\Cstop#1 +{\iw{Stopped in \lineno.}\cleanstop}% +\def\cleanstop{\diw{CLEANSTOP}\let\endeval\enduserline\endeval +}\endflageol +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% The command ``rem'' introduces a remark +% +\def\Crem{\endeval}% +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% The ``let'' command allows variable assignments +% +\def\Clet{\after\letgetequals\scan} +\def\letgetequals{\after\letgetvalue\mandatory{=}} +\def\letgetvalue{\after\letdoit\expression} +\def\letdoit{\expandafter\edef\csname V\word\endcsname{\value}% +\endeval} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% The ``print'' command takes a [list of] expression[s] and displays +% it [them]. +% +\def\Cprint{\after\printit\expression} +\def\printit{\iw{\value}\endeval} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% The ``if'' command takes an expression, the word ``then,'' and +% another command. If the expression is non-zero, the command is +% executed; otherwise it is ignored. +% +\def\Cif{\after\getift\expression} +\def\Cthen{\errmessage{Syntax error: THEN without IF}} +\def\getift{\after\getifh\mandatory t} +\def\getifh{\after\getife\mandatory h} +\def\getife{\after\getifn\mandatory e} +\def\getifn{\after\consequent\mandatory n} +\def\consequent{\ifnum\value=0\let\next=\endeval\else\let\next=\evalconsq\fi +\next} +\def\evalconsq{\after\evalline\scan} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Functions +% +% Functions may read the counter \mathParams to find out the number +% of the top parameter. Parameters are in Pa Pb Pc etc. +% +\def\return{\expandafter\def\expandafter\mathAcc\expandafter} +% +\def\Finc{\matha=\Pa \advance\matha by 1 +\return{\number\matha}} +% +\def\Fmin{\ifnum\Pa<\Pb\return{\Pa}\else\return{\Pb}\fi} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Program execution control +% +\def\Crun{\let\endeval\endincrline\def\lineno{0}\endeval} +\def\Cgoto{\let\endeval\endgotoline\after\gotomain\scan} +\def\gotomain{\edef\lineno{\word}\endeval} +% +\flageol% +\def\execline{%\message{Executing line \lineno...}% +\edef\theline{\csname/\lineno\endcsname}% +%\message{THE LINE\theline}% +\let\endeval\endincrline\after\evalline\expandafter\scan\theline +}\endflageol +% +% Different varieties of what to do at the end of a command: +% +% get new line from user (enduserline) +% get next line in order (endincrline) +% get line in \lineno (endgotoline) +% keep parsing current line (endcolonline tbi) +% +\flageol% +\def\endincrline#1 +{\diw{ENDINCRLINE}\edef\lineno{\csname L\lineno\endcsname}\execnextline} +% +\def\endgotoline#1 +{\diw{ENDGOTOLINE}\let\endeval\execincrline\execnextline}% +% +\def\execnextline{\diw{Ready to execute line \lineno...}% +\ifnum\lineno<99999\let\next\execline\else\let\next\cleanstop\fi\next}% +% +\def\enduserline #1 +{\diw{ENDUSERLINE}\parseline}\endflageol +% +\let\endeval\enduserline +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Start your engines! +% +\iw{This is BaSiX, v0.3, emphasis on the SICK! by amgreene@mit.edu} +\flageol +\catcode32=12 +\endeval |