Esempio n. 1
0
// Process pendent leaves
static void processLeaves(void)
 {
 int32_t data,addr;
 uint16_t *pointer;

 // Pop value set by DO
 if (CPOP(&data))
     {
	 consoleErrorMessage(&MainContext,"Cannot process leaves");
	 return;
     }

 // Check that data is about leaves
 if ((data&HEAD_MASK)!=BHEAD_LEAVE)
      {
	  consoleErrorMessage(&MainContext,"Inconsistent leave processing");
	  return;
      }

 // Discard head
 data&=BRANCH_MASK;

 // Discard one because 1 was added
 data--;

 while(MainContext.rstack.Pointer>data)
     {
	 // Try to get one element from the return stack
	 if (RPOP(&addr))
	    {
		consoleErrorMessage(&MainContext,"Inconsistent leave processing");
		return;
	    }

	 // Check that data is about leaves
	 if ((addr&HEAD_MASK)!=BHEAD_LEAVE)
	       {
	 	   consoleErrorMessage(&MainContext,"Inconsistent leave processing");
	 	   return;
	       }

	 // Discard head
	 addr&=BRANCH_MASK;

	 // Set pointer
	 pointer=(uint16_t*)(UDict.Mem+addr);

	 // Set value in pointer to current code position
	 (*pointer)=CodePosition;
     }
  }
