CUPL/CORC implementation for the edification of historians and
students of programming-language design. CUPL and CORC were
representative of a significant class of teaching languages in its
-period, and study of the design casts a clear light on the
-preoccupations of its time.
+period, and study of their design casts a clear light on the
+preoccupations of their time.
.P
.H 1 "The CUPL and CORC Languages"
.P
execution trace is displayed as the parse tree is printed. At level
4, each token intern and cons-cell allocation during parsing is also
dumped.
+.P
+.H 1 "Unix Implementation Notes."
+.P
+The CUPL/CORC implementation is built around YACC and LEX. The rest is
+ANSI and POSIX-conformant C.
+.P
+The YACC grammar just builds a parse tree, which is passed to
+interpret() for interpretation. This method requires that all
+programs are always small enough that the entire tree can be held
+in memory, but it has the advantage that front and back end are very
+well separated. It is a winning strategy on virtual-memory systems.
+.P
+One hack that greatly simplifies the grammar productions is that the
+lexer actually returns parse tree nodes, even for atoms like
+identifiers, strings, and numbers. In fact, the lexical analyzer even
+does label and variable name resolution with the same simple piece of
+code; each IDENTIFIER token is looked up in the identifier list when
+it's recognized, so the parse tree early becomes a DAG. (The -v1 option
+causes the compiler to dump its parse tree for inspection.)
+.P
+Most of the smarts are in interpret() and its sub-functions. Because
+array variables can be re-allocated, the internals have to use a
+dynamic vector/array type with its own indexing machinery. The code
+to manipulate this type lives in monitor.c.
+.P
+Note that much of this machinery is quite generic and could be re-used
+for other languages with little change.
+.P
+The implementation trades away some possible efficiencies for
+simplicity. Most importantly, each value has an attached malloc
+object to hold its elements, even when there is only one such element
+(as for scalars) which could reasonably be represented by a static
+field.
+.P
+There are some comments in the code which discuss the possibility of
+a back end that would emit C. This would be easy to do if there were
+any serious corpus of CUPL/CORC code demanding to be translated. The
+compiler back end would emit code shaped like the parse tree, which
+would then link monitor.c as runtime support.
+.P
+The only nontrivial difference between CUPL and CORC is the interpretation
+of GO TO <label> when <label> is associated with a block. In CUPL, this
+is a go to beginning of block; in CORC, it's go to end of block (which in
+CUPL is GO TO <block> END. The interpreter sets a flag when it sees any
+of the appropriate CORC-specific keywords (NOTE, BEGIN, DEC, DECREASE, EQL,
+GEQ, GTR, INC, INCREASE, INT, LEQ, LSS, NEQ, REPEAT, TITLE, UNTIL, $) during
+lexing, and execute() modifies its behavior appropriately.
+