.CH "The 'Drift' Compiler"
.MH "The 'Drift' Language"
.SH "Description"
'Drift' is an extremely simplified programming language for
computers with Von Neumann-style architectures.
While too restrictive to be generally useful, it does have a few
interesting features.
It is an expression-oriented language rather than statement-oriented;
non-declarative constructs generally yield a value of some sort.
The syntax is intended to be conducive to simple error recovery
schemes (particularly to panic-mode symbol skipping) while retaining
a reasonable degree of cleanliness and human engineering (for
example, statements are terminated by end-of-line, rather than some
delimiter like a semicolon; continuations across lines are represented
explicitly by an '&').
The semantics of the language closely reflect the expression-oriented
semantics of the VCG itself.
.pp
'Drift' programs are composed of variable declarations, function
declarations, and expressions.
Variables may be global in scope or restricted to the function in
which they are declared.
Function declarations may not be nested.
All variables represent floating point quantities; all functions
return floating point quantities.
The return value of a function is the return value of the last
expression in the expression series that comprises its body.
Functions may be recursive and need not be defined before use.
The function named 'main' is assumed to be the main program, and
will be invoked by whatever environment supports 'drift' programs.
.pp
Expressions are made of the four standard operators (+, -, *, /),
assignment ('=', treated uniformly as an arithmetic operator yielding
the value of its right-hand-side),
two-way selection ('if'), and a loop ('while').
Variables in expressions yield their values (or take on new ones if
used as the left operand of an assignment operator).
They must be declared before they are used.
Function calls in expressions cause parameters to be passed by value
to the named function;
the value returned by the function then takes the place of the call
in the expression.
The quad ('#') is a pseudovariable used for input/output.
When used in the right-hand-side of an assignment, it causes input
of a floating point value from standard input;
when used in the left-hand-side, it causes output of the right-hand-side
to standard output.
.SH "BNF"
The syntax of 'drift' presented below employs the extended BNF used
throughout the Software Tools Subsystem documentation.
Alternatives enclosed in curly braces {} may be repeated any number
of times, including zero.
Alternatives enclosed in square brackets @[] may be used once
or not at all.
.sp 2
.nf
program ->
   newlines {declaration newlines} eof

declaration ->
      global_variable_declaration
   |  function_declaration

global_variable_declaration ->
   'float' identifier {',' newlines identifier}

identifier ->
   letter {letter | digit | '_'}

newlines ->
   {NEWLINE}

function_declaration ->
   'function' identifier '(' formal_parameters ')' newlines
      {local_variable_declaration newlines}
      series newlines
   'end_function'

formal_parameters ->
   [identifier {',' newlines identifier}]

local_variable_declaration ->
   'float' identifier {',' newlines identifier}

series ->
   expression newlines {expression newlines}

expression ->
   sum {'=' sum}

sum ->
   term {('+' | '-') term}

term ->
   primary {('*' | '/') primary}

primary ->
      '#'
   |  'null'
   |  number
   |  identifier
   |  identifier '(' actual_parameters ')'
   |  loop
   |  conditional
   |  '(' series ')'

loop ->
   'while' newlines series newlines
      'do' newlines
      series newlines
      'od'

conditional ->
   'if' newlines series newlines
   'then' newlines series newlines
   ['else' newlines series newlines]
   'fi'

actual_parameters ->
   [series {',' newlines series}]
.fi
.SH "Examples"
The following programs compute the value of a base raised to a positive
integer exponent.
The first is iterative, while the second is recursive.
.sp 2
.nf
-- A sample program in 'drift'

   float x, y

   function power (base, exponent)

      float result

      result = 1
      while exponent       -- that is, while exponent <> 0
         do
         result = result * base
         exponent = exponent - 1
         od

      result
   end_function

   function main ()
      x = #
      y = #
      # = power (x, y)
   end_function
.sp 5
-- The same sample, only done recursively

   float x, y

   function power (base, exponent)
      if exponent
      then base * power (base, exponent - 1)
      else 1
      fi
   end_function

   function main ()
      x = #
      y = #
      # = power (x, y)
   end_function
.fi
.MH "The Compiler"
The 'drift' compiler was implemented in Ratfor under the Software Tools
Subsystem in about two man-days.
Conceptually, it generates intermediate form code for the VCG in two passes:
the first (lexical and syntactic) generates an internal form used only
by the front end, while the second (semantic) does semantic checking and
converts the internal form to IMF.
.pp
The lexical analyzer used in the compiler is a fairly standard one
employed in a number of Software Tools Subsystem programs because of
its compactness and high speed.
It resides almost entirely in the subroutine 'getsym'.
.pp
The parser code is input to 'stacc', a recursive-descent parser
generator that is part of the Software Tools package.
The production for 'program' is actually the main routine of the
compiler.
Note that very little attempt is made to recover from syntactic errors;
the purpose of the compiler is the demonstration of code generation,
not parsing.
The parser drives the compilation process, making calls on the lexical
analyzer and internal form code generation routines as necessary.
.pp
The IMF generation process is concentrated in the subroutine
'semantic_analysis' and its descendents.
This routine invokes 'void_context', 'lvalue_context', and
'rvalue_context' to propagate contextual information during a
traversal of the internal form tree.
The bulk of the IMF generation takes place in 'rvalue_context',
since most operators yield floating point values.
Special cases are handled in the other two contexts:
left-hand-sides of assignments by 'lvalue_context' and constructs
that don't yield values by 'void_context'.
Since the internal form is tree structured, the translation to IMF
is straightforward.
.SH "Global Variable Definitions"
.nf
.ti
.so =doc=/guide/vcg/drift_com.r.i
.SH "Parser Source Code"
.nf
.ti
.so =doc=/guide/vcg/drift.stacc
.SH "Remainder of Compiler Source Code"
.nf
.ti
.so =doc=/guide/vcg/drift.r
.SH "Run-Time Support Routines Source Code"
.nf
.ti
.so =doc=/guide/vcg/drift_lib.s
.EV
.fo //- # -//
