falcon picture


The Falcon Programming Language

Part of the documentation for the Falcon language
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science



Falcon was designed in a hurry in late 2012, for use in a compiler construction course in the spring of 2013. The experience of teaching that course uncovered a number of errors in the language design, to nobody's surprise.

Lexical Errors

The Falcon notation for nonprintable characters "Hello world!\LF NUL\" added what appeared to be gratuitous complexity to the lexical analyzer, including the need for a secondary symbol table of named characters.

No mod operator was specified. This is a simple oversight.

Use of backslash in the multiple character and /\ and or \/ operators is not pretty because the interpretation of backslash as a special quote character by Unix utilities is so pervasive.

Syntactic Errors

The decision to use Pascal-style const, type and var sections in a block leads to an unnecessarily ornate parser. The relation between the abstract syntax (and the semantics) of a block and the surface syntax would have been far more obvious if declarations had all begun as declarations, and only after the identifier being declared is named is it determined whether it is a type, variable or constant declaration.

Also, the pretty-printing rules for the declaration format chosen are far from obvious, and this is made worse by the presence of a code keyword.

Procedure and function definitions don't permit a semicolon after the parameter list or return type definition and before the body. Those used to typing semicolons are going to type one here very frequently.

Actual parameter lists are syntactically indistinguishable from constructors and should be merged in the syntax. The distinction between the two concepts is entirely semantic.

Semantic Errors

The decision not to use null-terminated strings in Falcon made writing the lexical analyzer a bit ugly because of the deeply ingrained habits of C programming.

The statement "functions may only be called from within expressions" is too restrictive. We need to be able to call functions within references so that functions can return pointers to which assignments are done.

The design decision to avoid a return keyword and instead use assignment to the function name to set the return value worked well in Pascal, but it clashes with the decision to allow function calls within a reference, combined with the decision to use the same bracketing for parameter lists as is used for array subscripts. Consider this example:

type r = range 0..1;
type a = array r of @r;
var  ob: @r;
function trouble( arg:r ): @a
     trouble(1) = ob;    -- (a)
     trouble(1)(1)@ = 1; -- (b)

Line (a) above sets one element of the array returned by trouble, while line (b) above makes a recursive call to trouble and then assigns to the object pointed to by an element of the array returned by that call. This is not at all obvious to the human reader, and it is difficult for the compiler, requiring the deferral of interpretation until long after the code has been read.

Exception handlers cannot re-raise the exception that evoked the handler. This is a problem in handlers that handle multiple exceptions and in generic else handlers. (If a handler just handles one particular exception, then it is easy to re-raise that exception.)