This is a brief summary of MathSolver's syntax and capabilities as of September 11, 2000. Suggestions are always welcome. For further clarification, consult the example programs.
MathSolver is interpreted and uses Forth-like syntax.
This means it behaves much like a ``RPN'' calculater:
7 6 + printn
(13)
It handles rational and real numbers:
2 3 / 4 + dup print " = " (1.0) * printn
(14/3) = (4.666667)
More interesting, of course, are symbolic manipulations, like
cubing a polynomial:
(a+2b) dup dup * * printn
(1 a^3 + 6 a^2 b + 12 a b^2 + 8 b^3)
or taking the derivative of a rational expression:
(x^2 + y) (x + y^2) / &x Deriv Printn
( (-1 x^2 + -2 x y^2 + 1 y) / (1 x^2 + 2 x y^2 + 1 y^4) )
Here, the program's output of ``+ -'' where a simple ``- '' would do
is rather slovenly.
I'm still working on the software, but cosmetics have low priority.
(The mentioned problem is eliminated readily by running the standard
tool ``sed "ss+ -s- sg"'' as a postprocess.)
A MathSolver program is a list of tokens separated by white space. Two types of token (STRING and EXPRESSION) may have embedded white space (spaces or tabs) but neither may span multiple lines (have embedded line feeds). The string ``//'' is a comment delimiter and causes the remainder of a line to be ignored. Input is case-insensitive: ``Print'', ``print'', ``PRINT'' or even ``pRiNt'' all specify the same command token. Some command words have synonyms: ``Printn,'' for example, can be replaced with just ``?''. A MathSolver program is terminated by EOF, or with an explicit ``Exit'' token.
In addition to certain pre-defined command words, a token may be
At present, nothing can be done with STRINGs except to print them, so that's what is done: the data stack is not affected.
Input EXPRESSIONs use algebraic notation and are parsed by a separate routine. Each EXPRESSION is turned into a single internal node which is pushed onto the stack. Some expressions can be printed and handled internally, but must be input in a roundabout way. For example, the expression ((3+i)x) is a single term with a complex coefficient, but must be entered as two terms: ``(3x + ix)''.
An INTEGER, like ``17'', should be equivalent to the EXPRESSION ``(17)''. Rational numbers can be built from INTEGERS: ``0 5 - 7 /'' is equivalent to ``(-5/7)''.
A USER WORD can be set to any token and, when invoked, is equivalent to that token.
An exception is STRING: since these are currently never pushed onto the
stack, they cannot be popped off and assigned to a User Word.
The same effect can be achieved however:
{ "Greetings Galaxy!\n" } dup :sayhello :say
Here we've created a procedure which does nothing but print a greeting.
The above input, however, doesn't print the greeting, but just gives
the procedure a name.
(To illustrate the homogeneity of tokens, and the power of the ``dup''
command, we actually give the procedure two names.)
Later the program input:
sayhello sayhello
will produce the output:
Greetings Galaxy!
Greetings Galaxy!
The SET WORD syntax was illustrated in the preceeding example. The input ``7 :Cnt'' is equivalent to the C executable statement ``Cnt = 7;'' and ``Cnt 2 - :Cnt'' is equivalent to ``Cnt -= 2''. Here, ``Cnt'' is used as program variable, but these are not to be confused with the algebraic variables used by MathSolver when it takes derivatives, etc. (Often it may seem convenient to bind, or conceptually equate, an algebraic variable with a program variable of the same name, but this is just a user mnemonic: MathSolver treats the two as of independent name spaces.)
A user word must be SET (with a ``:'' token) before it can be referenced; it is the first such SET which adds the word to an internal lookup table. In some cases this will be counterintuitive: say you define a procedure which uses a program variable, then set the variable; then invoke the procedure. This will fail: you must provide a dummy SET prior to the procedure definition.
Algebraic VARIABLES in MathSolver take names like ``a'', ``x'', ``x_3'', or ``y_17''. There are 500 possible such variables: 25 letters (`a' - `z') and 20 subscripts (`_0' - `_19'). The letters are case-insensitive, and `c' is a synonym of `c_0' and so on. The letter `i' is reserved: it is not a variable, but rather the constant square root of -1.
An expression may consist of just a variable, eg. ``(x_4)'' but when a
MathSolver command requires specifically a variable, it must
be input not as an expression, but specially, eg. ``&x_4''.
For example, the following replaces ``b'' with ``c + 2'' in an expression,
followed by the substitution ``c + 2i'':
(b^3 + b) dup dup ? (c + 2) &b substit ? (c + 2i) &b substit ?
(1 b^3 + 1 b)
(1 c^3 + 6 c^2 + 13 c + 10)
(1 c^3 + (0.000+6.000i) c^2 + -11.000 c + (0.000-6.000i))
(Note that, at present, MathSolver forces complex numbers into
floating-point: I've been too lazy to add rational number support there.)
Finally, PROCEDUREs may be the most confusing part of MathSolver
syntax.
They can be given names:
{ whatever ... "Greetings Galaxy!\n" } :sayhello
executed if an expression is constant and positive:
{ whatever ... "Greetings Galaxy!\n" } Progvar If
or executed repeatedly as long as a popped expression
is constant and positive:
{ whatever ... "Greetings Galaxy!\n" Progvar } Untilneg
Since the name of a procedure is executed rather than pushed onto the stack,
it cannot be used with ``If'' or ``Untilneg'' unless encapsulated in
another procedure, eg. as:
{ whatever } :Foo { Foo Progname } Untilneg
The usage of ``If'' and ``Untilneg'' is very clumsy, and I'd
be happy to hear suggestions for improvement.
Do not confuse algebraic variables with user words (``program variables''). At present there is no way to bind an algebraic variable to a value, but any instance can be set with the ``Substit'' command.
In the following ``constant'' refers to an expression with no algebraic variable.