#include "forth.h"
/* Compilation primitives. */

PRIMITIVE ("literal", Fliteral, Sliteral, NON_IMMEDIATE, ( -- ) )
{
  PUSH ((long) *(++pc));
}


/* Used by ";" in exiting compilation. */
jmp_buf colon_jump_buf;

PRIMITIVE (":", Fcolon, Scolon, NON_IMMEDIATE, ( -- ) )
{
  /* The colon compiler, as a C primitive.
   * There may be other incarnations someday.
   */

  char *name;

  if (setjmp (colon_jump_buf))
    {
      /* Fsemicolon() called longjmp() to get us here.  So end the
       * definition and return.
       */
      *dp++ = END_OF_PARAMS;
      return;
    }
  else
    {
      /* First get the name of the new word being defined. */
      BL;
      Fword ();

      /* Make name point to the counted string whose address Fword
       * left on the stack.
       */
      name = (char *) POP;

      /* User can call Fimmediate to set precedence later. */
      start_word (&name[1], name[0], NON_IMMEDIATE);


      /* Now we loop until ";", compiling everything we see on the way
       * to grandmother's house.
       */
      while (TRUE)
        {
          BL;
          Fword ();
          
          if (!(*sp))
            {
              if (infile != stdin)
                {
                  /* Done reading from file, continue on stdin. */
                  infile = stdin;
                  continue;
                }
              else
                {
                  /* User typed EOF, so return. */
                  return;
                }
            }
          
          Ffind ();
          
          if (POP)
            {
              /* What's on the stack now is the CFA of a word.  If
               * it's immediate, we want to run it; else, we want to
               * compile it into the current definition.
               */
              if (ENTRY_IMMEDIATE_P (CFA_ENTRY (*sp)))
                {
                  Fexecute ();
                }
              else
                {
                  *dp++ = POP;
                }
            }
          else
            {
              /* What's on the stack now is the address of a string
               * which encodes a number, so compile the number into
               * the definition, with Fliteral()'s help.
               */
              Fnumber ();
              *dp++ = (long) dict_lookup ("literal", 7);
              *dp++ = POP;
            }
        }
    }
}


PRIMITIVE (";", Fsemicolon, Ssemicolon, IMMEDIATE, ( -- ) )
{
  longjmp (colon_jump_buf, 1);
}


PRIMITIVE ("immediate", Fimmediate, Simmediate, NON_IMMEDIATE, ( -- ) )
{
  /* Set the precedence bit on the most recently-compiled dict entry. */
  *((char *) last_dp) ^= IMMEDIATE;
}