Esempio n. 2
0
// **************************************************************
//! \param idPrimitive the token of a primitive else an exception
//! is triggered.
//! UnknownForthPrimitive if idPrimitive is not the token of a
//! primitive (idPrimitive >= NUM_PRIMITIVES).
//! \throw UnfinishedStream called by Forth::nextWord() if the
//! stream does not contain a Forth word.
//! \throw UnknownForthWord if the extracted word by Forth::nextWord()
//! is not present in the dictionary.
//! \throw AbortForth if triggered by the Forth word ABORT.
//! \throw ModifiedStackDepth if the data stack depth is modified
//! during a definition.
//! \throw OutOfBoundDictionary if attempting to store data outside
//! the dictionary bounds.
//! \throw NoSpaceDictionary if attempting to add a new entry in a
//! full dictionary.
// **************************************************************
void Forth::execPrimitive(const Cell16 idPrimitive)
{
  //std::cout << "execPrimitive " << idPrimitive << std::endl;
  switch (idPrimitive)
    {
      // Dummy word / No operation
    case FORTH_PRIMITIVE_NOP:
      std::cout << "NOP\n";
      break;

      // Begin of commentary
    case FORTH_PRIMITIVE_LPARENTHESIS:
      m_saved_state = m_state;
      m_state = forth::Comment;
      break;

      // End of commentary
    case FORTH_PRIMITIVE_RPARENTHESIS:
      m_state = m_saved_state;
      break;

      // Line of commentary
    case FORTH_PRIMITIVE_COMMENTARY:
      STREAM.skipLine();
      break;

      // Begin the definition of a new word
    case FORTH_PRIMITIVE_COLON:
      create(nextWord());
      m_state = forth::Compile;
      break;

      // End the definition of a new word
    case FORTH_PRIMITIVE_SEMICOLON:
      m_dictionary.appendCell16(FORTH_PRIMITIVE_EXIT);
      m_state = forth::Interprete;
      if (m_depth_at_colon != stackDepth(forth::DataStack))
        {
          m_dictionary.m_last = m_last_at_colon;
          m_dictionary.m_here = m_here_at_colon;
          ModifiedStackDepth e(m_creating_word);
          throw e;
        }
      break;

      // Push in data stack the next free slot in the dictionary
    case FORTH_PRIMITIVE_PCREATE:
      DPUSH(m_tos);
      m_tos = m_ip + 4U;
      break;

      // Give a name to the next free slot in the dictionary.
      // (note: HERE is not moved)
      // https://fr.wikiversity.org/wiki/Forth/Conserver_des_donn%C3%A9es
    case FORTH_PRIMITIVE_CREATE:
      create(nextWord());
      m_dictionary.appendCell16(FORTH_PRIMITIVE_PCREATE);
      m_dictionary.appendCell16(FORTH_PRIMITIVE_EXIT);
      break;

    case FORTH_PRIMITIVE_BUILDS:
      create(nextWord());
      break;

    case FORTH_PRIMITIVE_DOES:
      break;

      // Set immediate the last word
    case FORTH_PRIMITIVE_IMMEDIATE:
      m_dictionary.m_dictionary[m_dictionary.m_last] |= FLAG_IMMEDIATE;
      break;

    case FORTH_PRIMITIVE_INCLUDE:
      // Restore TOS register (because execToken() poped TOS)
      DPUSH(m_tos);

      includeFile(nextWord());

      DPOP(m_tos);
      break;

    case FORTH_PRIMITIVE_STATE:
      DPUSH(m_tos);
      m_tos = m_state;
      break;

    case FORTH_PRIMITIVE_TRACE_ON:
      LOGI("Forth trace: ON");
      m_trace = true;
      break;

    case FORTH_PRIMITIVE_TRACE_OFF:
      LOGI("Forth trace: OFF");
      m_trace = false;
      break;

    case FORTH_PRIMITIVE_SMUDGE:
      {
        std::string const& word = nextWord();
        if (false == m_dictionary.smudge(word))
          {
            std::cout << FORTH_WARNING_COLOR << "[WARNING] Unknown word '"
                      << word << "'. Word SMUDGE Ignored !"
                      << FORTH_NORMAL_COLOR << std::endl;
          }
      }
      break;

    case FORTH_PRIMITIVE_TICK:
      {
        std::string const& word = nextWord();
        Cell16 token;
        bool immediate;
        if (false == m_dictionary.find(word, token, immediate))
          {
            token = 0;
            std::cout << FORTH_WARNING_COLOR << "[WARNING] Unknown word '"
                      << word << "'. Word TICK Ignored !"
                      << FORTH_NORMAL_COLOR << std::endl;
          }
        DPUSH(m_tos);
        m_tos = token;
      }
      break;

     case FORTH_PRIMITIVE_COMPILE:
       m_ip += 2;
       m_dictionary.appendCell16(m_dictionary.read16at(m_ip));
       break;

       // Append to the dictionary the next word
     case FORTH_PRIMITIVE_ICOMPILE:
       {
         Cell16 token;
         bool immediate;
         std::string const& word = nextWord();

         //m_ip += 2;
         if (m_dictionary.find(word, token, immediate))
           {
             m_dictionary.appendCell16(token);
           }
         else
           {
             UnknownForthWord e(word); throw e;
           }
       }
       break;

       // ANSI word to replace [COMPILE] and COMPILE
    case FORTH_PRIMITIVE_POSTPONE:
      {
        Cell16 token;
        bool immediate;
        std::string const& word = nextWord();

        if (m_dictionary.find(word, token, immediate))
          {
            if (immediate)
              {
                m_dictionary.appendCell16(token);
              }
            else
              {
                m_ip += 2;
                m_dictionary.appendCell16(m_dictionary.read16at(m_ip));
              }
          }
        else
          {
            UnknownForthWord e(word); throw e;
          }
      }
      break;

     case FORTH_PRIMITIVE_ABORT:
       abort("COUCOU");
       break;

     case FORTH_PRIMITIVE_EXECUTE:
       execToken(m_tos);
       break;

     case FORTH_PRIMITIVE_LBRACKET:
       m_state = forth::Interprete;
       break;

    case FORTH_PRIMITIVE_RBRACKET:
       m_state = forth::Compile;
       break;

    case FORTH_PRIMITIVE_HERE:
      DPUSH(m_tos);
      m_tos = m_dictionary.here();
      break;

    case FORTH_PRIMITIVE_LAST:
      DPUSH(m_tos);
      m_tos = m_dictionary.last();
      break;

    case FORTH_PRIMITIVE_ALLOT:
      m_dictionary.allot((int32_t) m_tos);
      DPOP(m_tos);
      break;

      // Reserve one cell of data space and store x in the cell.
    case FORTH_PRIMITIVE_COMMA32:
      m_dictionary.appendCell32(m_tos);
      DPOP(m_tos);
      break;

      // Reserve one cell of data space and store x in the cell.
    case FORTH_PRIMITIVE_COMMA16:
      m_dictionary.appendCell16(m_tos);
      DPOP(m_tos);
      break;

      // Reserve one cell of data space and store x in the cell.
    case FORTH_PRIMITIVE_COMMA8:
      m_dictionary.appendCell8(m_tos);
      DPOP(m_tos);
      break;

      // ( a-addr -- x )
      // x is the value stored at a-addr.
    case FORTH_PRIMITIVE_FETCH:
      m_tos = m_dictionary.read32at(m_tos);
      break;

      // Store x at a-addr.
      // ( x a-addr -- )
    case FORTH_PRIMITIVE_STORE32:
      DPOP(m_tos1);
      m_dictionary.write32at(m_tos, m_tos1);
      DPOP(m_tos);
      break;

    case FORTH_PRIMITIVE_STORE16:
      DPOP(m_tos1);
      m_dictionary.write16at(m_tos, m_tos1);
      DPOP(m_tos);
      break;

    case FORTH_PRIMITIVE_STORE8:
      DPOP(m_tos1);
      m_dictionary.write8at(m_tos, m_tos1);
      DPOP(m_tos);
      break;

      /* ( src dst n -- ) */
    case FORTH_PRIMITIVE_CMOVE:
      DPOP(m_tos2); // dst
      DPOP(m_tos1); // src
      m_dictionary.move(m_tos2, m_tos1, m_tos);
      DPOP(m_tos);
      break;

      /*  case FORTH_PRIMITIVE_THROW:
      if (m_tos)
        {
          M_THROW(m_tos);
        }
      else DPOP(m_tos);
      break;*/

      // Restore the IP when interpreting the definition
      // of a non primitive word
    case FORTH_PRIMITIVE_EXIT:
      RPOP(m_ip);
      if (m_trace) {
        std::cout << "POPed: " << std::hex << (int) m_ip << std::endl;
      }
      break;

      // Change IP
    case FORTH_PRIMITIVE_BRANCH:
      m_ip += m_dictionary.read16at(m_ip + 2U);
      // Do not forget that m_ip will be += 2 next iteration
      break;

      // Change IP if top of stack is 0
    case FORTH_PRIMITIVE_0BRANCH:
      if (0 == m_tos)
        {
          m_ip += m_dictionary.read16at(m_ip + 2U);
        }
      else
        {
          m_ip += 2U;
        }
      // Do not forget that m_ip will be += 2 next iteration
      DPOP(m_tos);
      break;

      // Move x to the return stack.
      // ( x -- ) ( R: -- x )
    case FORTH_PRIMITIVE_TO_RSTACK:
      RPUSH(m_tos);
      DPOP(m_tos);
      break;

      // Transfer cell pair x1 x2 to the return stack
      // ( x1 x2 -- ) ( R: -- x1 x2 )
    case FORTH_PRIMITIVE_2TO_RSTACK:
      DPOP(m_tos1);
      RPUSH(m_tos1);
      RPUSH(m_tos);
      DPOP(m_tos);
      break;

    case FORTH_PRIMITIVE_FROM_RSTACK:
      DPUSH(m_tos);
      RPOP(m_tos);
      break;

    case FORTH_PRIMITIVE_2FROM_RSTACK:
      DPUSH(m_tos);
      RPOP(m_tos);
      RPOP(m_tos1);
      DPUSH(m_tos1);
      break;

#if 0
    case FORTH_PRIMITIVE_DO:
      std::cout << "(DO)" << std::endl;
      RPUSH(m_tos);
      DPOP(m_tos1); // FIXME: optim: RPUSH(DPOP);
      RPUSH(m_tos1);
      m_tos = DDROP();
      break;

    case FORTH_PRIMITIVE_LOOP:
      std::cout << "(LOOP)" << std::endl;
      RPOP(m_tos1); /* limit */
      RPOP(m_tos2); /* index */
      ++m_tos2;
      if (m_tos2 == m_tos1)
        {
          ++m_ip;   /* skip branch offset, exit loop */
        }
      else
        {
/* Push index and limit back to R */
          RPUSH(m_tos2);
          RPUSH(m_tos1);
/* Branch back to just after (DO) */
          m_ip = m_dictionary.read16at(m_ip);
        }
      break;
#endif

    case FORTH_PRIMITIVE_I:
      DPUSH(m_tos);
      m_tos = RPICK(0);
      break;

    case FORTH_PRIMITIVE_J:
      DPUSH(m_tos);
      m_tos = RPICK(2);
      break;

    case FORTH_PRIMITIVE_CELL:
      DPUSH(m_tos);
      m_tos = sizeof (Cell32);
      break;

    case FORTH_PRIMITIVE_CELLS:
      m_tos = m_tos * sizeof (Cell32);
      break;

    case FORTH_PRIMITIVE_LITERAL_16:
      DPUSH(m_tos);
      m_ip += 2U; // Skip primitive LITERAL
      m_tos = m_dictionary.read16at(m_ip);
      break;

    case FORTH_PRIMITIVE_LITERAL_32:
      DPUSH(m_tos);
      m_ip += 2U; // Skip primitive LITERAL
      m_tos = m_dictionary.read32at(m_ip);
      m_ip += 2U; // Skip the number - 2 because of next ip
      break;

    case FORTH_PRIMITIVE_1MINUS:
      --m_tos;
      break;
    case FORTH_PRIMITIVE_1PLUS:
      ++m_tos;
      break;
    case FORTH_PRIMITIVE_2MINUS:
      m_tos -= 2;
      break;
    case FORTH_PRIMITIVE_2PLUS:
      m_tos += 2;
      break;

      // drop ( a -- )
    case FORTH_PRIMITIVE_DROP:
      DPOP(m_tos);
      break;

    case FORTH_PRIMITIVE_DEPTH:
      DPUSH(m_tos);
      m_tos = stackDepth(forth::DataStack);
      break;

      // nip ( a b -- b ) swap drop ;
    case FORTH_PRIMITIVE_NIP:
      DPOP(m_tos1);
      break;

    case FORTH_PRIMITIVE_ROLL:
      {
        m_tos1 = DPICK(m_tos);
        uint32_t *src = &DPICK(m_tos - 1);
        uint32_t *dst = &DPICK(m_tos);
        uint32_t ri = m_tos;
        while (ri--)
          {
            *dst-- = *src--;
          }
        m_tos = m_tos1;
        ++m_dsp;
      }
      break;

      // ( ... n -- sp(n) )
    case FORTH_PRIMITIVE_PICK:
      m_tos = DPICK(m_tos);
      break;

      // dup ( a -- a a )
    case FORTH_PRIMITIVE_DUP:
      DPUSH(m_tos);
      break;

    case FORTH_PRIMITIVE_QDUP:
      if (m_tos)
        {
          DPUSH(m_tos);
        }
      break;

      // swap ( a b -- b a )
    case FORTH_PRIMITIVE_SWAP:
      m_tos2 = m_tos;
      DPOP(m_tos);
      DPUSH(m_tos2);
      break;

      // over ( a b -- a b a )
    case FORTH_PRIMITIVE_OVER:
      DPUSH(m_tos);
      m_tos = DPICK(1);
      break;

      // rot ( a b c -- b c a )
    case FORTH_PRIMITIVE_ROT:
      DPOP(m_tos2);
      DPOP(m_tos3);
      DPUSH(m_tos2);
      DPUSH(m_tos);
      m_tos = m_tos3;
      break;

      // tuck ( a b -- b a b ) swap over ;
    case FORTH_PRIMITIVE_TUCK:
      DPOP(m_tos2);
      DPUSH(m_tos);
      DPUSH(m_tos2);
      break;

      // 2dup ( a b -- a b a b ) over over ;
    case FORTH_PRIMITIVE_2DUP:
      DPUSH(m_tos);
      m_tos2 = DPICK(1);
      DPUSH(m_tos2);
      break;

      // 2over ( a b c d -- a b c d a b )
    case FORTH_PRIMITIVE_2OVER:
      DPUSH(m_tos);
      m_tos2 = DPICK(3);
      DPUSH(m_tos2);
      m_tos = DPICK(3);
      break;

      // 2swap ( a b c d -- c d a b )
    case FORTH_PRIMITIVE_2SWAP:
      DPOP(m_tos1);
      DPOP(m_tos2);
      DPOP(m_tos3);
      DPUSH(m_tos1);
      DPUSH(m_tos);
      DPUSH(m_tos3);
      m_tos = m_tos2;
      break;

      // 2drop ( a b -- ) drop drop ;
    case FORTH_PRIMITIVE_2DROP:
      DPOP(m_tos);
      DPOP(m_tos);
      break;

      //
    case FORTH_PRIMITIVE_BINARY:
      changeDisplayBase(2U);
      break;
    case FORTH_PRIMITIVE_OCTAL:
      changeDisplayBase(8U);
      break;
    case FORTH_PRIMITIVE_HEXADECIMAL:
      changeDisplayBase(16U);
      break;
    case FORTH_PRIMITIVE_DECIMAL:
      changeDisplayBase(10U);
      break;
    case FORTH_PRIMITIVE_GET_BASE:
      DPUSH(m_tos);
      m_tos = m_base;
      break;
    case FORTH_PRIMITIVE_SET_BASE:
      if (false == changeDisplayBase(m_tos))
        {
          std::cerr << FORTH_WARNING_COLOR << "[WARNING] '"
                    << m_tos << "' is an invalid base and shall be [2..36]. Ignored !"
                    << FORTH_NORMAL_COLOR << std::endl;
        }
      break;

    case FORTH_PRIMITIVE_NEGATE:
      m_tos = -m_tos;
      break;
    case FORTH_PRIMITIVE_ABS:
      m_tos = std::abs((int32_t) m_tos);
      break;

    case FORTH_PRIMITIVE_PLUS:
      BINARY_OP(+);
      break;
    case FORTH_PRIMITIVE_MINUS:
      BINARY_OP(-);
      break;
    case FORTH_PRIMITIVE_DIV:
      BINARY_OP(/);
      break;
    case FORTH_PRIMITIVE_TIMES:
      BINARY_OP(*);
      break;
    case FORTH_PRIMITIVE_RSHIFT:
      BINARY_OP(>>);
      break;
    case FORTH_PRIMITIVE_LSHIFT:
      BINARY_OP(<<);
      break;
    case FORTH_PRIMITIVE_FALSE:
      m_tos = 0;
      DPUSH(m_tos);
      break;
    case FORTH_PRIMITIVE_TRUE:
      m_tos = -1;
      DPUSH(m_tos);
      break;
    case FORTH_PRIMITIVE_GREATER_EQUAL:
      LOGICAL_OP(>=);
      break;
    case FORTH_PRIMITIVE_LOWER_EQUAL:
      LOGICAL_OP(<=);
      break;
    case FORTH_PRIMITIVE_GREATER:
      LOGICAL_OP(>);
      break;
    case FORTH_PRIMITIVE_LOWER:
      LOGICAL_OP(<);
      break;
    case FORTH_PRIMITIVE_EQUAL:
      LOGICAL_OP(==);
      break;
    case FORTH_PRIMITIVE_0EQUAL:
      DPUSH(0U);
      LOGICAL_OP(==);
      break;
    case FORTH_PRIMITIVE_NOT_EQUAL:
      LOGICAL_OP(!=);
      break;
    case FORTH_PRIMITIVE_AND:
      BINARY_OP(&);
      break;
    case FORTH_PRIMITIVE_OR:
      BINARY_OP(|);
      break;
    case FORTH_PRIMITIVE_XOR:
      BINARY_OP(^);
      break;
    case FORTH_PRIMITIVE_MIN:
      DPOP(m_tos1);
      m_tos = ((int32_t) m_tos < (int32_t) m_tos1) ? m_tos : m_tos1;
      break;
    case FORTH_PRIMITIVE_MAX:
      DPOP(m_tos1);
      m_tos = ((int32_t) m_tos > (int32_t) m_tos1) ? m_tos : m_tos1;
      break;
    case FORTH_PRIMITIVE_DISP:
      std::cout << std::setbase(m_base) << (int32_t) m_tos << " ";
      DPOP(m_tos);
      break;
    case FORTH_PRIMITIVE_UDISP:
      std::cout << std::setbase(m_base) << (uint32_t) m_tos << " ";
      DPOP(m_tos);
      break;
    case FORTH_PRIMITIVE_CARRIAGE_RETURN:
      std::cout << std::endl;
      break;
    case FORTH_PRIMITIVE_DISPLAY_DSTACK:
      DPUSH(m_tos);
      displayStack(std::cout, forth::DataStack);
      DPOP(m_tos);
      break;
    case FORTH_PRIMITIVE_BEGIN_C_LIB:
      {
        std::pair<bool, std::string> res = m_dynamic_libs.begin(STREAM);
        if (!res.first)
          {
            abort(res.second);
          }
      }
      break;
    case FORTH_PRIMITIVE_END_C_LIB:
      {
        std::pair<bool, std::string> res = m_dynamic_libs.end(/*nth*/); // FIXME
        if (res.first)
          {
            uint16_t i = 0;
            for (auto it: m_dynamic_libs/*[nth]*/.m_functions)
              {
                create(it.func_forth_name);
                m_dictionary.appendCell16(FORTH_PRIMITIVE_EXEC_C_FUNC);
                m_dictionary.appendCell16(i);
                m_dictionary.appendCell16(FORTH_PRIMITIVE_EXIT);
                ++i;
              }
          }
        else
          {
            abort(res.second);
          }
      }
      break;
    case FORTH_PRIMITIVE_EXEC_C_FUNC:
      DPUSH(m_tos);
      m_ip += 2U; // Skip the index of pointer function
      m_tos = m_dictionary.read16at(m_ip);
      //std::cout << "Pile avant: ";
      //displayStack(std::cout, forth::DataStack);

      m_dynamic_libs/*[nth]*/.m_functions[m_tos].fun_ptr(&m_dsp);
      //std::cout << "Pile apres: ";
      //displayStack(std::cout, forth::DataStack);
      DPOP(m_tos);
      break;
    case FORTH_PRIMITIVE_C_FUNCTION:
      {
        std::pair<bool, std::string> res = m_dynamic_libs.function(STREAM);
        if (!res.first)
          {
            abort(res.second);
          }
      }
      break;
    case FORTH_PRIMITIVE_C_CODE:
      {
        std::pair<bool, std::string> res = m_dynamic_libs.code(STREAM);
        if (!res.first)
          {
            abort(res.second);
          }
      }
      break;
    case FORTH_PRIMITIVE_ADD_EXT_C_LIB:
      {
        std::pair<bool, std::string> res = m_dynamic_libs.extlib(STREAM);
        if (!res.first)
          {
            abort(res.second);
          }
      }
      break;
    default:
      UnknownForthPrimitive e(idPrimitive, __PRETTY_FUNCTION__); throw e;
      break;
    }
}