Man Linux: Main Page and Category List

NAME

       nickle - a desk calculator language

SYNOPSIS

       nickle  [--help|--usage]  [-f  file]  [-l library] [-e expr] [ script ]
       [--] [arg ...]

DESCRIPTION

       Nickle is a desk calculator  language  with  powerful  programming  and
       scripting  capabilities.   Nickle  supports  a  variety  of  datatypes,
       especially  arbitrary  precision  integers,  rationals,  and  imprecise
       reals.  The input language vaguely resembles C.  Some things in C which
       do not translate easily are different, some design  choices  have  been
       made differently, and a very few features are simply missing.

USAGE

       An  un-flagged  argument  is  treated  as a Nickle script, and replaces
       standard input.  Any  remaining  arguments  following  the  script  are
       placed  in  the  Nickle  string array argv for programmatic inspection.
       When invoked without an expression or  script  argument,  Nickle  reads
       from standard input, and writes to standard output.

       Options are as follows:

       --help,--usage
              Print a help/usage message and exit.  This is a built-in feature
              of Nickle’s ParseArgs module, and thus  will  also  be  true  of
              Nickle scripts that use this library.

       -f,--file file
              Load file into Nickle before beginning execution.

       -l,--library library
              Load  library into Nickle before beginning execution.  See below
              for a description of the library facility.

       -e,--expr expr
              Evaluate expr before beginning execution.

       --     Quit parsing arguments and pass the remainder,  unevaluated,  to
              argv.

SYNTAX

       To  make  the  input  language  more  useful in an interactive setting,
       newline only terminates statements at  ‘‘reasonable’’  times.   Newline
       terminates  either  expressions  or single statements typed by the user
       (with the exception  of  a  few  statements  which  require  lookahead:
       notably  if()  and  twixt(),  which have an optional else part). Inside
       compound statements  or  function  definitions,  only  a  ;  terminates
       statements.   This  approach is convenient and does not appear to cause
       problems in normal use.

       The syntax of Nickle programs is as follows.  In this description, name
       denotes  any  sequence of letters, digits and _ characters not starting
       with a digit; E denotes any expression; S denotes any statement; and  T
       denotes  any  type.   The  syntax  X,X,...,X denotes one or more comma-
       separated Xs, unless otherwise indicated.

       Comments:

       C-style comments are enclosed in /* and */,  and  shell-style  comments
       are denoted by a leading # at the start of a line.

       Operands:

       real number
              Can  include  exponent,  need not include decimal point or sign.
              Will be treated as exact rationals.  If a trailing decimal  part
              contains  an opening curly brace, the brace is silently ignored;
              if it contains a curly-bracketed trailing portion, it is treated
              as   a  repeating  decimal.   ‘Floating  point’’  constants  are
              currently represented  internally  as  rationals:  for  floating
              constants  with  a  given  precision  (and an infinite-precision
              exponent), use the imprecise() builtin function described below.

       octal number
              Start with a 0 (e.g., 014 is the same as 12).

       hexidecimal number
              Start with "0x" (e.g., 0x1a is the same as 26).

       string As  in  C.   String  constants  are surrounded by double-quotes.
              Backslashed  characters  (including  double-quotes)  stand   for
              themselves,  except  "\n"  stands for newline, "\r" for carriage
              return, "\b" for backspace, "\t" for tab and "\f" for  formfeed.

       name   A variable reference.

       name() name(E,E,...,E)
              A  function  call  with  zero  or more arguments.  Functions are
              fully call-by-value: arrays and  structures  are  copied  rather
              than being referenced as in C.

       desc name  T name = value
              Definition  expressions:  a new name is made available, with the
              value of the definition being the value of  the  initializer  in
              the  second  form,  and  uninitialized  in  the first form.  The
              descriptor desc is not optional: it consists of any  combination
              of  visibility,  storage  class  or  type  (in that order).  See
              QUALIFIERS  immediately  below  for  a  description   of   these
              qualifiers.  A structured value expression is also possible: see
              VALUES below.

              In addition to being able to  initialize  a  definition  with  a
              Nickle  value,  C-style  array, structure, and union definitions
              are also allowed: For example, the following
                int[*,*] name = {{0,1},{2,3}}
                int[2,2] name = {{0...}...}
              are permitted with the obvious semantics.  This is  the  context
              in  which  the  dimensions in a type may be expressions: see the
              discussion of array types above.  See the  discussion  of  array
              and structure values for array and structure initializer syntax.

QUALIFIERS

       A declaration or definition may be qualified,  as  in  C,  to  indicate
       details of programmatic behavior.  Unlike in C, these qualifiers, while
       optional, must appear in the given order.

       Visibility:

       public Any  definition  expression   (function   definition,   variable
              definition,  type  definition)  can  be qualified with public to
              indicate that the name being defined should be  visible  outside
              the  current  namespace,  and  should be automatically imported.
              See Namespaces below for further info.

       protected
              Any  definition  expression   (function   definition,   variable
              definition,  type definition) can be qualified with protected to
              indicate that the name being defined should be  visible  outside
              the  current  namespace,  but  should  not  be made available by
              import declarations.  See Namespaces below for further info.

       Lifetime:

       auto   An auto object is local to a particular block: its  lifetime  is
              at  least  the  lifetime  of that block.  An auto object with an
              initializer will be re-initialized each time  it  is  evaluated.
              This is the default lifetime for local objects.

       static A  static  object  is local to a particular function definition:
              its lifetime is at least the lifetime of that definition.  A new
              static  object  will be created each time its enclosing function
              definition is evaluated.

              In Nickle, the keyword static has to do only with lifetime (like
              the  use  of  static  inside  C  functions), not with visibility
              (which is handled by separate qualifiers as described above, not
              like the use of static in global scope in C).

       global A global object is global to the entire program: its lifetime is
              the lifetime of the program.  A global object  will  be  created
              and  initialized when its definition is first seen.  This is the
              default lifetime for global objects.

              The distinction between static and global lifetime in Nickle  is
              not  possible  in  C,  because  C  functions are not first class
              objects with nested scope.  When deciding  which  to  use  in  a
              Nickle  program,  think about what should happen if a definition
              is re-evaluated.

