








     HHoocc  --  AAnn IInntteerraaccttiivvee LLaanngguuaaggee FFoorr FFllooaattiinngg PPooiinntt
                         AArriitthhmmeettiicc

                      _B_r_i_a_n _K_e_r_n_i_g_h_a_n
                          _R_o_b _P_i_k_e


                          _A_B_S_T_R_A_C_T

          _H_o_c is a simple programmable interpreter  for
     floating  point  expressions.  It has C-style con-
     trol  flow,  function  definition  and  the  usual
     numerical  built-in  functions  such as cosine and
     logarithm.


11..  EExxpprreessssiioonnss

     _H_o_c is an expression language, much  like  C:  although
there  are  several control-flow statements, most statements
such as assignments are expressions whose  value  is  disre-
garded.   For example, the assignment operator = assigns the
value of its right operand to its left operand,  and  yields
the  value,  so  multiple  assignments work.  The expression
grammar is:

     _e_x_p_r_:          _n_u_m_b_e_r
          _|    _v_a_r_i_a_b_l_e
          _|    _( _e_x_p_r _)
          _|    _e_x_p_r _b_i_n_o_p _e_x_p_r
          _|    _u_n_o_p _e_x_p_r
          _|    _f_u_n_c_t_i_o_n _( _a_r_g_u_m_e_n_t_s _)

Numbers are floating point.  The input format is that recog-
nized  by  _s_c_a_n_f(3):  digits, decimal point, digits, _e or _E,
signed exponent.  At least one digit or a decimal point must
be present; the other components are optional.

     Variable  names  are formed from a letter followed by a
