<> <> DIRECTORY MathExpr, MathRules, MathDB, MathTypes, MathBox, ImagerFont, ImagerTransformation, Imager, Rope USING [ROPE, Fetch, Length], Vector USING [VEC], Convert USING [RopeFromChar, RopeFromReal], MathConstructors; MathConstructorsImpl: CEDAR PROGRAM IMPORTS MathBox, MathRules, ImagerFont, Imager, ImagerTransformation, MathExpr, MathDB, Convert, Rope EXPORTS MathConstructors ~ BEGIN <> EXPR: TYPE ~ MathExpr.EXPR; BOX: TYPE ~ MathBox.BOX; ROPE: TYPE ~ Rope.ROPE; VEC: TYPE ~ Vector.VEC; AtomBoxProc: TYPE ~ MathRules.AtomBoxProc; AtomPaintProc: TYPE ~ MathRules.AtomPaintProc; CompoundBoxProc: TYPE ~ MathRules.CompoundBoxProc; CompositionProc: TYPE ~ MathRules.CompositionProc; AtomToRopeProc: TYPE ~ MathRules.AtomToRopeProc; Alignment2D: TYPE ~ MathRules.Alignment2D; Offset: TYPE ~ MathRules.Offset; Size: TYPE ~ MathRules.Size; AtomValue: TYPE ~ MathTypes.AtomValue; AtomRopeValue: TYPE ~ MathTypes.AtomRopeValue; AtomCharValue: TYPE ~ MathTypes.AtomCharValue; AtomBoxValue: TYPE ~ MathTypes.AtomBoxValue; Argument: TYPE ~ MathExpr.Argument; Symbol: TYPE ~ MathExpr.Symbol; AtomClass: TYPE ~ MathExpr.AtomClass; AtomFlavor: TYPE ~ MathExpr.AtomFlavor; CompoundClass: TYPE ~ MathExpr.CompoundClass; FormatClass: TYPE ~ MathTypes.FormatClass; Style: TYPE ~ MathTypes.Style; <> 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, cvtRope: AtomToRopeProc] 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: ROPE _ NIL] RETURNS[CompoundClass] ~ MathExpr.MakeCompoundClass; <> smallGap: REAL = 0.05; medGap: REAL = 0.10; bigGap: REAL = 0.25; thinSpace: ImagerFont.Extents = [leftExtent: 0.0, rightExtent: 0.05, ascent: 0.05, descent: 0.0]; medSpace: ImagerFont.Extents = [leftExtent: 0.0, rightExtent: 0.12, ascent: 0.12, descent: 0.0]; <<>> <> <> PaintChar: AtomPaintProc ~ { <> <> xFactor, yFactor: REAL; -- scaling factors font: ImagerFont.Font; extents: ImagerFont.Extents; <> IF (absBox.Type # absolute) THEN ERROR wrongBoxType; WITH value SELECT FROM c: AtomCharValue => { font _ ImagerFont.Find[style.font]; extents _ ImagerFont.BoundingBox[font, c.char]; Imager.SetXY[context, [absBox.Offset.x, absBox.Offset.y]]; xFactor _ absBox.Width / (extents.leftExtent + extents.rightExtent); yFactor _ absBox.Height / (extents.descent + extents.ascent); Imager.SetFont[context, ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]]; Imager.ShowXChar[context, c.char]; }; <> ENDCASE => ERROR wrongAtomValueType; }; PaintRope: AtomPaintProc ~ { <> <> xFactor, yFactor: REAL; -- scaling factors font: ImagerFont.Font; extents: ImagerFont.Extents; <> IF (absBox.Type # absolute) THEN ERROR wrongBoxType; WITH value SELECT FROM r: AtomRopeValue => { font _ ImagerFont.Find[style.font]; extents _ ImagerFont.RopeBoundingBox[font, r.rope]; Imager.SetXY[context, [absBox.Offset.x, absBox.Offset.y]]; xFactor _ absBox.Width / (extents.rightExtent + extents.leftExtent); yFactor _ absBox.Height / (extents.ascent + extents.descent); Imager.SetFont[context, ImagerFont.Modify[font, ImagerTransformation.Scale2[[xFactor, yFactor]]]]; Imager.ShowRope[context, r.rope]; }; <> ENDCASE => ERROR wrongAtomValueType; }; PaintLine: AtomPaintProc ~ { <> <> 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 ~ { <> RETURN; }; <> LineBox: AtomBoxProc ~ { <> << Note that this is always a dummy value>> <> RETURN[[leftExtent: 0.0, rightExtent: 1.0, descent: 0.0, ascent: 0.03]]; }; CvtOtherToRope: AtomToRopeProc ~ { <> RETURN[""]; }; CharBox: AtomBoxProc ~ { <> font: ImagerFont.Font; font _ ImagerFont.Scale[ImagerFont.Find[style.font], style.scale]; WITH value SELECT FROM c: AtomCharValue => RETURN[ImagerFont.BoundingBox[font, c.char]]; <> ENDCASE => ERROR wrongAtomValueType; }; CvtCharToRope: AtomToRopeProc ~ { <> WITH value SELECT FROM c: AtomCharValue => RETURN[Convert.RopeFromChar[from: VAL[c.char.code], quote: FALSE]]; <> ENDCASE => ERROR wrongAtomValueType; }; RopeBox: AtomBoxProc ~ { <> font: ImagerFont.Font _ ImagerFont.Scale[ImagerFont.Find[style.font], style.scale]; WITH value SELECT FROM r: AtomRopeValue => RETURN[ImagerFont.RopeBoundingBox[font, r.rope]]; <> ENDCASE => ERROR wrongAtomValueType; }; CvtRopeToRope: AtomToRopeProc ~ { <> WITH value SELECT FROM r: AtomRopeValue => RETURN[r.rope]; <> ENDCASE => ERROR wrongAtomValueType; }; SpaceBox: AtomBoxProc ~ { <> WITH value SELECT FROM b: AtomBoxValue => RETURN[b.box]; <> ENDCASE => ERROR wrongAtomValueType; }; CvtSpaceToRope: AtomToRopeProc ~ { <> RETURN[NIL]; }; <> <> FixedSizeBoxRule: CompoundBoxProc ~ { <> RETURN[boxes]; }; FractionBoxRule: CompoundBoxProc ~ { <> <> fbarBox: BOX _ MathBox.GetBox[$fractionBar, boxes]; numBox: BOX _ MathBox.GetBox[$numerator, boxes]; denomBox: BOX _ MathBox.GetBox[$denominator, boxes]; <> scaleX: REAL _ 1.1 * MAX[numBox.Width[], denomBox.Width[]] / fbarBox.Width[]; <> fbarBox _ MathBox.Scale[fbarBox, [scaleX, 1.0]]; RETURN[LIST[fbarBox, numBox, denomBox]]; }; ParenBoxRule: CompoundBoxProc ~ { <> <<>> leftParenBox: BOX _ MathBox.GetBox[$leftParen, boxes]; rightParenBox: BOX _ MathBox.GetBox[$rightParen, boxes]; aBox: BOX _ MathBox.GetBox[$a, boxes]; <> scaleFactor: REAL _ 1.1 * aBox.Height[] / leftParenBox.Height[]; leftParenBox _ MathBox.Scale[leftParenBox, [scaleFactor, scaleFactor]]; rightParenBox _ MathBox.Scale[rightParenBox, [scaleFactor, scaleFactor]]; RETURN[LIST[aBox, leftParenBox, rightParenBox]]; }; RadicalBoxRule: CompoundBoxProc ~ { <> <> radRootBox: BOX _ MathBox.GetBox[$radRoot, boxes]; radLineBox: BOX _ MathBox.GetBox[$radLine, boxes]; nBox: BOX _ MathBox.GetBox[$n, boxes]; radicandBox: BOX _ MathBox.GetBox[$radicand, boxes]; <> <> rootScale: REAL _ 1.2 * radicandBox.Height[] / radRootBox.Height[]; lineScale: VEC _ [radicandBox.Width[]/radLineBox.Width[], 1.0]; <> radRootBox _ MathBox.Scale[radRootBox, [rootScale, rootScale]]; radLineBox _ MathBox.Scale[radLineBox, lineScale]; RETURN[LIST[radRootBox, radLineBox, nBox, radicandBox]]; }; <> PowCompRule: CompositionProc ~ { <> tempBox: BOX; tempBoxes: LIST OF BOX; vertOffsetExponent, vertOffsetBase: Offset; alignments: LIST OF Alignment2D _ NIL; IF MathBox.GetBox[$base, boxes].Height[] > MathBox.GetBox[$exponent, boxes].Height[] THEN { vertOffsetExponent _ [bottom, 0.2]; vertOffsetBase _ [top]; } ELSE { vertOffsetExponent _ [bottom]; vertOffsetBase _ [top, -0.2]; }; alignments _ LIST[ [$exponent, [$base, [left], [right]], [$base, vertOffsetExponent, vertOffsetBase]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $base, $base]; RETURN[tempBox, tempBoxes]; }; FractionCompRule: CompositionProc ~ { <> tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$denominator, [$fractionBar, [center], [center]], [$fractionBar, [top], [bottom, -2*bigGap]]], [$numerator, [$fractionBar, [center], [center]], [$fractionBar, [bottom], [top, 2*bigGap]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $fractionBar, $fractionBar]; RETURN[tempBox, tempBoxes]; }; SummationCompRule: CompositionProc ~ { <> << $summand)>> tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$lowerbound, [$sigma, [center], [center]], [$sigma, [top], [bottom, -smallGap]]], [$upperbound, [$sigma, [center], [center]], [$sigma, [bottom], [top, smallGap]]], [$summand, [$sigma, [left], [right, medGap]], [$sigma, [center], [center]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $sigma, $summand]; RETURN[tempBox, tempBoxes]; }; RadicalCompRule: CompositionProc ~ { <> tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$radRoot, [$radicand, [right], [left]], [$radicand, [center], [center]]], [$radLine, [$radRoot, [left], [right]], [$radRoot, [top], [top]]], [$n, [$radRoot, [right], [left, bigGap]], [$radRoot, [bottom], [center, smallGap]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $n, $radicand]; RETURN[tempBox, tempBoxes]; }; IntegrationCompRule: CompositionProc ~ { <> tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$lowerlimit, [$integral, [right], [left, medGap]], [$integral, [top], [bottom, -smallGap]]], [$upperlimit, [$integral, [left], [right, -medGap]], [$integral, [bottom], [top, smallGap]]], [$integrand, [$integral, [left], [right]], [$integral, [center], [center]]], [$dx, [$integrand, [left], [right, smallGap]], [$integrand, [origin], [origin]]], [$wrt, [$dx, [left], [right]], [$dx, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $lowerlimit, $integrand]; RETURN[tempBox, tempBoxes]; }; UnaryOpCompRule: CompositionProc ~ { <> 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, $aliasUnaryOp]; RETURN[tempBox, tempBoxes]; }; BinaryOpCompRule: CompositionProc ~ { <> << symbols $aliasLeftSpace & $aliasRightSpace.>> <<>> tempBox: BOX; tempBoxes: LIST OF BOX; leftVertOffsetA, leftVertOffsetOp, rightVertOffsetB, rightVertOffsetOp: Offset; alignments: LIST OF Alignment2D; <> 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, $aliasBinOp]; RETURN[tempBox, tempBoxes]; }; RelationCompRule: CompositionProc ~ { <> << symbols $aliasLeftSpace & $aliasRightSpace.>> <<>> tempBox: BOX; tempBoxes: LIST OF BOX; leftVertOffsetLHS, leftVertOffsetRel, rightVertOffsetRHS, rightVertOffsetRel: Offset; alignments: LIST OF Alignment2D; <> 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, $aliasRelation]; RETURN[tempBox, tempBoxes]; }; ComplexCompRule: CompositionProc ~ { <> 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, $plus]; RETURN[tempBox, tempBoxes]; }; ProductCompRule: CompositionProc ~ { <> tempBox: BOX; tempBoxes: LIST OF BOX; alignments: LIST OF Alignment2D _ LIST[[$multiplier, [$multiplicand, [right], [left, -smallGap]], [$multiplicand, [origin], [origin]]]]; [tempBox, tempBoxes] _ MathRules.Compose[boxes, alignments, $multiplier, $multiplier]; RETURN[tempBox, tempBoxes]; }; ParenCompRule: CompositionProc ~ { <> << $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, $a]; RETURN[tempBox, tempBoxes]; }; <> <<>> MakeBinOpClass: PUBLIC PROC[class, op, a, b: ATOM, operation: EXPR, description: ROPE, cvtAS: ROPE] RETURNS[CompoundClass] ~ { <> << 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[thinSpace]]; rightSpace: Symbol _ MakeSymbol[$rightThinSpace, LIST[$aliasRightSpace], normal, MakeSpace[thinSpace]]; 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] ~ { <> << 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[medSpace]]; rightSpace: Symbol _ MakeSymbol[$rightSpace, LIST[$aliasRightSpace], normal, MakeSpace[medSpace]]; 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] ~ { <> << 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[medSpace]]; unaryOpSym: Symbol _ MakeSymbol[op, LIST[$aliasUnaryOp], normal, operation]; RETURN[MakeCompoundClass[class, unaryOp, description, LIST[argArg], LIST[unaryOpSym, spaceSym], FixedSizeBoxRule, UnaryOpCompRule, cvtAS]]; }; <> <> MakePlainSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$plainSym, MathExpr.MakeAtomChar[c]]]; }; MakeBigMathSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$bigMathSym, MathExpr.MakeAtomChar[c]]]; }; MakeSmallMathSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$smallMathSym, MathExpr.MakeAtomChar[c]]]; }; MakeItalSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$italicSym, MathExpr.MakeAtomChar[c]]]; }; MakeMathItalSym: PROC[c: CHAR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$mathItalicSym, MathExpr.MakeAtomChar[c]]]; }; MakeLine: PROC[] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$line, MathExpr.MakeAtomOther[NIL]]]; }; MakeSpace: PROC[b: ImagerFont.Extents] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$space, MathExpr.MakeAtomBox[b]]]; }; MakePlaceHolder: PUBLIC PROC[] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeAtomicExpr[$placeholder, MathExpr.MakeAtomRope["\056\057"]]]; }; MakeInt: PUBLIC PROC[n: ROPE] RETURNS[EXPR] ~ { <> << 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; <> 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, MathExpr.MakeAtomRope[n]]]; }; MakeReal: PUBLIC PROC[r: REAL] RETURNS[EXPR] ~ { <> <<>> RETURN[MathExpr.MakeAtomicExpr[$real, MathExpr.MakeAtomRope[Convert.RopeFromReal[r]]]]; }; MakeVariable: PUBLIC PROC[var: ROPE] RETURNS[EXPR] ~ { <> << SIGNALS badFormat if n is not a legal variable (e.g. invalid chars).>> <<>> IF var.Length[] = 0 THEN ERROR badFormat; <<>> <> 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, MathExpr.MakeAtomRope[var]]]; }; <> 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]]]]; }; <> <<>> MakeMatrix: PUBLIC PROC[nRows, nCols: NAT, rows: LIST OF LIST OF EXPR] RETURNS[EXPR] ~ { <> 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; ENDLOOP; RETURN[MathExpr.MakeMatrixExpr[[$matrix, matrix], nRows, nCols, elements, MakeBigMathSym['\042], MakeBigMathSym['\043], MakeSpace[[leftExtent: 0.0, rightExtent: 0.9, descent: 0.0, ascent: 0.6]]]]; }; <> <<>> 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]]]]; }; MakeParen: PUBLIC PROC[a: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$paren, LIST[[$a, a]]]]; }; <> MakeEqFormula: PUBLIC PROC[lhs, rhs: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$eqFormula, 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]]]]; }; <> MakeRadical: PUBLIC PROC[radicand, n: EXPR] RETURNS[EXPR] ~ { RETURN[MathExpr.MakeCompoundExpr[$radical, LIST[[$radicand, radicand], [$n, n]]]]; }; <> 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]]]]; }; <> <<>> 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]]]]; }; <> wrongAtomValueType: PUBLIC ERROR = CODE; wrongBoxType: PUBLIC ERROR = CODE; badFormat: PUBLIC ERROR = CODE; <> DefineClasses: PROC [] ~ { <> cmr10, cmti10, cmmi10, cmex10, cmsy10: Style; integerClass, realClass, variableClass, plainSymClass, smallMathSymClass, bigMathSymClass, italSymClass, mathItalSymClass, lineClass, placeholderClass, spaceClass: AtomClass; sumClass, summationClass, fractionClass, integrationClass, differenceClass, powClass, eqFormulaClass, ltFormulaClass, leFormulaClass, geFormulaClass, gtFormulaClass, radicalClass, complexClass, productClass, orClass, notClass, negationClass, andClass, parenClass: CompoundClass; lbArg, ubArg, summandArg, llimArg, ulimArg, integrandArg, wrtArg, baseArg, exponentArg, numeratorArg, denominatorArg, nArg, radicandArg, multiplierArg, multiplicandArg, realPartArg, imaginaryPartArg, aParenArg: Argument; plusSym, sigmaSym, integralSym, dxSym, lineSym, radRootSym, radLineSym, iSym, leftParenSym, rightParenSym: Symbol; <> MathDB.ResetAtomClasses[]; MathDB.ResetCompoundClasses[]; <<>> <> 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) <> integerClass _ MakeAtomClass[$integer, atom, argument, cmr10, RopeBox, PaintRope, CvtRopeToRope]; realClass _ MakeAtomClass[$real, atom, argument, cmr10, RopeBox, PaintRope, CvtRopeToRope]; variableClass _ MakeAtomClass[$variable, atom, argument, cmti10, RopeBox, PaintRope, CvtRopeToRope]; plainSymClass _ MakeAtomClass[$plainSym, atom, symbol, cmr10, CharBox, PaintChar, CvtCharToRope]; bigMathSymClass _ MakeAtomClass[$bigMathSym, atom, symbol, cmex10, CharBox, PaintChar, CvtCharToRope]; smallMathSymClass _ MakeAtomClass[$smallMathSym, atom, symbol, cmsy10, CharBox, PaintChar, CvtCharToRope]; mathItalSymClass _ MakeAtomClass[$mathItalicSym, atom, symbol, cmmi10, CharBox, PaintChar, CvtCharToRope]; italSymClass _ MakeAtomClass[$italicSym, atom, symbol, cmti10, CharBox, PaintChar, CvtCharToRope]; lineClass _ MakeAtomClass[$line, atom, symbol, cmr10, LineBox, PaintLine, CvtOtherToRope]; placeholderClass _ MakeAtomClass[$placeholder, atom, placeholder, cmmi10, RopeBox, PaintRope, CvtRopeToRope]; spaceClass _ MakeAtomClass[$space, atom, symbol, cmr10, SpaceBox, PaintSpace, CvtSpaceToRope]; <> MathDB.InstallAtomClass[integerClass]; MathDB.InstallAtomClass[realClass]; MathDB.InstallAtomClass[variableClass]; MathDB.InstallAtomClass[plainSymClass]; MathDB.InstallAtomClass[italSymClass]; MathDB.InstallAtomClass[smallMathSymClass]; MathDB.InstallAtomClass[bigMathSymClass]; MathDB.InstallAtomClass[mathItalSymClass]; MathDB.InstallAtomClass[lineClass]; MathDB.InstallAtomClass[placeholderClass]; MathDB.InstallAtomClass[spaceClass]; <> 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['+]]; <> multiplierArg _ MakeArgument[$multiplier, LIST[$aliasA, $aliasHot], normal]; multiplicandArg _ MakeArgument[$multiplicand, LIST[$aliasB], normal]; <> lbArg _ MakeArgument[$lowerbound, NIL, script]; ubArg _ MakeArgument[$upperbound, NIL, script]; summandArg _ MakeArgument[$summand, LIST[$aliasHot], normal]; sigmaSym _ MakeSymbol[$sigma, LIST[$aliasOp], normal, MakeBigMathSym['\130]]; <> llimArg _ MakeArgument[$lowerlimit, NIL, script]; ulimArg _ MakeArgument[$upperlimit, NIL, script]; integrandArg _ MakeArgument[$integrand, LIST[$aliasHot], normal]; wrtArg _ MakeArgument[$wrt, NIL, script]; integralSym _ MakeSymbol[$integral, LIST[$aliasOp], normal, MakeBigMathSym['\132]]; dxSym _ MakeSymbol[$dx, NIL, script, MakeItalSym['d]]; <> baseArg _ MakeArgument[$base, LIST[$aliasA, $aliasHot], normal]; exponentArg _ MakeArgument[$exponent, LIST[$aliasB], script]; <> numeratorArg _ MakeArgument[$numerator, LIST[$aliasA, $aliasHot], normal]; denominatorArg _ MakeArgument[$denominator, LIST[$aliasB], normal]; lineSym _ MakeSymbol[$fractionBar, LIST[$aliasLine], normal, MakeLine[]]; <> 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[]]; <> aParenArg _ MakeArgument[$a, LIST[$aliasA, $aliasHot], normal]; leftParenSym _ MakeSymbol[$leftParen, NIL, normal, MakeBigMathSym['\040]]; rightParenSym _ MakeSymbol[$rightParen, NIL, normal, MakeBigMathSym['\041]]; <> <<>> <> sumClass _ MakeBinOpClass[$sum, $plus, $addend, $augend, MakePlainSym['+], "a + b", "$addend + $augend"]; differenceClass _ MakeBinOpClass[$difference, $minus, $subtrahend, $minuend, MakePlainSym['\173], "a - b", "$subtrahend - $minuend"]; 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"]; <> negationClass _ MakeUnaryOpClass[$negation, $minus, $a, MakePlainSym['-], "-a", "-$a"]; notClass _ MakeUnaryOpClass[$not, $notOp, $a, MakeSmallMathSym['\072], "~a", "~ $a"]; <> eqFormulaClass _ MakeRelationClass[$eqFormula, $equals, $lhs, $rhs, MakePlainSym['=], "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"]; <> complexClass _ MakeCompoundClass[$complex, other, "a + bi", LIST[realPartArg, imaginaryPartArg], LIST[iSym, plusSym], FixedSizeBoxRule, ComplexCompRule, "($a + $bi)"]; productClass _ MakeCompoundClass[$product, binaryOp, "a * b", LIST[multiplierArg, multiplicandArg], NIL, FixedSizeBoxRule, ProductCompRule, "$multiplier $multiplicand"]; summationClass _ MakeCompoundClass[$summation, op, "summation", LIST[lbArg, ubArg, summandArg], LIST[sigmaSym], FixedSizeBoxRule, SummationCompRule, "(summation ($lowerbound) ($upperbound) ($summand))"]; integrationClass _ MakeCompoundClass[$integration, op, "integration", LIST[llimArg, ulimArg, integrandArg, wrtArg], LIST[integralSym, dxSym], FixedSizeBoxRule, IntegrationCompRule, "(integral ($lowerlimit) ($upperlimit) ($integrand) ($wrt))"]; powClass _ MakeCompoundClass[$pow, other, "a^b", LIST[baseArg, exponentArg], NIL, FixedSizeBoxRule, PowCompRule, "$base^$exponent"]; parenClass _ MakeCompoundClass[$paren, paren, "( a )", LIST[aParenArg], LIST[leftParenSym, rightParenSym], ParenBoxRule, ParenCompRule, "( $a )"]; fractionClass _ MakeCompoundClass[$fraction, over, "a / b", LIST[numeratorArg, denominatorArg], LIST[lineSym], FractionBoxRule, FractionCompRule, "$numerator / $denominator"]; radicalClass _ MakeCompoundClass[$radical, radical, "radical", LIST[nArg, radicandArg], LIST[radRootSym, radLineSym], RadicalBoxRule, RadicalCompRule, "(root ($radicand) ($n))"]; <> <<>> <> MathDB.InstallCompoundClass[sumClass]; MathDB.InstallCompoundClass[differenceClass]; MathDB.InstallCompoundClass[andClass]; MathDB.InstallCompoundClass[orClass]; <> MathDB.InstallCompoundClass[notClass]; MathDB.InstallCompoundClass[negationClass]; <> MathDB.InstallCompoundClass[powClass]; MathDB.InstallCompoundClass[parenClass]; MathDB.InstallCompoundClass[complexClass]; MathDB.InstallCompoundClass[productClass]; MathDB.InstallCompoundClass[summationClass]; MathDB.InstallCompoundClass[integrationClass]; MathDB.InstallCompoundClass[fractionClass]; MathDB.InstallCompoundClass[radicalClass]; <> MathDB.InstallCompoundClass[eqFormulaClass]; MathDB.InstallCompoundClass[ltFormulaClass]; MathDB.InstallCompoundClass[leFormulaClass]; MathDB.InstallCompoundClass[gtFormulaClass]; MathDB.InstallCompoundClass[geFormulaClass]; }; <> DefineClasses[]; END.