OPERATORS

       Here are the basic Nickle operators, grouped  in  order  of  decreasing
       precedence:

       A[E,E,...,E]
              Refers  to  the  E’th  element of the array expression A, or the
              E1’th/E2’th/etc element  of  a  multi-dimensional  array.   Both
              arrays  of arrays ala C and multidimensional arrays ala NAWK are
              possible.

       struct.tag
              Structure dereference.

       struct->tag
              Structure pointer dereference ala C.

       =============

       ++ --  Unary increment/decrement. May be either postfix or prefix.

       -      Unary negate

       ! E    Logical negation.

       E !    Factorial.  Requires a non-negative integer argument.

       * E    Pointer dereference.

       & E    Reference construction.

       =============

       (U) E  Construct a value of union type with tag U and value E.

       =============

       **     Exponentiation. Both  operands  may  be  fractional.   The  left
              operand  must  be  non-negative  unless  the  right  operand  is
              integer.  The result type is the type of the left operand if the
              right operand is integer, and real otherwise.

              This  is  the  only  known  type-unsound  feature  of Nickle: an
              expression like 2 ** -3 will statically be of type integer,  but
              dynamically  will  generate a rational result.  This may cause a
              runtime type error later on: consider
                int x = 2 ** -3;

       =============

       * / // %
              Times, divide, integer divide, and remainder.  The right operand
              of the last three operators must be nonzero.  The result type of
              the division operator will always  be  at  least  rational:  the
              result type of the integer division operator will always be int.
              This is a notable departure from C, where  integer  division  is
              implied by integer operands.  Integer division is defined by
                x // y == y > 0 ? floor (x / y) : ceil(x / y)
              The remainder is always non-negative and is defined by: by
                x % y = x - (x // y) * y

       =============

       + -    Addition and subtraction.

       =============

       << >>  Bitwise  left  and  right shift with integer operands.  Negative
              right operands work as expected.  These operators are defined by
                x << y = x * 2 ** y
                x >> y = x // 2 ** y
              Another  way  to look at this is that negative left operands are
              considered to be in an infinite  twos-complement  representation
              (i.e.,  sign-extended  to  infinity),  with  right  shift  sign-
              extending its left operand.

       =============

       <= >= < >
              Relational operators.

       =============

       == !=  Equality operators.

       =============
              Finally, in order of decreasing precedence:

       &      Bitwise AND.  Negative operands  are  considered  to  be  in  an
              infinite  twos-complement representation (i.e., sign-extended to
              infinity).

       ^      Bitwise XOR.  Negative operands as in bitwise AND.

       |      Bitwise OR.  Negative operands as in bitwise AND.

       &&     Short-circuit logical AND.

       ||     Short-circuit logical OR.

       E ? E : E
              Conditional expression: if first  expression  is  logical  true,
              value is second expression, else third.

       fork E Create (and return) a thread.  See Thread below for details.

       = += -= *= /= //= %= **= <<= >>= ^= &= |=
              Assignment  operators.   Left-hand-side  must  be assignable.  x
              <op>= y is equivalent to x = x <op> y

       E , E  Returns right-hand expression.

TYPES

       The type declaration syntax  of  Nickle  more  strongly  resembles  the
       ‘‘left’’  variant of the Java syntax than the C syntax.  Essentially, a
       type consists of:

       poly integer rational real string continuation void
              A base type of the language.  Type void is actually only  usable
              in  certain contexts, notably function returns.  It is currently
              implemented as a ‘‘unit’’ type ala ML,  and  thus  has  slightly
              different behavior than in C.  Type poly is the supertype of all
              other types (i.e.,  it  can  be  used  to  inhibit  static  type
              checking),  and  is  the default type in most situations where a
              type need not appear.

       file semaphore thread
              Also builtin base types, but integral to  the  File  and  Thread
              ADTs: see below.

       More About Types:

       Nickle  supports polymorphic data: As an expresion is evaluated, a data
       type is chosen to fit the result.  Any Nickle object may be  statically
       typed,  in  which  case  bounds violations will be flagged as errors at
       compile  time.   Polymorphic  variables  and  functions  do  not  place
       restrictions  on  the  assigned data type; this is the default type for
       all objects.

       poly   This describes the union of all datatypes.  A variable with this
              type can contain any data value.

       int    Arbitrary precision integers.

       rational
              Arbitrary precision rational numbers.

       real   Arbitrary  exponent  precision  floating point numbers.  As many
              computations cannot be carried out exactly as rational  numbers,
              Nickle  implements non-precise arithmetic using its own machine-
              independent representation  for  floating  point  numbers.   The
              builtin  function  imprecise(n) generates a real number with 256
              bits of  precision  from  the  number  n,  while  imprecise(n,p)
              generates a real number with p bits of precision.

       T[]    An  array  of  type  T, of one or more dimensions.  There are no
              zero-dimensional arrays in Nickle.

       T[*]   A one-dimensional array of type T.  Unlike in C,  the  dimension
              of  an  array  is  never  part  of its type in Nickle.  Further,
              arrays and pointers are unrelated types in Nickle.

       T[*,*,...,*]
              A two or more dimensional array of type T.  The stars ‘‘*’’  are
              not optional.  As the previous paragraphs make clear, ‘‘T[]’’ is
              not a zero-dimensional array.

       T[E,E,...,E]
              In definition contexts, integer values may  be  given  for  each
              dimension  of  an  array context.  These are strictly for value-
              creation purposes, and are not part of the type.  An array  type
              is  determined only by the base type and number of dimensions of
              the array.

       T0() T0(T,T,...,T)
              A function returning type T0.  A  function  accepts  0  or  more
              arguments.

       T0() T0(T,T,...,T ...)
              A  function  accepting  zero or more required arguments, plus an
              arbitrary number of optional arguments.  The second sequence  of
              three  dots  (ellipsis)  is  syntax,  not  metasyntax:  see  the
              description of varargs functions for details.

       *T     A pointer to a location of type T.  Pointer arithmetic in Nickle
              operates  only  upon  pointers to arrays: the pointer must be of
              the correct type, and may never stray out of bounds.  A  pointer
              may  either point to some location or be null (0).  As in C, the
              precedence of ‘‘*’’ is lower than the precedence  of  ‘‘[]’’  or
              ‘‘()’’: use parenthesis as needed.

       struct {T name; T name; ...}
              A structure with fields of the given name and type.  The types T
              are optional: in their absence, the type of the field is poly.

       union {T name; T name; ...}
              A ‘‘disjoint union’’ of the given types.  This is more like  the
              variant  record  type of Pascal or the datatype of ML than the C
              union type: the names are tags of the given type, exactly one of
              which applies to a given value at a given time.

       (T)    Parentheses for grouping.

       Typedef:

       As in C, new type names may be created with the typedef statement.  The
       syntax is
         typedef T typename;
       where T is a Nickle type.  The resulting typename may be used  anywhere
       a type is expected.

VALUES

       Values of the base types of Nickle are as expected.  See the syntax for
       constants above.  Values of type file, semaphore, and continuation  may
       currently  be  created  only  by  calls to builtin functions: no Nickle
       constants of these types exist.

       As noted in TYPES above,  Nickle  has  several  kinds  of  ‘‘structured
       value’’:  arrays,  functions, pointers, structures and disjoint unions.
       All of these have some common properties.  When  created,  all  of  the
       component   values  are  uninitialized  (unless  otherwise  specified).
       Attempts to use an uninitialized value will result in either a compile-
       time error or a runtime exception.

       Arrays:

       [E]    creates  a  (zero-based)  array with E elements.  E must be non-
              negative.

       [E]{V,V,...,V}
              Creates an array with E elements, initialized  to  the  Vs.   If
              there  are  too few initializers, remaining elements will remain
              uninitialized.

       [E]{V,V,...,V...}
              The second ellipsis (three  dots)  is  syntax,  not  metasyntax.
              Create  an  array  with  E  elements.  The first elements in the
              array  will  be  initialized  according  to  the  Vs,  with  any
              remaining elements receiving the same value as the last V.  This
              syntax may be used in the obvious fashion with any of the  array
              initializers below.

       [*]{V,V,...,V}
              Creates  an  initialized  array with exactly as many elements as
              initializers.  There must be at least one initializer.

       [E,E,...,E] [*,*,...,*]
              Creates multidimensional arrays.  Integer expressions   and  "*"
              cannot  be  mixed:  an  array’s  dimensions  are entirely either
              specified or unspecified by the definition.   These  arrays  may
              also  be created initialized: see next paragraph for initializer
              syntax.

       (T[E]) (T[E,E,...,E]) (T[E]){E,E,...,E}

       (T[E,E,...,E]){{E,...},...,{E,...}}
              Alternate  syntax  for  creating  arrays   of   type   T.    The
              initializers,  in  curly  braces,  are  optional.  The number of
              initializers must be less than or equal to the given  number  of
              elements  in  each  dimension.  For multidimensional arrays, the
              extra  curly  braces  per  dimension  in  the  initializer   are
              required; this is unlike C, where they are optional.

       (T[*]){E,E,...,E} (T[*,*,...,*]){{E,...},...,{E,...}}
              Creates  arrays  of  type T, with each dimension’s size given by
              the maximum number of  initializers  in  any  subarray  in  that
              dimension.

       Pointers:

       0      The null pointer, in contexts where a pointer is required.

       &V &A[E,E,...,E] &S.N
              Creates  a  pointer  to  the  given  variable, array element, or
              structure member.  The type of the pointer will be *T,  where  T
              is the type of the object pointed to.

       *P     The  value  pointed  to  by  pointer  P.   This can be viewed or
              modified as in C.

       Functions:

       (T func(){S;S;...S;}) (T func(T name,T name,...T name){S;S;...S;})
              Function expression: denotes a function of zero or  more  formal
              parameters  with  the given types and names, returning the given
              result type.  The function body is  given  by  the  curly-brace-
              enclosed statement list.  All types are optional, and default to
              poly.  As noted above, functions are strictly call-by-value:  in
              particular,   arrays  and  structures  are  copied  rather  than
              referenced.

       T function name(T name,T name,...,T name){S;S;...S;}
              Defines a function of zero or more arguments.   Syntactic  sugar
              for
                T(T,T,...T)    name    =    (T    func(T    name,T   name,...T
              name){S;S;...S;});

       T function name(T name, T name ...)
              The ellipsis here is syntax, not metasyntax: if the last  formal
              argument  to  a function is followed by three dots, the function
              may be called with more actuals  than  formals.   All  ‘‘extra’’
              actuals  are  packaged  into the array formal of the given name,
              and typechecked against the optional type T of the last argument
              (default poly).

       Structures:

       (struct { T name; T name; ...T name; }){name = E; name = E; ...name=E;}
              Create  a  value  of  a  structured  type.  The named fields are
              initialized  to   the   given   values,   with   the   remainder
              uninitialized.   As indicated, initialization is by label rather
              than positional as in C.

       Unions:

       (union { T name; T name; ...T name; }.name) E
              Create a value of the given union type,  the  variant  given  by
              .name, and the value given by E.  E must be type-compatible with
              name.

STATEMENTS

       The statement syntax very closely resembles that of C.  Some additional
       syntax has been added to support Nickle’s additional functionality.

       E;     Evaluates the expression.

       {S ... S}
              Executes the enclosed statements in order.

       if (E) S
              Basic conditional.

       if (E) S
              Conditional execution.

       else S Else  is  allowed,  with  the  usual  syntax  and semantics.  In
              particular, an else binds to the most recent applicable if()  or
              twixt().

       while (E) S
              C-style while loop.

       do S while (E);
              C-style do loop.

       for (opt-E; opt-E; opt-E) S
              C-style for loop.

       switch (E) { case E: S-list  case E: S-list ... default: S-list }
              C-style  case  statement.  The case expressions are not required
              to be constant expressions, but may  be  arbitrary.   The  first
              case  evaluating  to  the  switch  argument  is  taken, else the
              default if present, else the switch body is skipped.

       twixt(opt-E; opt-E) S

       twixt(opt-E; opt-E) S else S
              If first argument expression evaluates to true, the body of  the
              twixt()   and  then  the  second  argument  expression  will  be
              evaluated.  If the first argument expression evaluates to false,
              the  else statement will be executed if present.  Otherwise, the
              entire twixt() statement will be skipped.

       The twixt() statement guarantees that all of these events  will  happen
       in the specified order regardless of the manner in which the twixt() is
       entered (from outside) or exited, including exceptions,  continuations,
       and break.  (Compare with Java’s ‘‘finally’’ clause.)

       try S;

       try S catch name (T name, ...) { S; ... };

       try S catch name (T name, ...) { S; ... } ... ;
              Execute the first statement S.  If an exception is raised during
              execution, and the name matches the name in a catch block,  bind
              the   formal  parameters  in  the  catch  block  to  the  actual
              parameters of the exception, and execute the body of  the  catch
              block.   There  may  be  multiple  catch  blocks  per try.  Zero
              catches, while legal, is relatively useless.   After  completion
              of  a catch block, execution continues after the try clause.  As
              with else, a catch binds to the most recent applicable try-catch
              block.

       raise name(name, name, ..., name)
              Raise the named exception with zero or more arguments.

       ;      The null statement

       break; Discontinue     execution     of     the    nearest    enclosing
              for/do/while/switch/twixt statement.  The leave expression  will
              be executed as the twixt statement is exited.

       continue;
              Branch directly to the conditional test of the nearest enclosing
              for/do/while statement.

       return E;
              Return value E from the nearest enclosing function.

       Namespaces:

       Like Java and C++ Nickle has a notion of  namespace,  a  collection  of
       names  with partially restricted visibility.  In Nickle, namespaces are
       created with the namespace command.

       opt-P namespace N { S ... }
              Places all names defined in the statements S  into  a  namespace
              named  N.   The  optional qualifier P may be the keyword public,
              but beware: this merely indicates that  the  name  N  itself  is
              visible  elsewhere  in  the current scope, and has nothing to do
              with the visibility of items inside the namespace.

       extend namespace N { S ... }
              Reopen the given namespace N,  and  extend  it  with  the  names
              defined as public in the given statements S.

              Names  defined  inside  the  namespace are invisible outside the
              namespace unless they are qualified  with  the  keyword  public.
              Public names may be referred to using a path notation:
                namespace::namespace::...::namespace::name
              refers  to  the  given  name  as defined inside the given set of
              namespaces.  The double-colon syntax is unfortunate,  as  it  is
              slightly  different  in  meaning  than  in C++, but all the good
              symbols were taken, and it is believed to be a feature that  the
              namespace   separator   is   syntactically  different  than  the
              structure operator. In Java, for example, the phrase
                name.name.name
              is syntactically ambiguous: the middle  name  may  be  either  a
              structure or a namespace.

       import N;
              The  name  N must refer to a namespace: all public names in this
              namespace are  brought  into  the  current  scope  (scoping  out
              conflicting names).

BUILTINS

       Nickle  has a collection of standard functions built in.  Some of these
       are written in C, but many are written in Nickle.  Several  collections
       of  functions  have  associated  builtin  datatypes:  their namespaces,
       together with their types, should be viewed as ADTs.

       Top-Level Builtins:

       int printf(string fmt, poly args...)
              Calls File::fprintf(stdout,  fmt,  args  ...)  and  returns  its
              result.

       string function gets ()
              Calls File::fgets(stdin) and returns its result.

       string function scanf (string fmt, *poly args...)
              Calls File::vfscanf(stdin, fmt, args) and returns its result.

       string function vscanf (string fmt, (*poly)[*] args)
              Calls File::vfscanf(stdin, fmt, args) and returns its result.

       real imprecise(rational value)
              See the discussion of type real above.

       real imprecise(rational value, int prec)
              See the discussion of type real above.

       int string_to_integer(string s)

       int atoi(string s)
              The  argument  s is a signed digit string, and the result is the
              integer it represents.  If  the  string  s  is  syntactically  a
              hexadecimal,  octal, binary, or explicit base-10 constant, treat
              it as such.

       int string_to_integer(string s, int base)

       int atoi(string s, int base)
              Treat s as a string of digits in the given base.  A  base  of  0
              acts  as  with  no base argument.  Otherwise, base specification
              syntax in the string is ignored.

       int putchar(int c)
              Place  the  given  character  on  the  standard   output   using
              File::putc(c, stdout), and return its result.

       int sleep(int msecs)
              Try   to   suspend   the  current  thread  for  at  least  msecs
              milliseconds.  Return 1 on early return, and 0 otherwise.

       int exit(int status)
              Exit Nickle with the given status code.  Do not return anything.

       int dim(poly[*] a)
              Given  a  one-dimensional  array  a, dim() returns the number of
              elements of a.

       int[] dims(poly[] a)
              Given an arbitrary array a, dims() returns an array of  integers
              giving  the  size of each dimension of a.  Thus, dim(dims(a)) is
              the number of dimensions of a.

       *poly reference(poly v)
              Given an arbitrary value v, ‘‘box’’ that value into storage  and
              return a pointer to the box.

       rational string_to_real(string s)

       rational atof(string s)
              Convert  the  real  constant  string  s into its associated real
              number.

       number abs(real v)
              Return the absolute value of v.  The  result  type  chosen  will
              match the given context.

       int floor(real v)
              Return  the  largest integer less than or equal to v.  This will
              fail if v is a real and the precision is too low.

       int ceil(real v)
              Return the smallest integer greater than or equal  to  v.   This
              will fail if v is a real and the precision is too low.

       int exponent(real v)
              Return the exponent of the imprecise real v.

       rational mantissa(real v)
              Return  the  mantissa  of  the imprecise real v, as a rational m
              with 0 <= m <= 0.5 .

       int numerator(rational v)
              Return the numerator of the rational number v: i.e., if v =  n/d
              in reduced form, return n.

       int denominator(rational v)
              Return  the  denominator  of the rational number v: i.e., if v =
              n/d in reduced form, return d.

       int precision(real v)
              Return the number of bits of precision of the  mantissa  of  the
              imprecise real number v.

       int sign(real v)
              Return -1 or 1 as v is negative or nonnegative.

       int bit_width(int v)
              Return   the   number  of  bits  required  to  represent  abs(v)
              internally.

       int is_int(poly v)
              Type predicate.

       int is_rational(poly v)
              Numeric type  predicates  are  inclusive:  e.g.,  is_rational(1)
              returns 1.

       int is_number(poly v)
              Type predicate.

       int is_string(poly v)
              Type predicate.

       int is_file(poly v)
              Type predicate.

       int is_thread(poly v)
              Type predicate.

       int is_semaphore(poly v)
              Type predicate.

       int is_continuation(poly v)
              Type predicate.

       int is_array(poly v)
              Type predicate.

       int is_ref(poly v)
              Type  predicate:  checks  for  pointer type.  This is arguably a
              misfeature, and may change.

       int is_struct(poly v)
              Type predicate.

       int is_func(poly v)
              Type predicate.

       int is_void(poly v)
              Type predicate.

       int gcd(int p, int q)
              Return the GCD of p and q.  The result is always positive.

       int xor(int a, int b)
              Return a ^ b .  This is mostly a holdover from before Nickle had
              an xor operator.

       poly setjmp(continuation *c, poly retval)
              The   setjmp()   and  longjmp()  primitives  together  with  the
              continuation type  form  an  ADT  useful  for  nearly  arbitrary
              transfers   of  flow-of-control.   The  setjmp()  and  longjmp()
              builtins are like those of C, except that the  restriction  that
              longjmp()  always  jump  upwards  is  removed(!): a continuation
              saved via setjmp() never  becomes  invalid  during  the  program
              lifetime.

              The setjmp() builtin saves the current location and context into
              its continuation pointer argument, and then returns  its  second
              argument.

       void longjmp(continuation c, poly retval)
              The  longjmp()  builtin  never  returns  to  the  call site, but
              instead returns from the setjmp() that created the continuation,
              with return value equal to the second argument of longjmp().

       string prompt
              The  prompt  printed  during  interactive use when at top-level.
              Default "> ".  when waiting for  the  rest  of  a  statement  or
              expression,  and  when  debugging, respectively.  Default values
              are "> ", "+ ", and "- ".

       string prompt2
              The prompt printed during interactive use when waiting  for  the
              rest of a statement or expression.  Default "+ ".

       string prompt3
              The  prompt  printed  during  interactive  use  when  debugging.
              Default "- ".

       string format
              The printf() format  for  printing  top-level  values.   Default
              "%g".

       string version
              The  version number of the Nickle implementation currently being
              executed.

       string build
              The build date of  the  Nickle  implementation  currently  being
              executed,  in the form "yyyy/mm/dd", or "?" if the build date is
              unknown for some reason.

       file stdin
              Bound to the standard input stream.

       file stdout
              Bound to the standard output stream.

       file stderr
              Bound to the standard error stream.

       Exceptions:

       A few standard  exceptions  are  predeclared  and  used  internally  by
       Nickle.

       exception uninitialized_value(string msg)
              Attempt to use an uninitialized value.

       exception invalid_argument(string msg, int arg, poly val)
              The arg-th argument to a builtin function had invalid value val.

       exception readonly_box(string msg, poly val)
              Attempt to change the value of a read-only quantity to val.

       exception invalid_array_bounds(string msg, poly a, poly i)
              Attempt to access array a at index i is out of bounds.

       exception divide_by_zero(string msg, real num, real den)
              Attempt to divide num by den with den == 0.

       exception invalid_struct_member(string msg, poly struct, string name)
              Attempt to refer to member name of the object struct, which does
              not exist.

       exception invalid_binop_values(string msg, poly arg1, poly arg2)
              Attempt  to  evaluate a binary operator with args arg1 and arg2,
              where at least one of these values is invalid.

       exception invalid_unop_values(string msg, poly arg)
              Attempt to evaluate a unary operator with invalid argument  arg.

       Builtin Namespaces:

       Math   The   math   functions  available  in  the  Math  namespace  are
              implemented in a fashion intended to be compatible  with  the  C
              library.   Please  consult  the  appropriate manuals for further
              details.

       real pi
              Imprecise    constant    giving     the     value     of     the
              circumference/diameter  ratio  of  the  circle  to  the  default
              precision of 256 bits.

       protected real e
              Imprecise constant giving the  value  of  the  base  of  natural
              logarithms  to  the  default  precision of 256 bits.  Since e is
              protected, it must be referenced via Math::e, in order to  avoid
              problems  with  using  the  fifth  letter of the alphabet at top
              level.

       real function sqrt(real v)
              Returns the square root of v.

       real function cbrt(real v)
              Returns the cube root of v.

       real function exp(real v)
              Returns e**v.

       real function log(real a)
              Returns v such that  e**v  ==  a.   Throws  an  invalid_argument
              exception if a is non-positive.

       real function log10(real a)
              Returns  v  such  that  10**v  == a.  Throws an invalid_argument
              exception if a is non-positive.

       real function log2(real a)
              Returns v such that  2**v  ==  a.   Throws  an  invalid_argument
              exception if a is non-positive.

       real function pi_value(int prec)
              Returns  the  ratio  of  the  circumference  of  a circle to the
              diameter, with prec bits of precision.

       real function sin(real a)
              Returns the ratio of the opposite  side  to  the  hypotenuse  of
              angle a of a right triangle, given in radians.

       real function cos(real a)
              Returns  the  ratio  of  the  adjacent side to the hypotenuse of
              angle a of a right triangle, given in radians.

       void function sin_cos(real a, *real sinp, *real cosp)
              Returns with sin(a) and cos(a) stored in the  locations  pointed
              to  by  sinp  and cosp respectively.  If either pointer is 0, do
              not store into that  location.   May  be  slightly  faster  than
              calling both trig functions independently.

       real function tan(real a)
              Returns  the  ratio of the opposite side to the adjacent side of
              angle a of a  right  triangle,  given  in  radians.   Note  that
              tan(pi/2) is not currently an error: it will return a very large
              number dependent on the precision of its input.

       real function asin(real v)
              Returns a such that sin(a) == v.

       real function acos(real v)
              Returns a such that cos(a) == v.

       real function atan(real v)
              Returns a such that tan(a) == v.

       real function atan2(real x, y)
              Returns a such that tan(a) == x / y.  Deals correctly with y  ==
              0.

       real function pow(real a, real b)
              The implementation of the ** operator.

       File   The namespace File provides operations on file values.

       int function fprintf(file f, string s, ....)
              Print  formatted  values  to  a file, as with UNIX stdio library
              fprintf().  fprintf() and printf() accept a  reasonable  sub-set
              of  the  stdio  library version:  %c, %d, %e, %x, %o, %f, %s, %g
              work as expected, as does %v to  smart-print  a  value.   Format
              modifiers  may be placed between the percent-sign and the format
              letter to modify formatting.  There are a lot of known bugs with
              input and output formatting.

              Format Letters:

              %c     Requires  a  small integer argument (0..255), and formats
                     as an ASCII character.

              %d     Requires an integer argument, and formats as an  integer.

              %x     Requires  an  integer  argument, and formats as a base-16
                     (hexadecimal) integer.

              %o     Requires an integer argument, and  formats  as  a  base-8
                     (octal) integer.

              %e     Requires  a  number  argument,  and formats in scientific
                     notation.

              %f     Requires a number argument, and  formats  in  fixed-point
                     notation.

              %s     Requires   a   string  argument,  and  emits  the  string
                     literally.

              %g     Requires a number,  and  tries  to  pick  a  precise  and
                     readable representation to format it.

              Format Modifiers:

              digits All   format  characters  will  take  an  integer  format
                     modifier indicating the number of blanks  in  the  format
                     field  for  the  data to be formatted.  The value will be
                     printed right-justified in this space.

              digits.digits
                     The real formats will  take  a  pair  of  integer  format
                     modifiers   indicating  the  field  width  and  precision
                     (number of chars after decimal point)  of  the  formatted
                     value.  Either integer may be omitted.

              -      A precision value indicating infinite precision.

              *      The  next  argument to fprintf() is an integer indicating
                     the field width or precision of the formatted value.

       file function string_write()
              Return a file which collects written values into a string.

       int function close(file f)
              Close file f and return an indication of success.

       int function flush(file f)
              Flush the buffers of file f and return an indication of success.

       int function getc(file f)
              Get the next character from file f and return it.

       int function end(file f)
              Returns true if file f is at EOF, else false.

       int function error(file f)
              Returns true if an error is pending on file f, else false.

       int function clear_error(file f)
              Clears  pending  errors  on file f, and returns an indication of
              success.

       file function string_read(string s)
              Returns a virtual file whose contents are the string s.

       string function string_string(file f)
              Return the string previously written  into  the  file  f,  which
              should  have  been  created  by string_read() or string_write().
              Behavior on other files is currently undefined.

       file function open(string path, string mode)
              Open the file at the given path with the given mode string,  ala
              UNIX  stdio  fopen().   Permissible  modes are as in stdio: "r",
              "w", "x", "r+", "w+" and "x+".

       integer function fputc(integer c, file f)
              Output the character c to the  output  file  f,  and  return  an
              indication of success.

       integer function ungetc(integer c, file f)
              Push  the  character c back onto the input file f, and return an
              indication of success.

       integer function setbuf(file f, integer n)
              Set the size of the buffer associated with  file  f  to  n,  and
              return n.

       string function fgets (file f)
              Get  a  line  of  input  from  file  f, and return the resulting
              string.

       file function pipe(string path, string[*] argv, string mode)
              Start up the program at the given path, returning a  file  which
              is  one  end of a "pipe" to the given process. The mode argument
              can be "r" to read from the pipe or "w" to write  to  the  pipe.
              The argv argument is an array of strings giving the arguments to
              be passed to the program, with argv[0] conventionally being  the
              program name.

       int  function  print  (file f, poly v, string fmt, int base, int width,
       int prec, string fill)
              Print  value  v  to  file  f  in format fmt with the given base,
              width, prec, and fill.  Used internally by File::fprintf();

       int function fscanf(file f, string fmt, *poly args...)
              Fill the locations pointed to by  the  array  args  with  values
              taken   from  file  f  according  to  string  fmt.   The  format
              specifiers are much as in UNIX stdio scanf():  the  "%d",  "%e",
              "%f",  "%c"  and "%s" specifiers are supported with the expected
              modifiers.

       int function vfscanf (file f, string fmt, (*poly)[*] args)
              Given the file f, the format fmt, and  the  array  of  arguments
              args, fscanf() appropriately.

       Thread The  namespace  Thread  supports  various  operations useful for
              programming with  threads,  which  provide  concurrent  flow  of
              control  in  the  shared  address  space.  There is one piece of
              special syntax associated with threads.

              fork(E)
                     Accepts an arbitrary expression, and evaluates  it  in  a
                     new  child thread.  The parent thread receives the thread
                     as the value of the fork expression.

              The remainder of the Thread functions are fairly standard.

       int function kill(thread list...)
              Kills  every  running  thread  in  the  array  list.   With   no
              arguments,  kills  the  currently  running  thread.  Returns the
              number of threads killed.

       int function trace(poly list...)
              Shows the state of every running thread in the array list.  With
              no  arguments,  traces  the  default  continuation.  Returns the
              number of threads traced.

       int function cont()
              Continues execution of any interrupted threads, and returns  the
              number of continued threads.

       thread function current()
              Return the current thread.

       int function list()
              Reports the currently running thread to stdout.

       int function get_priority(thread t)
              Reports the priority of the given thread.

       thread function id_to_thread(int id)
              Returns the thread with the given id, if found, and 0 otherwise.

       poly function join(thread t)
              Waits for  thread  t  to  terminate,  and  returns  whatever  it
              returns.

       int function set_priority(thread t, int i)
              Attempts to set the priority of thread t to level i, and returns
              the new priority.  Larger priorities mean more runtime:  a  task
              with higher priority will always run instead of a lower priority
              task.  Threads of equal highest priority will  be  pre-emptively
              multitasked.

       Semaphore
              The Semaphore namespace encapsulates operations on the semaphore
              built-in ADT.  A semaphore is used for  thread  synchronization.
              Each  signal()  operation  on  the  semaphore awakens the least-
              recent thread to wait() on that  semaphore.   The  ‘‘count’’  of
              waiting processes may be set at semaphore creation time.

       semaphore function new(int c)
              Create  a  new  semaphore  with  an  initial  count c of waiting
              processes.  If c is positive, it means that c threads  may  wait
              on the semaphore before one blocks.  If c is negative, it sets a
              count of threads which must be waiting on the  semaphore  before
              further waits will not block.

       semaphore function new()
              Call semaphore(0) and return its result.

       int signal(semaphore s)
              Increment semaphore s.  If s is non-positive, and some thread is
              blocked on s, release the least-recently-blocked thread.  Return
              1 on success.

       int wait(semaphore s)
              Decrement  semaphore s.  If s is negative, block until released.
              Return 1 on success.

       int test(semaphore s)
              Test whether wait() on  semaphore  s  would  cause  the  current
              thread  to  block.   If  so,  return  0.   Otherwise, attempt to
              decrement s, and return 1 if successful.

       String The String namespace contains a  few  basic  operations  on  the
              string ADT.

       int function length(string s)
              Returns the number of characters in s.

       string function new(int c)
              Returns as a string the single character c.

       string function new(int cv[*])
              Returns a string comprised of the characters of cv.

       int function index(string t, string p)
              Returns  the integer index of the pattern string p in the target
              string t, or -1 if p is not a substring of t.

       string function substr(string s, int i, int l)
              Returns the substring of string s starting with the character at
              offset   i   (zero-based)  and  continuing  for  a  total  of  l
              characters.  If l is negative, the  substring  will  consist  of
              characters preceding rather than succeeding i.

       PRNG   The  PRNG namespace provides pseudo-random number generation and
              manipulation.  The core  generator  is  the  RC4  stream  cipher
              generator,  properly  bootstrapped.   This  provide  a stream of
              cryptographically-secure  pseudo-random   bits   at   reasonable
              amortized   cost.    (But  beware,  initialization  is  somewhat
              expensive.)

       void function srandom(int s)
              Initialize the generator, using the (arbitrarily-large)  integer
              as a seed.

       void function dev_srandom(int nbits)
              Initialize  the  generator, using nbits bits of entropy obtained
              from some reasonable entropy  source.   On  UNIX  systems,  this
              source  is  /dev/urandom.   Asking for more initial entropy than
              the system has may lead either to bootstrapping (as on UNIX)  or
              to hanging, so use cautiously.

       int function randbits(int n)
              Returns an n-bit pseudo-random number, in the range 0..(2**n)-1.
              Useful for things like RSA.

       int function randint(int n)
              Returns a pseudo-random number in the range 0..n-1.

       void function shuffle(*(poly[*]) a)
              Performs an efficient in-place true shuffle (c.f. Knuth) of  the
              array a.

       Command
              The  Command  namespace  is  used  by  the top-level commands as
              described below.  It is also  occasionally  useful  in  its  own
              right.

       string library_path
              Contains the current library search path, a colon-separated list
              of directories to be searched for library files.

       int function undefine(string name)
              Implements the  top-level  undefine  command.  Remove  the  name
              denoted  by  string  name  from the namespace.  This removes all
              visible definitions of the name.

       int function undefine(string[*] names)
              Remove each of the names in the array names from the  namespace.
              This removes all visible definitions of each name.

       int function delete(string name)
              Attempt  to  remove  the command with the given string name from
              the top-level command list, and return 1 if successful.

       int function lex_file(string path)
              Attempt to make the file at the given path the current source of
              Nickle  code,  and  return  1  if  successful.   Note  that this
              effectively ‘‘includes’’ the file by pushing it onto a stack  of
              files to be processed.

       int function lex_library(string filename)
              Like  lex_file(),  but  searches  the  directories  given by the
              library_path  variable  for  the  first  file  with  the   given
              filename.

       int function lex_string(string code)
              Attempt  to make the Nickle code contained in the string code be
              the next input.

       int function edit(string[*] names)
              Implements the top-level edit command. The names  in  the  array
              are  a path of namespace names leading to the symbol name, which
              is last.

       int function new(string name, poly func)
              Binds function func to the top-level command string name:  i.e.,
              makes it part of the top-level command vocabulary.

       int function new_names(string name, poly func)
              Binds  function func to the top-level command string name: i.e.,
              makes it part  of  the  top-level  command  vocabulary.   Unlike
              new(),  the  string  names  given  to  func at the top level are
              passed unevaluated as an array of string names or  as  a  single
              string name.

       int function pretty_print(file f, string[*] names)
              Implements the top-level print command.  Each of the passed name
              strings is looked up and the corresponding code printed to  file
              f.

       int function display(string fmt, poly val)
              Uses printf() to display the value val in format fmt.

       History
              Nickle maintains a top-level value history, useful as an adjunct
              to command-line editing when calculating.  The History namespace
              contains functions to access this history.

       int function show(string fmt)
              Implements  the  history  top-level  command  with no arguments.
              Show the most recent history values with format fmt.

       int function show(string fmt, int count)
              Implements the history  top-level  command  with  one  argument.
              Show the last count history values with format fmt.

       int function show(string fmt, int first, int last)
              Implements the history top-level command with two arguments.

       poly function insert(poly val)
              Insert val in the history list, and return it.

       Environ
              Many   operating  systems  have  some  notion  of  ‘‘environment
              variables.’’   The  Environ  namespace  contains  functions   to
              manipulate these.

       int function check(string name)
              Returns  1  if  the  variable  with  the  given  name  is in the
              environment, and 0 otherwise.

       string function get(string name)
              Attempts to retrieve and return the  value  of  the  environment
              variable  with  the  given  name.   Throws  an  invalid_argument
              exception if the variable is not available.

       int function unset(string name)
              Attempts to unset the environment variable with the given  name,
              and returns an indication of success.

       string function set(string name, string value)
              Attempts  to set the environment variable with the given name to
              the given value, and returns an indication of success.

COMMANDS

       Nickle has a set of commands which may be given at the top level.

       quit   Exit Nickle.

       quit E Exit Nickle with integer status code E.

       undefine NAME {,NAME}
              Remove these names from the system.

       load E Load a file given by the string name E.

       library E
              Load a library given by the string name E.  See  the  discussion
              of the NICKLEPATH environment variable in ENVIRONMENT below, and
              the discussion of Command::library_path above.

       E # E  Print expr1 in base expr2 .

       print NAME
              Display a formatted version  of  the  object  denoted  by  NAME.
              Comments  and  original  formating  are  lost.   If  NAME  is  a
              variable, print the type as well as the value.

       edit NAME
              Invoke $EDITOR on  the  named  object,  and  re-incorporate  the
              results of the edit.  This is most useful with functions.

       history
              Display  the  10  most  recently  printed  values.   They can be
              accessed with $n where n is the number displayed to the right of
              the value in this list.

       history E
              Display the E most recent history values.

       history E,E
              Display  history  values  from  the  first integer E through the
              second.

DEBUGGER

       When an unhandled exception reaches top  level  during  execution,  the
       user  receives a dash prompt, indicating that debug mode is active.  In
       this mode, the command-line environment is that in which the  unhandled
       exception  was  raised.  In addition a number of debugging commands are
       available to the user:

       trace  Get a stack backtrace showing the current state, as with the GDB
              where command.

       up     Move  up  the  stack (i.e., toward the top-level expression) ala
              GDB.

       down   Move down the stack (i.e., toward the current context) ala  GDB.

       done   Leave debugging mode, abandoning execution.

              In addition, the Debug namespace is scoped in in debugging mode.
              This is primarily of use in debugging Nickle itself.

       collect()
              Run the garbage collector.

       dump(function)
              Print the compiled byte code for function.

ENVIRONMENT

       EDITOR The editor used by  the  edit  command,  described  in  COMMANDS
              above.

       NICKLERC
              The  location of the user’s .nicklerc file, which will be loaded
              at the beginning of nickle execution if possible.

       HOME   Used to find the user’s .nicklerc if NICKLERC is not set.

       NICKLEPATH
              A colon-separated path whose elements are directories containing
              Nickle  code.   The  library  command and the -l flag, described
              above, search this path for a filename matching the given  file.
              The  default  library  path  in  the absence of this variable is
              /usr/share/nickle.

       NICKLESTART
              The filename of the file that should be loaded as a bootstrap on
              Nickle  startup.  The default in the absence of this variable is
              to load /usr/share/nickle/builtin.5c.

EXAMPLES

       An example (taken from the bc manual:

         real function exponent(real x) {
             real a = 1;
             int b = 1;
             real s = 1;
             int i = 1;
             while (1) {
                 a = a * x;
                 b = b * i;
                 real c = a / b;
                 if (abs(c) < 1e-6)
                     return s;
                 s = s + c;
                 i++;
             }
         }

       defines a function to compute an approximate value of  the  exponential
       function e ** x and

         for (i = 1; i < 10; i++)
             printf ("%g\n", exponent (i));

       prints  approximate values of the exponential function of the first ten
       integers.

VERSION

       This document describes version 1.99.2 of nickle, as well as some newer
       features.  It was distributed with version 2.69 of nickle.

BUGS

       See the discussion of the type of the exponentiation operator ** above.

       Due to a difficult-to-remove grammar ambiguity, it is not  possible  to
       use  a  bare  assignment  expression  in  an  array  initializer: it is
       confused with a structure initializer.  For example:
         > int x = 0;
         > (int[*]){x = 1}
         ->     (int[*]) { x = 1 }
       Non array initializer
       The workaround is to parenthesize the assignment expression:
         > (int[*]){(x = 1)}
         [1]{1}
       Because this is so rare, so hard to fix, and so easy  to  work  around,
       this bug is unlikely to be fixed anytime soon.

       There  are  a  lot of known bugs with input and output formatting.  The
       obvious stuff works, other stuff does not.

       The semantics of division are unfortunately different from those of  C.
       This  is arguably because C is broken in this area: we cannot currently
       see any obvious fix.  C allows automatic implicit coercion of  floating
       to integral types, but we consider this a misfeature.

       The implementation has not been thoroughly tested.

AUTHOR

       Nickle is the work of Keith Packard <keithp@keithp.com> and Bart Massey
       <bart_massey@iname.com>.

       Nickle is
       Copyright  1988-2006  Keith  Packard  and  Bart  Massey.   All   Rights
       Reserved.

       Permission is hereby granted, free of charge, to any person obtaining a
       copy  of  this  software  and  associated  documentation   files   (the
       "Software"),  to  deal  in  the Software without restriction, including
       without limitation the rights to use,  copy,  modify,  merge,  publish,
       distribute,  sublicense,  and/or  sell  copies  of the Software, and to
       permit persons to whom the Software is furnished to do so,  subject  to
       the following conditions:

       The above copyright notice and this permission notice shall be included
       in all copies or substantial portions of the Software.

       THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
       OR   IMPLIED,   INCLUDING   BUT   NOT  LIMITED  TO  THE  WARRANTIES  OF
       MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  NONINFRINGEMENT.
       IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       FROM,  OUT  OF  OR  IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       DEALINGS IN THE SOFTWARE.

       Except as contained in this notice, the names of the authors  or  their
       institutions  shall  not be used in advertising or otherwise to promote
       the sale, use or other dealings in this Software without prior  written
       authorization from the authors.

                                  2009/11/07