string of letters and numbers.  _b_i_n_o_p refers to binary oper-
ators such as addition or logical comparison; _u_n_o_p refers to
the two negation operators, `!'  (logical  negation,  `not')
and  `-'  (arithmetic negation, sign change).  Table 1 lists
the operators.
















                             -2-


 +---------------------------------------------------------+
 | TTaabbllee 11::  Operators, in decreasing order of precedence  |
 |^       exponentiation (FORTRAN **), right associative   |
 |! -     (unary) logical and arithmetic negation          |
 |* /     multiplication, division                         |
 |+ -     addition, subtraction                            |
 |> >=    relational operators: greater, greater or equal, |
 |< <=      less, less or equal,                           |
 |== !=     equal, not equal (all same precedence)         |
 |&&      logical AND (both operands always evaluated)     |
 |||      logical OR (both operands always evaluated)      |
 |=       assignment, right associative                    |
 +---------------------------------------------------------+

     Functions, as described later, may be  defined  by  the
user.   Function arguments are expressions separated by com-
mas.  There are also a number of built-in functions, all  of
which take a single argument, described in Table 2.

   +-----------------------------------------------------+
   |            TTaabbllee 22::  Built-in Functions             |
   |abs(x)     |_x|, absolute value of _x                  |
   |atan(x)    arc tangent of _x                          |
   |cos(x)     cos(_x), cosine of _x                       |
   |exp(x)     _e_x, exponential of _x                      |
   |int(x)     integer part of _x, truncated towards zero |
   |log(x)     log(_x), logarithm base _e of _x             |
   |log10(x)   log10(_x), logarithm base 10 of _x          |
   |sin(x)     sin(_x), sine of _x                         |
   |sqrt(x)    _x, _x12__                                     |
   +-----------------------------------------------------+

     Logical  expressions  have  value  1.0  (true)  and 0.0
(false).  As in C, any non-zero value is taken to  be  true.
As  is always the case with floating point numbers, equality
comparisons are inherently suspect.

     _H_o_c also has a few built-in constants, shown  in  Table
3.

+-------------------------------------------------------------------+
|                   TTaabbllee 33::  Built-in Constants                    |
|DEG     57.29577951308232087680   180/, degrees per radian         |
|E        2.71828182845904523536   _e, base of natural logarithms    |
|GAMMA    0.57721566490153286060   , Euler-Mascheroni constant      |
|PHI      1.61803398874989484820   (5+1)/2, the golden ratio        |
|PI       3.14159265358979323846   , circular transcendental number |
+-------------------------------------------------------------------+

22..  SSttaatteemmeennttss aanndd CCoonnttrrooll FFllooww

     _H_o_c statements have the following grammar:











                             -3-


     _s_t_m_t_:          _e_x_p_r
          _|    _v_a_r_i_a_b_l_e _= _e_x_p_r
          _|    _p_r_o_c_e_d_u_r_e _( _a_r_g_l_i_s_t _)
          _|    _w_h_i_l_e _( _e_x_p_r _) _s_t_m_t
          _|    _i_f _( _e_x_p_r _) _s_t_m_t
          _|    _i_f _( _e_x_p_r _) _s_t_m_t _e_l_s_e _s_t_m_t
          _|    _{ _s_t_m_t_l_i_s_t _}
          _|    _p_r_i_n_t _e_x_p_r_-_l_i_s_t
          _|    _r_e_t_u_r_n _o_p_t_i_o_n_a_l_-_e_x_p_r

     _s_t_m_t_l_i_s_t_:      (nothing)
          _|    _s_t_m_l_i_s_t _s_t_m_t

An  assignment  is  parsed  by default as a statement rather
than an expression, so assignments  typed  interactively  do
not print their value.

     Note that semicolons are not special to _h_o_c: statements
are terminated  by  newlines.   This  causes  some  peculiar
behavior.  The following are legal statements:

     if (x < 0) print(y) else print(z)

     if (x < 0) {
          print(y)
     } else {
          print(z)
     }

In the second example, the braces are mandatory: the newline
after the _i_f would terminate the  statement  and  produce  a
syntax error were the brace omitted.

     The syntax and semantics of _h_o_c control flow facilities
are basically the same as in C.  The _w_h_i_l_e and _i_f statements
are  just  as  in  C,  except there are no _b_r_e_a_k or _c_o_n_t_i_n_u_e
statements.

33..  IInnppuutt aanndd OOuuttppuutt:: _r_e_a_d aanndd _p_r_i_n_t

     The input function  _r_e_a_d,  like  the  other  built-ins,
takes  a single argument.  Unlike the built-ins, though, the
argument is not an expression: it is the name of a variable.
The next number (as defined above) is read from the standard
input and assigned to the named variable.  The return  value
of  _r_e_a_d  is  1 (true) if a value was read, and 0 (false) if
_r_e_a_d encountered end of file or an error.

     Output is generated  with  the  _p_r_i_n_t  statement.   The
arguments to _p_r_i_n_t are a comma-separated list of expressions
and strings in double quotes, as in  C.   Newlines  must  be
supplied; they are never provided automatically by _p_r_i_n_t.











                             -4-


     Note  that  _r_e_a_d  is  a  special built-in function, and
therefore takes a single parenthesized argument, while _p_r_i_n_t
is a statement that takes a comma-separated, unparenthesized
list:

     while (read(x)) {
          print "value is ", x, "\n"
     }


44..  FFuunnccttiioonnss aanndd PPrroocceedduurreess

     Functions and procedures are distinct in _h_o_c,  although
they are defined by the same mechanism.  This distinction is
simply for run-time error checking: it is  an  error  for  a
procedure  to  return  a  value,  and  for a function _n_o_t to
return one.

     The definition syntax is:

     _f_u_n_c_t_i_o_n_: _f_u_n_c _n_a_m_e_(_) _s_t_m_t

     _p_r_o_c_e_d_u_r_e_:_p_r_o_c _n_a_m_e_(_) _s_t_m_t

_n_a_m_e may be the name of any variable --  built-in  functions
are  excluded.   The  definition, up to the opening brace or
statement, must be on one line, as with  the  _i_f  statements
above.

     Unlike  C,  the  body of a function or procedure may be
any statement, not necessarily a  compound  (brace-enclosed)
statement.   Since semicolons have no meaning in _h_o_c, a null
procedure body is formed by an empty pair of braces.

     Functions and procedures may take arguments,  separated
by  commas,  when  invoked.  Arguments are referred to as in
the shell: refers to the third (1-indexed)  argument.   They
are  passed  by  value and within functions are semantically
equivalent to variables.  It is an  error  to  refer  to  an
argument  numbered  greater  than  the  number  of arguments
passed to the routine. The error checking  is  done  dynami-
cally,  however,  so  a routine may have variable numbers of
arguments if initial arguments affect the  number  of  argu-
ments to be referenced (as in C's _p_r_i_n_t_f).



















                             -5-


     Functions and procedures may recurse, but the stack has
limited depth (about a hundred calls).  The following  shows
a _h_o_c definition of Ackermann's function:

     $ hoc
     func ack() {
             if ($1 == 0) return $2+1
             if ($2 == 0) return ack($1-1, 1)
             return ack($1-1, ack($1, $2-1))
     }
     ack(3, 2)
             29
     ack(3, 3)
             61
     ack(3, 4)
     hoc: stack too deep near line 8
     ...


55..  EExxaammpplleess

     Stirling's formula:

                     _n!~2_n(_n/_e)_n(1+1__12___n__)


     $ hoc
     func stirl() {
         return sqrt(2*$1*PI) * ($1/E)^$1*(1 + 1/(12*$1))
     }
     stirl(10)
             3628684.7
     stirl(20)
             2.4328818e+18


     Factorial function, _n!:

     func fac() if ($1 <= 0) return 1 else return $1 * fac($1-1)


     Ratio of factorial to Stirling approximation:





















                             -6-


     i = 9
     while ((i = i+1) <= 20) {
             print i, "  ", fac(i)/stirl(i), "\n"
     }
     10   1.0000318
     11   1.0000265
     12   1.0000224
     13   1.0000192
     14   1.0000166
     15   1.0000146
     16   1.0000128
     17   1.0000114
     18   1.0000102
     19   1.0000092
     20   1.0000083













































