MathConstructorsImpl.mesa
Carl Waldspurger, August 30, 1986 7:12:37 pm PDT
DIRECTORY
MathExpr,
MathRules,
MathDB,
MathTypes,
MathBox,
ImagerFont,
ImagerTransformation,
Imager,
Rope USING [ROPE, Fetch, Length, Substr, Equal, FromChar],
Vector USING [VEC],
Convert USING [RopeFromReal, AtomFromRope, RopeFromAtom],
MathConstructors;
MathConstructorsImpl: CEDAR PROGRAM
IMPORTS MathBox, MathRules, ImagerFont, Imager, ImagerTransformation, MathExpr,
MathDB, Convert, Rope
EXPORTS MathConstructors ~
BEGIN
Type Abbreviations
EXPR: TYPE ~ MathExpr.EXPR;
BOX: TYPE ~ MathBox.BOX;
ROPE: TYPE ~ Rope.ROPE;
VEC: TYPE ~ Vector.VEC;
AtomBoxProc: TYPE ~ MathRules.AtomBoxProc;
AtomPaintProc: TYPE ~ MathRules.AtomPaintProc;
AtomToASRopeProc: TYPE ~ MathRules.AtomToASRopeProc;
CompoundBoxProc: TYPE ~ MathRules.CompoundBoxProc;
CompositionProc: TYPE ~ MathRules.CompositionProc;
Alignment2D: TYPE ~ MathRules.Alignment2D;
Offset: TYPE ~ MathRules.Offset;
Size: TYPE ~ MathRules.Size;
Argument: TYPE ~ MathExpr.Argument;
Symbol: TYPE ~ MathExpr.Symbol;
AtomClass: TYPE ~ MathExpr.AtomClass;
AtomFlavor: TYPE ~ MathExpr.AtomFlavor;
CompoundClass: TYPE ~ MathExpr.CompoundClass;
FormatClass: TYPE ~ MathTypes.FormatClass;
MatrixClass: TYPE ~ MathExpr.MatrixClass;
Style: TYPE ~ MathTypes.Style;
Procedure Abbreviations
MakeArgument: PROC[name: ATOM, aliases: LIST OF ATOM, size: Size] RETURNS[Argument] ~ MathExpr.MakeArgument;
MakeSymbol: PROC[name: ATOM, aliases: LIST OF ATOM, size: Size, value: EXPR] RETURNS[Symbol] ~ MathExpr.MakeSymbol;
MakeAtomClass: PROC[name: ATOM, formatClass: FormatClass, flavor: AtomFlavor, style: Style, boxRule: AtomBoxProc, paintRule: AtomPaintProc, cvtASRule: AtomToASRopeProc ← NIL] RETURNS[AtomClass] ~ MathExpr.MakeAtomClass;
MakeCompoundClass: PROC[name: ATOM, formatClass: FormatClass, description: ROPE, args: LIST OF Argument, syms: LIST OF Symbol, boxRule: CompoundBoxProc, compBox: CompositionProc, cvtAS: ROPENIL] RETURNS[CompoundClass] ~ MathExpr.MakeCompoundClass;
Constants
smallGap: REAL = 0.05;
medGap: REAL = 0.10;
bigGap: REAL = 0.25;
Common Rule Procs
Common AtomToASRope Procs
GreekVarToASRope: AtomToASRopeProc ~ {
IF value.Length[] < 1 THEN RETURN["unknown"]
ELSE RETURN[CharToGreekName[value.Fetch[0]]];
};
PlaceHolderToASRope: AtomToASRopeProc ~ {
RETURN["?"];
};
InfinityToASRope: AtomToASRopeProc ~ {
RETURN["infinity"];
};
Common Paint Procs
PaintChar: AtomPaintProc ~ {
effects: Paints value onto context in absBox
check type
IF (absBox.Type[] # absolute) THEN ERROR wrongBoxType
ELSE {
font: ImagerFont.Font ← ImagerFont.Find[style.font];
extents: ImagerFont.Extents ← ImagerFont.RopeBoundingBox[font, value];
xFactor: REAL ← absBox.Width[] / (extents.leftExtent + extents.rightExtent);
yFactor: REAL ← absBox.Height[] / (extents.descent + extents.ascent);
Imager.SetXY[context, absBox.Offset[]];
Imager.SetFont[context,
ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]];
Imager.ShowRope[context, value];
};
};
PaintOverlay: AtomPaintProc ~ {
effects: Paints value as a sequence of centered superimposed characters.
This is useful for things like negated symbols (/ slashed through)...
check types
IF (absBox.Type[] # absolute) THEN ERROR wrongBoxType
ELSE {
font: ImagerFont.Font ← ImagerFont.Find[style.font];
extents: ImagerFont.Extents ← OverlayBox[value, style];
xFactor: REAL ← absBox.Width[] / (extents.rightExtent + extents.leftExtent);
yFactor: REAL ← absBox.Height[] / (extents.ascent + extents.descent);
scale Font
font ← ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]];
paint chars, one by one, on ope of each other
FOR i:INT IN [0..value.Length[]-1] DO
char: ROPE ← value.Substr[i, 1];
box: ImagerFont.Extents ← ImagerFont.RopeBoundingBox[font, char];
position: VEC ← [MathRules.AlignHorizontal[box, [center], absBox, [center]],
MathRules.AlignVertical[box, [center], absBox, [center]]];
Imager.SetXY[context, position];
Imager.SetFont[context, font];
Imager.ShowRope[context, char];
ENDLOOP;
};
};
PaintRope: AtomPaintProc ~ {
effects: Paints value onto context in absBox
check types
IF (absBox.Type[] # absolute) THEN ERROR wrongBoxType
ELSE {
font: ImagerFont.Font ← ImagerFont.Find[style.font];
extents: ImagerFont.Extents ← ImagerFont.RopeBoundingBox[font, value];
xFactor: REAL ← absBox.Width[] / (extents.rightExtent + extents.leftExtent);
yFactor: REAL ← absBox.Height[] / (extents.ascent + extents.descent);
Imager.SetXY[context, absBox.Offset[]];
Imager.SetFont[context,
ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]];
Imager.ShowRope[context, value];
};
};
PaintLine: AtomPaintProc ~ {
effects: Paints a line onto context filling absBox
caveats: Ignores value & style
r: Imager.Rectangle ← [x: absBox.Offset[].x + absBox.Extents[].leftExtent, y: absBox.Offset[].y + absBox.Extents[].descent, w: absBox.Width[], h: absBox.Height[]];
Imager.MaskRectangle[context, r];
};
PaintSpace: AtomPaintProc ~ {
effects: none
RETURN;
};
Common Box Procs & AtomToRopeProcs
LineBox: AtomBoxProc ~ {
effects: Returns a bounding box for a line
Note that this is always a dummy value
don't really need any data from value; always returns protoypical line size
RETURN[[leftExtent: 0.0, rightExtent: 1.0, descent: 0.0, ascent: 0.03]];
};
CharBox: AtomBoxProc ~ {
effects: Returns a bounding box for value
font: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find[style.font], style.scale];
RETURN[ImagerFont.RopeBoundingBox[font, value]];
};
OverlayBox: AtomBoxProc ~ {
effects: Returns a bounding box for value as a sequence of overlayed chars
font: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find[style.font], style.scale];
farLeft, farRight, farUp, farDown: REAL ← 0.0; -- extreme edges of overlayed extents
FOR i:INT IN [0..value.Length[]-1] DO
box: ImagerFont.Extents ← ImagerFont.RopeBoundingBox[font, value.Substr[i, 1]];
farLeft ← MAX[farLeft, box.leftExtent];
farRight ← MAX[farRight, box.rightExtent];
farUp ← MAX[farUp, box.ascent];
farDown ← MAX[farDown, box.descent];
ENDLOOP;
RETURN[[leftExtent: farLeft, rightExtent: farRight, descent: farDown, ascent: farUp]];
};
RopeBox: AtomBoxProc ~ {
effects: Returns a bounding box for value
font: ImagerFont.Font ← ImagerFont.Scale[ImagerFont.Find[style.font], style.scale];
RETURN[ImagerFont.RopeBoundingBox[font, value]];
};
SpaceBox: AtomBoxProc ~ {
effects: Returns a bounding box for value
size: ATOM ← Convert.AtomFromRope[value];
RETURN[
SELECT size FROM
$null => [leftExtent: 0.0, rightExtent: 0.001, descent: 0.0, ascent: 0.001],
$thin => [leftExtent: 0.0, rightExtent: 0.05, ascent: 0.05, descent: 0.0],
$medium => [leftExtent: 0.0, rightExtent: 0.12, ascent: 0.12, descent: 0.0],
$thick => [leftExtent: 0.0, rightExtent: 0.25, ascent: 0.25, descent: 0.0],
$veryThick => [leftExtent: 0.0, rightExtent: 0.4, ascent: 0.4, descent: 0.0],
$matrix => [leftExtent: 0.0, rightExtent: 0.9, ascent: 0.65, descent: 0.0],
$limit => [leftExtent: 0.0, rightExtent: 0.25, ascent: 0.12, descent: 0.0],
$product => [leftExtent: 0.0, rightExtent: 0.001, ascent: 0.21, descent: -0.19]
default to $thin
ENDCASE => [leftExtent: 0.0, rightExtent: 0.05, ascent: 0.05, descent: 0.0]
];
};
Common Compound Procs
Box Rules
FixedSizeBoxRule: CompoundBoxProc ~ {
effects: Returns unaltered boxes (i.e. no resizing takes place)
RETURN[boxes];
};
FractionBoxRule: CompoundBoxProc ~ {
effects: Sizes boxes for expr of form ($fractionBar $numerator $denominator)
should ENABLE noSuchBox
fbarBox: BOX ← MathBox.GetBox[$fractionBar, boxes];
numBox: BOX ← MathBox.GetBox[$numerator, boxes];
denomBox: BOX ← MathBox.GetBox[$denominator, boxes];
topSpaceBox: BOX ← MathBox.GetBox[$topSpace, boxes];
bottomSpaceBox: BOX ← MathBox.GetBox[$bottomSpace, boxes];
fraction bar must be as wide as the wider of numerator, denominator
scaleX: REAL ← 1.1 * MAX[numBox.Width[], denomBox.Width[]] / fbarBox.Width[];
adjust fbarBox extents
fbarBox ← MathBox.Scale[fbarBox, [scaleX, 1.0]];
RETURN[LIST[fbarBox, numBox, denomBox, topSpaceBox, bottomSpaceBox]];
};
ParenBoxRule: CompoundBoxProc ~ {
effects: Sizes boxes for expr of form ($paren $a)
leftParenBox: BOX ← MathBox.GetBox[$leftParen, boxes];
rightParenBox: BOX ← MathBox.GetBox[$rightParen, boxes];
aBox: BOX ← MathBox.GetBox[$a, boxes];
right and left parentheses must be as tall as expression "a"
scaleFactor: REALMAX[0.25, 1.1 * aBox.Height[] / leftParenBox.Height[]];
leftParenBox ← MathBox.Scale[leftParenBox, [scaleFactor, scaleFactor]];
rightParenBox ← MathBox.Scale[rightParenBox, [scaleFactor, scaleFactor]];
RETURN[LIST[aBox, leftParenBox, rightParenBox]];
};
NRadicalBoxRule: CompoundBoxProc ~ {
effects: Sizes boxes for expr of form ($radRoot $radLine $n $radicand)
should ENABLE noSuchBox
radRootBox: BOX ← MathBox.GetBox[$radRoot, boxes];
radLineBox: BOX ← MathBox.GetBox[$radLine, boxes];
nBox: BOX ← MathBox.GetBox[$n, boxes];
spaceBox: BOX ← MathBox.GetBox[$space, boxes];
radicandBox: BOX ← MathBox.GetBox[$radicand, boxes];
line must be exactly as long as radicand,
root symbol must be as tall as radicand + 2*space
rootScale: REAL ← ((2 * spaceBox.Height[]) + radicandBox.Height[]) / radRootBox.Height[];
lineScale: VEC ← [radicandBox.Width[]/radLineBox.Width[], 1.0];
adjust symbol extents
radRootBox ← MathBox.Scale[radRootBox, [rootScale, rootScale]];
radLineBox ← MathBox.Scale[radLineBox, lineScale];
RETURN[LIST[radRootBox, radLineBox, nBox, radicandBox, spaceBox]];
};
RadicalBoxRule: CompoundBoxProc ~ {
effects: Sizes boxes for expr of form ($radRoot $radLine $radicand)
should ENABLE noSuchBox
radRootBox: BOX ← MathBox.GetBox[$radRoot, boxes];
radLineBox: BOX ← MathBox.GetBox[$radLine, boxes];
spaceBox: BOX ← MathBox.GetBox[$space, boxes];
radicandBox: BOX ← MathBox.GetBox[$radicand, boxes];
line must be exactly as long as radicand,
root symbol must be as tall as radicand + 2*space
rootScale: REAL ← ((2 * spaceBox.Height[]) + radicandBox.Height[]) / radRootBox.Height[];
lineScale: VEC ← [radicandBox.Width[]/radLineBox.Width[], 1.0];
adjust symbol extents
radRootBox ← MathBox.Scale[radRootBox, [rootScale, rootScale]];
radLineBox ← MathBox.Scale[radLineBox, lineScale];
RETURN[LIST[radRootBox, radLineBox, radicandBox, spaceBox]];
};
FunctionBoxRule: CompoundBoxProc ~ {
effects: Sizes boxes for expr of form ($f $space $args $leftParen $rightParen)
should ENABLE noSuchBox
lParenBox: BOX ← MathBox.GetBox[$leftParen, boxes];
rParenBox: BOX ← MathBox.GetBox[$rightParen, boxes];
spaceBox: BOX ← MathBox.GetBox[$space, boxes];
fBox: BOX ← MathBox.GetBox[$f, boxes];
argsBox: BOX ← MathBox.GetBox[$args, boxes];
parens must be as big as args
right and left parentheses must be as tall as expression "a"
scaleFactor: REALMAX[1.0, 1.1 * argsBox.Height[] / lParenBox.Height[]];
lParenBox ← MathBox.Scale[lParenBox, [scaleFactor, scaleFactor]];
rParenBox ← MathBox.Scale[rParenBox, [scaleFactor, scaleFactor]];
RETURN[LIST[fBox, spaceBox, lParenBox, rParenBox, argsBox]];
};
Composition Rules
PowCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($exponent $base)
tempBox: BOX;
tempBoxes: LIST OF BOX;
vertOffsetExponent, vertOffsetBase, horizOffsetBase: Offset;
alignments: LIST OF Alignment2D ← NIL;
baseBox: BOX ← MathBox.GetBox[$base, boxes];
exponentBox: BOX ← MathBox.GetBox[$exponent, boxes];
hintBox: BOX ← baseBox.SuperscriptHint[]; -- hint about where to place subscript w/i base
IF hintBox # NIL THEN {
hint, so align exponent with base via hintBox
horizOffsetBase ← [origin, hintBox.Offset[].x + hintBox.Extents[].rightExtent];
IF (hintBox.Height[] * baseBox.Height[]) > exponentBox.Height[] THEN {
vertOffsetExponent ← [bottom, 0.2];
top of hint box inside base box
vertOffsetBase ← [origin, hintBox.Offset[].y + hintBox.Extents[].ascent];
}
ELSE {
vertOffsetExponent ← [bottom];
0.8 way up on hint box
vertOffsetBase ← [origin, 0.8 * (hintBox.Offset[].y + hintBox.Extents[].ascent)];
};
}
ELSE {
no hint, so align exponent directly with base
horizOffsetBase ← [right];
IF baseBox.Height[] > exponentBox.Height[] THEN {
vertOffsetExponent ← [bottom, 0.2];
vertOffsetBase ← [top];
}
ELSE {
vertOffsetExponent ← [bottom];
vertOffsetBase ← [top, -0.2];
};
};
alignments ← LIST[
[$exponent,
[$base, [left], horizOffsetBase],
[$base, vertOffsetExponent, vertOffsetBase]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$base, [origin]], [$base, [origin]]];
RETURN[tempBox, tempBoxes];
};
SubscriptCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($base $subscript)
tempBox: BOX;
tempBoxes: LIST OF BOX;
vertOffsetSubscript, vertOffsetBase: Offset;
alignments: LIST OF Alignment2D ← NIL;
IF MathBox.GetBox[$base, boxes].Height[] >
MathBox.GetBox[$subscript, boxes].Height[] THEN {
vertOffsetSubscript ← [top, -0.2];
vertOffsetBase ← [bottom];
}
ELSE {
vertOffsetSubscript ← [top];
vertOffsetBase ← [bottom, +0.2];
};
alignments ← LIST[
[$subscript,
[$base, [left], [right]],
[$base, vertOffsetSubscript, vertOffsetBase]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$base, [origin]], [$base, [origin]]];
make hint to place superscript over base instead of entire expression
tempBox ← tempBox.ChangeSuperHint[MathBox.GetBox[$base, tempBoxes]];
RETURN[tempBox, tempBoxes];
};
FractionCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($fractionBar $numerator $denominator)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$topSpace,
[$fractionBar, [center], [center]],
[$fractionBar, [bottom], [top]]],
[$bottomSpace,
[$fractionBar, [center], [center]],
[$fractionBar, [top], [bottom]]],
[$numerator,
[$fractionBar, [center], [center]],
[$topSpace, [bottom], [top]]],
[$denominator,
[$fractionBar, [center], [center]],
[$bottomSpace, [top], [bottom]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$fractionBar, [origin]],
[$fractionBar, [origin]]];
RETURN[tempBox, tempBoxes];
};
ListCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($comma $car $cdr) with symbol $space.
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$car,
[$comma, [right], [left]],
[$comma, [origin], [origin]]],
[$space,
[$comma, [left], [right]],
[$comma, [origin], [origin]]],
[$cdr,
[$space, [left], [right]],
[$comma, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$car, [origin]], [$comma, [origin]]];
RETURN[tempBox, tempBoxes];
};
FunctionCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($f $space $args $leftParen $rightParen)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$leftParen,
[$args, [right], [left]],
[$args, [center], [center]]],
[$rightParen,
[$args, [left], [right]],
[$args, [center], [center]]],
[$space,
[$leftParen, [right], [left]],
[$args, [origin], [origin]]],
[$f,
[$space, [right], [left]],
[$args, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$f, [origin]], [$f, [origin]]];
RETURN[tempBox, tempBoxes];
};
LimitCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($lim $approaches $of $space)
tempBox: BOX;
tempBoxes: LIST OF BOX;
limBox: BOX ← MathBox.GetBox[$lim, boxes];
approachesBox: BOX ← MathBox.GetBox[$approaches, boxes];
alignments: LIST OF Alignment2D;
IF approachesBox.Width[] > limBox.Width[] THEN {
alignments ← LIST[
[$space,
[$of, [right], [left]],
[$of, [center], [center]]],
[$approaches,
[$space, [right], [left]],
[$space, [top], [bottom]]],
[$lim,
[$approaches, [center], [center]],
[$space, [bottom], [top]]]];
}
ELSE {
alignments ← LIST[
[$space,
[$of, [right], [left]],
[$of, [center], [center]]],
[$lim,
[$space, [right], [left]],
[$space, [bottom], [top]]],
[$approaches,
[$lim, [center], [center]],
[$space, [top], [bottom]]]];
};
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$approaches, [origin]], [$of, [origin]]];
RETURN[tempBox, tempBoxes];
};
SummationCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($summation $lowerbound $upperbound
$summand)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← NIL;
vertSigmaOffset, vertSummandOffset: Offset;
SELECT MathBox.GetBox[$summand, boxes].FormatClass[] FROM
over => {
vertSigmaOffset ← [center];
vertSummandOffset ← [center];
};
ENDCASE => {
vertSummandOffset ← [origin];
vertSigmaOffset ← [center, -0.2];
};
alignments ← LIST[
[$lowerbound,
[$sigma, [center], [center]],
[$sigma, [top], [bottom, -smallGap]]],
[$upperbound,
[$sigma, [center], [center]],
[$sigma, [bottom], [top, +smallGap]]],
[$summand,
[$sigma, [left], [right, medGap]],
[$sigma, vertSummandOffset, vertSigmaOffset]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$sigma, [origin]], [$sigma, [center, -0.2]]];
RETURN[tempBox, tempBoxes];
};
NRadicalCompRule: CompositionProc ~ {
effects: Compose layout for expr of form ($radRoot $radLine $n $radicand)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$radRoot,
[$radicand, [right], [left]],
[$radicand, [center], [center]]],
[$space,
[$radicand, [center], [center]],
[$radicand, [bottom], [top]]],
[$radLine,
[$radRoot, [left], [right]],
[$radRoot, [top], [top]]],
[$n,
[$radRoot, [right], [left, bigGap]],
[$radRoot, [bottom], [center, +smallGap]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$n, [origin]], [$radicand, [origin]]];
RETURN[tempBox, tempBoxes];
};
RadicalCompRule: CompositionProc ~ {
effects: Compose layout for expr of form ($radRoot $radLine $radicand)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$radRoot,
[$radicand, [right], [left]],
[$radicand, [center], [center]]],
[$space,
[$radicand, [center], [center]],
[$radicand, [bottom], [top]]],
[$radLine,
[$radRoot, [left], [right]],
[$radRoot, [top], [top]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$radicand, [origin]],
[$radicand, [origin]]];
RETURN[tempBox, tempBoxes];
};
IntegrationCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($integral $lowerlimit
$upperlimit $integrand $dx $wrt)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← NIL;
vertIntegralOffset, vertIntegrandOffset: Offset;
SELECT MathBox.GetBox[$integrand, boxes].FormatClass[] FROM
over => {
vertIntegralOffset ← [center];
vertIntegrandOffset ← [center];
};
ENDCASE => {
vertIntegralOffset ← [center, -0.2];
vertIntegrandOffset ← [origin];
};
alignments ← LIST[
[$lowerlimit,
[$integral, [right], [left, +bigGap]],
[$integral, [top], [bottom, -smallGap]]],
[$upperlimit,
[$integral, [right], [right]],
[$integral, [bottom], [top, +smallGap]]],
[$integrand,
[$integral, [left], [right]],
[$integral, vertIntegrandOffset, vertIntegralOffset]],
[$space,
[$integrand, [left], [right]],
[$integrand, [origin], [origin]]],
[$dx,
[$space, [left], [right]],
[$space, [origin], [origin]]],
[$wrt,
[$dx, [left], [right]],
[$dx, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$lowerlimit, [origin]], [$integral, [center, -0.2]]];
RETURN[tempBox, tempBoxes];
};
IndefiniteIntCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($integral $integrand $dx $wrt)
tempBox: BOX;
tempBoxes: LIST OF BOX;
vertIntegralOffset, vertIntegrandOffset: Offset;
alignments: LIST OF Alignment2D ← NIL;
SELECT MathBox.GetBox[$integrand, boxes].FormatClass[] FROM
over => {
vertIntegralOffset ← [center];
vertIntegrandOffset ← [center];
};
ENDCASE => {
vertIntegralOffset ← [center, -0.2];
vertIntegrandOffset ← [origin];
};
alignments LIST[
[$integrand,
[$integral, [left], [right]],
[$integral, vertIntegrandOffset, vertIntegralOffset]],
[$space,
[$integrand, [left], [right]],
[$integrand, [origin], [origin]]],
[$dx,
[$space, [left], [right,]],
[$space, [origin], [origin]]],
[$wrt,
[$dx, [left], [right]],
[$dx, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$integral, [origin]],
[$integral, [center, -0.2]]];
RETURN[tempBox, tempBoxes];
};
UnaryOpCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($aliasUnaryOp $aliasA).
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$aliasSpace,
[$aliasUnaryOp, [left], [right]],
[$aliasUnaryOp, [origin], [origin]]],
[$aliasA,
[$aliasSpace, [left], [right]],
[$aliasSpace, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$aliasUnaryOp, [origin]],
[$aliasUnaryOp, [origin]]];
RETURN[tempBox, tempBoxes];
};
BinaryOpCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($aliasBinOp $aliasA $aliasB) with
symbols $aliasLeftSpace & $aliasRightSpace.
tempBox: BOX;
tempBoxes: LIST OF BOX;
leftVertOffsetA, leftVertOffsetOp, rightVertOffsetB, rightVertOffsetOp: Offset;
alignments: LIST OF Alignment2D;
set vertical offset depending on format classes of A & B arguments
SELECT MathBox.GetBox[$aliasA, boxes].FormatClass[] FROM
over => {
leftVertOffsetA ← [origin];
leftVertOffsetOp ← [center];
};
matrix => {
leftVertOffsetA ← [center];
leftVertOffsetOp ← [center];
};
ENDCASE => {
leftVertOffsetA ← [origin];
leftVertOffsetOp ← [origin];
};
SELECT MathBox.GetBox[$aliasB, boxes].FormatClass[] FROM
over => {
rightVertOffsetB ← [origin];
rightVertOffsetOp ← [center];
};
matrix => {
rightVertOffsetB ← [center];
rightVertOffsetOp ← [center];
};
ENDCASE => {
rightVertOffsetB ← [origin];
rightVertOffsetOp ← [origin];
};
alignments ← LIST[
[$aliasLeftSpace,
[$aliasBinOp, [right], [left]],
[$aliasBinOp, [origin], [origin]]],
[$aliasA,
[$aliasLeftSpace, [right], [left]],
[$aliasBinOp, leftVertOffsetA, leftVertOffsetOp]],
[$aliasRightSpace,
[$aliasBinOp, [left], [right]],
[$aliasBinOp, [origin], [origin]]],
[$aliasB,
[$aliasRightSpace, [left], [right]],
[$aliasBinOp, rightVertOffsetB, rightVertOffsetOp]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$aliasA, [origin]], [$aliasBinOp, [origin]]];
RETURN[tempBox, tempBoxes];
};
RelationCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($aliasRelation $aliasLHS $aliasRHS) with
symbols $aliasLeftSpace & $aliasRightSpace.
tempBox: BOX;
tempBoxes: LIST OF BOX;
leftVertOffsetLHS, leftVertOffsetRel, rightVertOffsetRHS, rightVertOffsetRel: Offset;
alignments: LIST OF Alignment2D;
set vertical offset depending on format classes of lhs & rhs arguments
SELECT MathBox.GetBox[$aliasLHS, boxes].FormatClass[] FROM
over => {
leftVertOffsetLHS ← [origin];
leftVertOffsetRel ← [center];
};
matrix => {
leftVertOffsetLHS ← [center];
leftVertOffsetRel ← [center];
};
ENDCASE => {
leftVertOffsetLHS ← [origin];
leftVertOffsetRel ← [origin];
};
SELECT MathBox.GetBox[$aliasRHS, boxes].FormatClass[] FROM
over => {
rightVertOffsetRHS ← [origin];
rightVertOffsetRel ← [center];
};
matrix => {
rightVertOffsetRHS ← [center];
rightVertOffsetRel ← [center];
};
ENDCASE => {
rightVertOffsetRHS ← [origin];
rightVertOffsetRel ← [origin];
};
alignments ← LIST[
[$aliasLeftSpace,
[$aliasRelation, [right], [left]],
[$aliasRelation, [origin], [origin]]],
[$aliasLHS,
[$aliasLeftSpace, [right], [left]],
[$aliasRelation, leftVertOffsetLHS, leftVertOffsetRel]],
[$aliasRightSpace,
[$aliasRelation, [left], [right]],
[$aliasRelation, [origin], [origin]]],
[$aliasRHS,
[$aliasRightSpace, [left], [right]],
[$aliasRelation, rightVertOffsetRHS, rightVertOffsetRel]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$aliasLHS, [origin]],
[$aliasRelation, [origin]]];
RETURN[tempBox, tempBoxes];
};
ComplexCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($complex $a $b)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ←
LIST[[$a, [$plus, [right], [left, -smallGap]],
[$plus, [origin], [origin]]],
[$b, [$plus, [left], [right, smallGap]],
[$plus, [origin], [origin]]],
[$i, [$b, [left], [right, smallGap]],
[$b, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$a, [origin]], [$plus, [origin]]];
RETURN[tempBox, tempBoxes];
};
FactorialCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($bang $a $space)
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$space,
[$a, [left], [right]],
[$a, [origin], [origin]]],
[$bang,
[$space, [left], [right]],
[$a, [origin], [origin]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$a, [origin]], [$a, [origin]]];
RETURN[tempBox, tempBoxes];
};
ParenCompRule: CompositionProc ~ {
effects: Composes layout for expr of form ($paren $a) with symbols
$leftParen and $rightParen
tempBox: BOX;
tempBoxes: LIST OF BOX;
alignments: LIST OF Alignment2D ← LIST[
[$leftParen,
[$a, [right], [left]],
[$a, [center], [center]]],
[$rightParen,
[$a, [left], [right]],
[$a, [center], [center]]]];
[tempBox, tempBoxes] ←
MathRules.Compose[boxes, alignments, [$leftParen, [origin]],
[$self, [center, -0.25]]];
RETURN[tempBox, tempBoxes];
};
Class Constructors
MakeBinOpClass: PUBLIC PROC[class, op, a, b: ATOM, operation: EXPR,
description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ {
effects: Creates and returns standard binary operation compound class named "class".
The alignment is "a operation b"; alignment is thru baselines.
All of a, b, op are of fixed size "normal".
aArg: Argument ← MakeArgument[a, LIST[$aliasA, $aliasHot], normal];
bArg: Argument ← MakeArgument[b, LIST[$aliasB], normal];
opSym: Symbol ← MakeSymbol[op, LIST[$aliasBinOp], normal, operation];
leftSpace: Symbol ← MakeSymbol[$leftThinSpace, LIST[$aliasLeftSpace], normal, MakeSpace[$thin]];
rightSpace: Symbol ← MakeSymbol[$rightThinSpace, LIST[$aliasRightSpace], normal, MakeSpace[$thin]];
RETURN[MakeCompoundClass[class, binaryOp, description, LIST[aArg, bArg], LIST[opSym, leftSpace, rightSpace], FixedSizeBoxRule, BinaryOpCompRule, cvtAS]];
};
MakeRelationClass: PUBLIC PROC[class, rel, lhs, rhs: ATOM, relation: EXPR,
description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ {
effects: Creates and returns standard relation compound class named "class".
The alignment is "lhs relation rhs"; alignment is thru baselines.
All of lhs, rhs, rel are of fixed size "normal".
lhsArg: Argument ← MakeArgument[lhs, LIST[$aliasLHS, $aliasHot], normal];
rhsArg: Argument ← MakeArgument[rhs, LIST[$aliasRHS], normal];
relSym: Symbol ← MakeSymbol[rel, LIST[$aliasRelation], normal, relation];
leftSpace: Symbol ← MakeSymbol[$leftSpace, LIST[$aliasLeftSpace], normal, MakeSpace[$thick]];
rightSpace: Symbol ← MakeSymbol[$rightSpace, LIST[$aliasRightSpace], normal, MakeSpace[$thick]];
RETURN[MakeCompoundClass[class, relation, description, LIST[lhsArg, rhsArg], LIST[relSym, leftSpace, rightSpace], FixedSizeBoxRule, RelationCompRule, cvtAS]];
};
MakeUnaryOpClass: PUBLIC PROC[class, op, arg: ATOM, operation: EXPR, description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ {
effects: Creates and returns standard unary operation compound class named "class".
The alignment is "operation arg"; alignment is thru baselines.
Both op, arg are of fixed size "normal".
argArg: Argument ← MakeArgument[arg, LIST[$aliasA, $aliasHot], normal];
spaceSym: Symbol ← MakeSymbol[$Space, LIST[$aliasSpace], normal, MakeSpace[$medium]];
unaryOpSym: Symbol ← MakeSymbol[op, LIST[$aliasUnaryOp], normal, operation];
RETURN[MakeCompoundClass[class, unaryOp, description, LIST[argArg], LIST[unaryOpSym, spaceSym], FixedSizeBoxRule, UnaryOpCompRule, cvtAS]];
};
High Level Expression Constructors
Atoms
MakePlainSym: PROC[c: CHAR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$plainSym, Rope.FromChar[c]]];
};
MakePlainRope: PROC[r: ROPE] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$plainSym, r]];
};
MakeOverlaySym: PROC[r: ROPE] RETURNS[EXPR] ~ {
effects: Returns a symbol expression which is all the chars in r superimposed.
RETURN[MathExpr.MakeAtomicExpr[$overlaySym, r]];
};
MakeBigMathSym: PROC[c: CHAR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$bigMathSym, Rope.FromChar[c]]];
};
MakeSmallMathSym: PROC[c: CHAR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$smallMathSym, Rope.FromChar[c]]];
};
MakeItalSym: PROC[c: CHAR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$italicSym, Rope.FromChar[c]]];
};
MakeMathItalSym: PROC[c: CHAR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$mathItalicSym, Rope.FromChar[c]]];
};
MakeLine: PROC[] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$line, "LINE"]];
};
MakeSpace: PROC[size: ATOM] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$space, Convert.RopeFromAtom[size, FALSE]]];
};
MakePlaceHolder: PUBLIC PROC[] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeAtomicExpr[$placeholder, "\056\057"]];
};
MakeInfinity: PUBLIC PROC[] RETURNS[EXPR] ~ {
effects: Constructs and returns an expression for +infinity.
RETURN[MathExpr.MakeAtomicExpr[$infinity, "\061"]];
};
MakeInt: PUBLIC PROC[n: ROPE] RETURNS[EXPR] ~ {
effects: Constructs and returns an integer expression for n.
SIGNALS badFormat if n is not a legal integer.
IF n.Length[] = 0 THEN ERROR badFormat;
SELECT n.Fetch[0] FROM
IN ['0..'9] => NULL;
'- => IF n.Length[] = 1 THEN ERROR badFormat; -- a lone minus sign is invalid
ENDCASE => ERROR badFormat;
check that each char in n is a legal digit
FOR i:INT IN[1..n.Length[]-1] DO
SELECT n.Fetch[i] FROM
IN ['0..'9] => NULL;
ENDCASE => ERROR badFormat;
ENDLOOP;
RETURN[MathExpr.MakeAtomicExpr[$integer, n]];
};
MakeReal: PUBLIC PROC[r: REAL] RETURNS[EXPR] ~ {
effects: Constructs and returns a real expression for n.
RETURN[MathExpr.MakeAtomicExpr[$real, Convert.RopeFromReal[r]]];
};
MakeVariable: PUBLIC PROC[var: ROPE] RETURNS[EXPR] ~ {
effects: Constructs and returns a variable expression for var.
SIGNALS badFormat if n is not a legal variable (e.g. invalid chars).
IF var.Length[] = 0 THEN ERROR badFormat;
check that each char is an alphabetic char A thru Z, either case (disabled 9/30/86)
FOR i:INT IN[0..var.Length[]-1] DO
SELECT var.Fetch[i] FROM
IN ['A..'Z], IN ['a..'z] => NULL;
ENDCASE => ERROR badFormat;
ENDLOOP;
RETURN[MathExpr.MakeAtomicExpr[$variable, var]];
};
GreekNameToChar: PROC[name: ROPE] RETURNS[CHAR] ~ {
effects: Returns the greek TeX character named by name.
SIGNALS badFormat if names is unrecognized
RETURN[
SELECT TRUE FROM
Rope.Equal["alpha", name, FALSE] => '\013,
Rope.Equal["beta", name, FALSE] => '\014,
Rope.Equal["gamma", name, FALSE] => '\015,
Rope.Equal["delta", name, FALSE] => '\016,
Rope.Equal["epsilon", name, FALSE] => '\017,
Rope.Equal["zeta", name, FALSE] => '\020,
Rope.Equal["eta", name, FALSE] => '\021,
Rope.Equal["theta", name, FALSE] => '\022,
Rope.Equal["iota", name, FALSE] => '\023,
Rope.Equal["kappa", name, FALSE] => '\024,
Rope.Equal["lambda", name, FALSE] => '\025,
Rope.Equal["mu", name, FALSE] => '\026,
Rope.Equal["nu", name, FALSE] => '\027,
Rope.Equal["xi", name, FALSE] => '\030,
Rope.Equal["pi", name, FALSE] => '\031,
Rope.Equal["rho", name, FALSE] => '\032,
Rope.Equal["sigma", name, FALSE] => '\033,
Rope.Equal["tau", name, FALSE] => '\034,
Rope.Equal["upsilon", name, FALSE] => '\035,
Rope.Equal["phi", name, FALSE] => '\036,
Rope.Equal["chi", name, FALSE] => '\037,
Rope.Equal["psi", name, FALSE] => '\040,
Rope.Equal["omega", name, FALSE] => '\041,
ENDCASE => ERROR badFormat -- name unrecognized as a greek letter
];
};
CharToGreekName: PROC[c: CHAR] RETURNS[ROPE] ~ {
effects: Returns the name associated with the greek TeX character c.
If no such association exists, returns "unknown".
RETURN[
SELECT c FROM
'\013 => "alpha",
'\014 => "beta",
'\015 => "gamma",
'\016 => "delta",
'\017 => "epsilon",
'\020 => "zeta",
'\021 => "eta",
'\022 => "theta",
'\023 => "iota",
'\024 => "kappa",
'\025 => "lambda",
'\026 => "mu",
'\027 => "nu",
'\030 => "xi",
'\031 => "pi",
'\032 => "rho",
'\033 => "sigma",
'\034 => "tau",
'\035 => "upsilon",
'\036 => "phi",
'\037 => "chi",
'\040 => "psi",
'\041 => "omega",
ENDCASE => "unknown"
];
};
MakeGreekVar: PUBLIC PROC[name: ROPE] RETURNS[EXPR] ~ {
effects: Constructs and returns a greek variable expression for the
lowercase greek letter associated with name (e.g. "gamma", "lambda").
SIGNALS badFormat if name does not name a greek letter.
greekRope: ROPE ← Rope.FromChar[GreekNameToChar[name ! badFormat => {ERROR badFormat}]];
RETURN[MathExpr.MakeAtomicExpr[$greekVar, greekRope]];
};
Binary Ops
MakeSum: PUBLIC PROC[addend, augend: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$sum, LIST[[$addend, addend], [$augend, augend]]]];
};
MakeDifference: PUBLIC PROC[subtrahend, minuend: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$difference, LIST[[$subtrahend, subtrahend], [$minuend, minuend]]]];
};
MakeAnd: PUBLIC PROC[a, b: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$and, LIST[[$a, a], [$b, b]]]];
};
MakeOr: PUBLIC PROC[a, b: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$or, LIST[[$a, a], [$b, b]]]];
};
Matrix
MakeMatrix: PUBLIC PROC[nRows, nCols: NAT, rows: LIST OF LIST OF EXPR]
RETURNS[EXPR] ~ {
effects: Constructs and returns a matrix expression of size nRows by nCols from rows.
SIGNALS badFormat if dimensions given don't exactly match dimension(rows).
local declarations
elements: LIST OF MathExpr.TaggedMathExpr ← NIL;
rowCount, colCount: NAT ← 0;
FOR l: LIST OF LIST OF EXPR ← rows, l.rest UNTIL l = NIL DO
rowCount ← rowCount + 1;
colCount ← 0;
FOR elts: LIST OF EXPR ← l.first, elts.rest UNTIL elts = NIL DO
colCount ← colCount + 1;
elements ← CONS[[MathRules.AtomFromRowCol[rowCount, colCount], elts.first], elements];
ENDLOOP;
IF colCount # nCols THEN ERROR badFormat; -- wrong # cols for this row
ENDLOOP;
IF rowCount # nRows THEN ERROR badFormat; -- wrong # rows
RETURN[MathExpr.MakeMatrixExpr[$matrix, nRows, nCols, elements]];
};
MakeVector: PUBLIC PROC[dimension: NAT, elements: LIST OF EXPR, row: BOOL] RETURNS[EXPR] ~ {
effects: Constructs and returns a vector expression of size dimension from elements.
SIGNALS badFormat if dimension doesn't exactly match dimension(elements).
local declarations
elts: LIST OF MathExpr.TaggedMathExpr ← NIL;
rowCount, colCount: NAT ← 0;
IF row THEN rowCount ← 1 ELSE colCount ← 1; -- row vec has 1 row, col vec has 1 col
FOR l: LIST OF EXPR ← elements, l.rest UNTIL l = NIL DO
IF row THEN colCount ← colCount + 1 ELSE rowCount ← rowCount + 1;
elts ← CONS[[MathRules.AtomFromRowCol[rowCount, colCount], l.first], elts];
ENDLOOP;
complain if dimension does not agree with length(elements)
IF row THEN {
IF colCount # dimension THEN ERROR badFormat; -- wrong # elements
}
ELSE {
IF rowCount # dimension THEN ERROR badFormat; -- wrong # elements
};
RETURN[MathExpr.MakeMatrixExpr[$vector, rowCount, colCount, elts]];
};
Other
MakeComplex: PUBLIC PROC[a, b: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$complex, LIST[[$a, a], [$b, b]]]];
};
MakeProduct: PUBLIC PROC[multiplier, multiplicand: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$product, LIST[[$multiplier, multiplier], [$multiplicand, multiplicand]]]];
};
MakeFraction: PUBLIC PROC[numerator, denominator: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$fraction, LIST[[$numerator, numerator], [$denominator, denominator]]]];
};
MakePow: PUBLIC PROC[base, exponent: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$pow, LIST[[$base, base], [$exponent, exponent]]]];
};
MakeSubscript: PUBLIC PROC[base, subscript: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$subscript, LIST[[$base, base], [$subscript, subscript]]]];
};
MakeParen: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$paren, LIST[[$a, a]]]];
};
Relations
MakeEqFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$eqFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]];
};
MakeNotEqFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$notEqFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]];
};
MakeLtFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$ltFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]];
};
MakeLeFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$leFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]];
};
MakeGtFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$gtFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]];
};
MakeGeFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$geFormula, LIST[[$lhs, lhs], [$rhs, rhs]]]];
};
Radical
MakeRadical: PUBLIC PROC[radicand, n: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$nRadical, LIST[[$radicand, radicand], [$n, n]]]];
};
Ops
MakeSummation: PUBLIC PROC[lb, ub, summand: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$summation, LIST[[$lowerbound, lb], [$summand, summand], [$upperbound, ub]]]];
};
MakeIntegral: PUBLIC PROC[llim, ulim, integrand, wrt: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$integration, LIST[[$lowerlimit, llim], [$upperlimit, ulim], [$integrand, integrand], [$wrt, wrt]]]];
};
MakeIndefiniteIntegral: PUBLIC PROC[integrand, wrt: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$indefInt, LIST[[$integrand, integrand], [$wrt, wrt]]]];
};
Unary Ops
MakeNot: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$not, LIST[[$a, a]]]];
};
MakeNegation: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ {
RETURN[MathExpr.MakeCompoundExpr[$negation, LIST[[$a, a]]]];
};
Signals & Errors
wrongAtomValueType: PUBLIC ERROR = CODE;
wrongBoxType: PUBLIC ERROR = CODE;
badFormat: PUBLIC ERROR = CODE;
Define & Install Expression Classes
DefineClasses: PROC [] ~ {
local declarations (lots of 'em)
cmr10, cmti10, cmmi10, cmex10, cmsy10: Style;
integerClass, realClass, variableClass, plainSymClass, overlaySymClass, smallMathSymClass, bigMathSymClass, italSymClass, mathItalSymClass, lineClass, placeholderClass, spaceClass, greekVarClass, infinityClass: AtomClass;
sumClass, summationClass, fractionClass, integrationClass, indefIntClass, differenceClass, powClass, eqFormulaClass, approxEqFormulaClass, notEqFormulaClass, ltFormulaClass, leFormulaClass, geFormulaClass, gtFormulaClass, nRadicalClass, radicalClass, complexClass, productClass, orClass, notClass, negationClass, andClass, parenClass, subscriptClass, listClass, functionClass, altFunctionClass, limitClass, factorialClass, approachesClass: CompoundClass;
matrixClass, vectorClass: MatrixClass;
lbArg, ubArg, summandArg, llimArg, ulimArg, integrandArg, wrtArg, baseArg, exponentArg, numeratorArg, denominatorArg, nArg, radicandArg, realPartArg, imaginaryPartArg, aParenArg, subscriptArg, carArg, cdrArg, fArg, argsArg, ofArg, approachesArg, factorialArg: Argument;
plusSym, sigmaSym, integralSym, dxSym, lineSym, radRootSym, radLineSym, iSym, leftParenSym, rightParenSym, numerSpSym, denomSpSym, integralSpaceSym, commaSym, listSpSym, funSpaceSym, funLParenSym, funRParenSym, altFunLP, altFunRP, limSym, factorialSym, factorialSpSym, limSpaceSym, radSpaceSym: Symbol;
reset current DB state (i.e. clean slate)
MathDB.ResetAtomClasses[];
MathDB.ResetCompoundClasses[];
MathDB.ResetMatrixClasses[];
plain vanilla TeX fonts
cmr10 ← [font: "xerox/pressfonts/cmr60"]; -- standard times roman (1 unit high)
cmti10 ← [font: "xerox/pressfonts/cmti60"]; -- italic (1 unit high)
cmex10 ← [font: "xerox/pressfonts/cmex60"]; -- math extentsion font (1 unit high)
cmmi10 ← [font: "xerox/pressfonts/cmmi60"]; -- math italic font (1 unit high)
cmsy10 ← [font: "xerox/pressfonts/cmsy60"]; -- math symbols font (1 unit high)
define Atom Classes
integerClass ← MakeAtomClass[$integer, atom, argument, cmr10, RopeBox, PaintRope];
realClass ← MakeAtomClass[$real, atom, argument, cmr10, RopeBox, PaintRope];
variableClass ← MakeAtomClass[$variable, atom, argument, cmti10, RopeBox, PaintRope];
greekVarClass ← MakeAtomClass[$greekVar, atom, argument, cmmi10, CharBox, PaintChar, GreekVarToASRope];
plainSymClass ← MakeAtomClass[$plainSym, atom, symbol, cmr10, RopeBox, PaintRope];
overlaySymClass ← MakeAtomClass[$overlaySym, atom, symbol, cmr10, OverlayBox, PaintOverlay];
bigMathSymClass ← MakeAtomClass[$bigMathSym, atom, symbol, cmex10, CharBox, PaintChar];
smallMathSymClass ← MakeAtomClass[$smallMathSym, atom, symbol, cmsy10, CharBox, PaintChar];
mathItalSymClass ← MakeAtomClass[$mathItalicSym, atom, symbol, cmmi10, CharBox, PaintChar];
italSymClass ← MakeAtomClass[$italicSym, atom, symbol, cmti10, CharBox, PaintChar];
lineClass ← MakeAtomClass[$line, atom, symbol, cmr10, LineBox, PaintLine];
placeholderClass ← MakeAtomClass[$placeholder, atom, placeholder, cmmi10, RopeBox, PaintRope, PlaceHolderToASRope];
spaceClass ← MakeAtomClass[$space, atom, symbol, cmr10, SpaceBox, PaintSpace];
infinityClass ← MakeAtomClass[$infinity, atom, argument, cmsy10, CharBox, PaintChar, InfinityToASRope];
register atom classes
MathDB.InstallAtomClass[integerClass];
MathDB.InstallAtomClass[realClass];
MathDB.InstallAtomClass[variableClass];
MathDB.InstallAtomClass[greekVarClass];
MathDB.InstallAtomClass[plainSymClass];
MathDB.InstallAtomClass[overlaySymClass];
MathDB.InstallAtomClass[italSymClass];
MathDB.InstallAtomClass[smallMathSymClass];
MathDB.InstallAtomClass[bigMathSymClass];
MathDB.InstallAtomClass[mathItalSymClass];
MathDB.InstallAtomClass[lineClass];
MathDB.InstallAtomClass[placeholderClass];
MathDB.InstallAtomClass[spaceClass];
MathDB.InstallAtomClass[infinityClass];
define info for "complex a b" (a + bi)
realPartArg ← MakeArgument[$a, LIST[$aliasA, $aliasHot], normal];
imaginaryPartArg ← MakeArgument[$b, LIST[$aliasB], normal];
iSym ← MakeSymbol[$i, NIL, normal, MakeItalSym['i]];
plusSym ← MakeSymbol[$plus, LIST[$aliasBinOp], normal, MakePlainSym['+]];
define info for "summation lowerbound upperbound summand"
lbArg ← MakeArgument[$lowerbound, NIL, script];
ubArg ← MakeArgument[$upperbound, NIL, script];
summandArg ← MakeArgument[$summand, LIST[$aliasHot], normal];
sigmaSym ← MakeSymbol[$sigma, LIST[$aliasOp], normal, MakeBigMathSym['\130]];
define info for indefinite & definite integrals (normal & surface)
llimArg ← MakeArgument[$lowerlimit, NIL, script];
ulimArg ← MakeArgument[$upperlimit, NIL, script];
integrandArg ← MakeArgument[$integrand, LIST[$aliasHot], normal];
wrtArg ← MakeArgument[$wrt, NIL, normal];
integralSym ← MakeSymbol[$integral, LIST[$aliasOp], normal, MakeBigMathSym['\132]];
dxSym ← MakeSymbol[$dx, NIL, normal, MakeItalSym['d]];
integralSpaceSym ← MakeSymbol[$space, LIST[$aliasSpace], normal, MakeSpace[$thick]];
define info for "pow base exponent" & "subscript base subscript"
baseArg ← MakeArgument[$base, LIST[$aliasA, $aliasHot], normal];
exponentArg ← MakeArgument[$exponent, LIST[$aliasB], script];
subscriptArg ← MakeArgument[$subscript, LIST[$aliasB], script];
define info for "fraction numerator denominator"
numeratorArg ← MakeArgument[$numerator, LIST[$aliasA, $aliasHot], normal];
denominatorArg ← MakeArgument[$denominator, LIST[$aliasB], normal];
denomSpSym ← MakeSymbol[$bottomSpace, LIST[$aliasSpace], normal, MakeSpace[$thin]];
numerSpSym ← MakeSymbol[$topSpace, LIST[$aliasSpace], normal, MakeSpace[$thin]];
lineSym ← MakeSymbol[$fractionBar, LIST[$aliasLine], normal, MakeLine[]];
define info for "radical n radicand"
nArg ← MakeArgument[$n, LIST[$aliasB], script];
radicandArg ← MakeArgument[$radicand, LIST[$aliasA, $aliasHot], normal];
radRootSym ← MakeSymbol[$radRoot, NIL, normal, MakeBigMathSym['\162]];
radLineSym← MakeSymbol[$radLine, LIST[$aliasLine], normal, MakeLine[]];
radSpaceSym ← MakeSymbol[$space, LIST[$aliasSpace], normal, MakeSpace[$medium]];
define info for "( a )"
aParenArg ← MakeArgument[$a, LIST[$aliasA, $aliasHot], normal];
leftParenSym ← MakeSymbol[$leftParen, NIL, normal, MakeBigMathSym['\040]];
rightParenSym ← MakeSymbol[$rightParen, NIL, normal, MakeBigMathSym['\041]];
define info for "$list $car $cdr"
carArg ← MakeArgument[$car, LIST[$aliasA, $aliasHot], normal];
cdrArg ← MakeArgument[$cdr, LIST[$aliasB], normal];
commaSym ← MakeSymbol[$comma, NIL, normal, MakeItalSym[',]];
listSpSym ← MakeSymbol[$space, LIST[$aliasSpace], normal, MakeSpace[$thick]];
define info for functions
fArg ← MakeArgument[$f, LIST[$aliasA, $aliasHot], normal];
argsArg ← MakeArgument[$args, LIST[$aliasB], normal];
funSpaceSym ← MakeSymbol[$space, LIST[$aliasSpace], normal, MakeSpace[$medium]];
funLParenSym ← MakeSymbol[$leftParen, NIL, normal, MakePlainSym['\050]];
funRParenSym ← MakeSymbol[$rightParen, NIL, normal, MakePlainSym['\051]];
altFunLP ← MakeSymbol[$leftParen, NIL, normal, MakeSpace[$null]];
altFunRP ← MakeSymbol[$rightParen, NIL, normal, MakeSpace[$null]];
define info for limits
ofArg ← MakeArgument[$of, LIST[$aliasA, $aliasHot], normal];
approachesArg ← MakeArgument[$approaches, NIL, script];
limSpaceSym ← MakeSymbol[$space, LIST[$aliasSpace], normal, MakeSpace[$limit]];
limSym ← MakeSymbol[$lim, NIL, script, MakePlainRope["lim"]];
define into for factorial
factorialArg ← MakeArgument[$a, LIST[$aliasA, $aliasHot], normal];
factorialSym ← MakeSymbol[$bang, NIL, normal, MakePlainSym['!]];
factorialSpSym ← MakeSymbol[$space, LIST[$aliasSpace], normal, MakeSpace[$thin]];
define compound classes
binary operations
sumClass ← MakeBinOpClass[$sum, $plus, $addend, $augend, MakePlainSym['+], "a + b", "$addend + $augend"];
differenceClass ← MakeBinOpClass[$difference, $minus, $subtrahend, $minuend, MakePlainSym['\173], "a - b", "$subtrahend - $minuend"];
productClass ← MakeBinOpClass[$product, $times, $multiplier, $multiplicand, MakeSpace[$product], "a * b", "$multiplier * $multiplicand"];
andClass ← MakeBinOpClass[$and, $andOp, $a, $b, MakeSmallMathSym['\136], "a AND b", "$a & $b"];
orClass ← MakeBinOpClass[$or, $orOp, $a, $b, MakeSmallMathSym['\137], "a OR b", "$a | $b"];
unary operations
negationClass ← MakeUnaryOpClass[$negation, $minus, $a, MakePlainSym['-], "-a", "-$a"];
notClass ← MakeUnaryOpClass[$not, $notOp, $a, MakeSmallMathSym['\072], "~a", "~ $a"];
relations
eqFormulaClass ← MakeRelationClass[$eqFormula, $equals, $lhs, $rhs, MakePlainSym['=], "lhs = rhs", "$lhs = $rhs"];
notEqFormulaClass ← MakeRelationClass[$notEqFormula, $equals, $lhs, $rhs, MakeOverlaySym["=/"], "lhs # rhs", "$lhs # $rhs"];
ltFormulaClass ← MakeRelationClass[$ltFormula, $lt, $lhs, $rhs, MakeMathItalSym['<], "lhs < rhs", "$lhs < $rhs"];
gtFormulaClass ← MakeRelationClass[$gtFormula, $gt, $lhs, $rhs, MakeMathItalSym['>], "lhs > rhs", "$lhs > $rhs"];
leFormulaClass ← MakeRelationClass[$leFormula, $le, $lhs, $rhs, MakeSmallMathSym['\024], "lhs <= rhs", "$lhs <= $rhs"];
geFormulaClass ← MakeRelationClass[$geFormula, $ge, $lhs, $rhs, MakeSmallMathSym['\025], "lhs >= rhs", "$lhs >= $rhs"];
approxEqFormulaClass ← MakeRelationClass[$approxEqFormula, $equals, $lhs, $rhs, MakeSmallMathSym['\031], "lhs approx= rhs", "$lhs approx= $rhs"];
approachesClass ← MakeRelationClass[$approachesFormula, $approaches, $lhs, $rhs, MakeSmallMathSym['\041], "lhs -> rhs", "$lhs -> $rhs"];
others
listClass ← MakeCompoundClass[$list, other, "a, b", LIST[carArg, cdrArg], LIST[commaSym, listSpSym], FixedSizeBoxRule, ListCompRule, "($car $cdr)"];
functionClass ← MakeCompoundClass[$function, other, "function(args)", LIST[fArg, argsArg], LIST[funLParenSym, funRParenSym, funSpaceSym], FunctionBoxRule, FunctionCompRule, "(function $f $args)"];
altFunctionClass ← MakeCompoundClass[$altFunction, other, "function args", LIST[fArg, argsArg], LIST[altFunLP, altFunRP, funSpaceSym], FixedSizeBoxRule, FunctionCompRule, "(function $f $args)"];
complexClass ← MakeCompoundClass[$complex, other, "a + bi", LIST[realPartArg, imaginaryPartArg], LIST[iSym, plusSym], FixedSizeBoxRule, ComplexCompRule, "($a + $bi)"];
summationClass ← MakeCompoundClass[$summation, op, "summation", LIST[lbArg, ubArg, summandArg], LIST[sigmaSym], FixedSizeBoxRule, SummationCompRule, "(summation $lowerbound $upperbound $summand)"];
integrationClass ← MakeCompoundClass[$integration, op, "def integration", LIST[llimArg, ulimArg, integrandArg, wrtArg], LIST[integralSym, dxSym, integralSpaceSym], FixedSizeBoxRule, IntegrationCompRule, "(integral $lowerlimit $upperlimit $integrand $wrt)"];
indefIntClass ← MakeCompoundClass[$indefInt, op, "indef integration", LIST[integrandArg, wrtArg], LIST[integralSym, dxSym, integralSpaceSym], FixedSizeBoxRule, IndefiniteIntCompRule, "(indefIntegral $integrand $wrt)"];
powClass ← MakeCompoundClass[$pow, other, "a^b", LIST[baseArg, exponentArg], NIL, FixedSizeBoxRule, PowCompRule, "$base^$exponent"];
subscriptClass ← MakeCompoundClass[$subscript, other, "a sub b", LIST[baseArg, subscriptArg], NIL, FixedSizeBoxRule, SubscriptCompRule, "$baseSub$subscript"];
parenClass ← MakeCompoundClass[$paren, paren, "( a )", LIST[aParenArg], LIST[leftParenSym, rightParenSym], ParenBoxRule, ParenCompRule, "( $a )"];
fractionClass ← MakeCompoundClass[$fraction, over, "a / b", LIST[numeratorArg, denominatorArg], LIST[lineSym, numerSpSym, denomSpSym], FractionBoxRule, FractionCompRule, "$numerator / $denominator"];
nRadicalClass ← MakeCompoundClass[$nRadical, radical, "nth radical", LIST[nArg, radicandArg], LIST[radRootSym, radLineSym, radSpaceSym], NRadicalBoxRule, NRadicalCompRule, "(nthRoot $radicand $n)"];
radicalClass ← MakeCompoundClass[$radical, radical, "radical", LIST[radicandArg], LIST[radRootSym, radLineSym, radSpaceSym], RadicalBoxRule, RadicalCompRule, "(Root $radicand)"];
limitClass ← MakeCompoundClass[$limit, other, "limit", LIST[approachesArg, ofArg], LIST[limSpaceSym, limSym], FixedSizeBoxRule, LimitCompRule, "(limit $approaches $of)"];
factorialClass ← MakeCompoundClass[$factorial, other, "a!", LIST[factorialArg], LIST[factorialSym, factorialSpSym], FixedSizeBoxRule, FactorialCompRule, "$a!"];
register compound classes
binary ops
MathDB.InstallCompoundClass[sumClass];
MathDB.InstallCompoundClass[differenceClass];
MathDB.InstallCompoundClass[andClass];
MathDB.InstallCompoundClass[orClass];
unary ops
MathDB.InstallCompoundClass[notClass];
MathDB.InstallCompoundClass[negationClass];
others
MathDB.InstallCompoundClass[listClass];
MathDB.InstallCompoundClass[factorialClass];
MathDB.InstallCompoundClass[functionClass];
MathDB.InstallCompoundClass[altFunctionClass];
MathDB.InstallCompoundClass[powClass];
MathDB.InstallCompoundClass[subscriptClass];
MathDB.InstallCompoundClass[parenClass];
MathDB.InstallCompoundClass[complexClass];
MathDB.InstallCompoundClass[productClass];
MathDB.InstallCompoundClass[summationClass];
MathDB.InstallCompoundClass[limitClass];
MathDB.InstallCompoundClass[approachesClass];
MathDB.InstallCompoundClass[integrationClass];
MathDB.InstallCompoundClass[indefIntClass];
MathDB.InstallCompoundClass[fractionClass];
MathDB.InstallCompoundClass[radicalClass];
MathDB.InstallCompoundClass[nRadicalClass];
relations
MathDB.InstallCompoundClass[eqFormulaClass];
MathDB.InstallCompoundClass[notEqFormulaClass];
MathDB.InstallCompoundClass[ltFormulaClass];
MathDB.InstallCompoundClass[leFormulaClass];
MathDB.InstallCompoundClass[gtFormulaClass];
MathDB.InstallCompoundClass[geFormulaClass];
MathDB.InstallCompoundClass[approxEqFormulaClass];
define matrix classes
matrixClass ← MathExpr.MakeMatrixClass[$matrix, matrix, MakeBigMathSym['\042], MakeBigMathSym['\043], MakeSpace[$matrix]];
vectorClass ← MathExpr.MakeMatrixClass[$vector, matrix, MakeBigMathSym['\042], MakeBigMathSym['\043], MakeSpace[$matrix]];
install matrix classes
MathDB.InstallMatrixClass[matrixClass];
MathDB.InstallMatrixClass[vectorClass];
};
Install Classes Defined in this Module
DefineClasses[];
END.