1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com#include "Forth.h" 919a89f287f3af6fd34470a7aab92a989109d513freed@android.com#include "ForthParser.h" 10f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com#include "SkTDArray.h" 11f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com#include "SkString.h" 1219a89f287f3af6fd34470a7aab92a989109d513freed@android.com#include "SkTDStack.h" 13f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 14f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comForthEngine::ForthEngine(ForthOutput* output) : fOutput(output) { 15f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com size_t size = 32 * sizeof(intptr_t); 16f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fStackBase = reinterpret_cast<intptr_t*>(sk_malloc_throw(size)); 17f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fStackStop = fStackBase + size/sizeof(intptr_t); 18f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fStackCurr = fStackStop; 19f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 20f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 21f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comForthEngine::~ForthEngine() { 22f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com sk_free(fStackBase); 23f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 24f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 25f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEngine::sendOutput(const char text[]) { 26f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (fOutput) { 27f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fOutput->show(text); 28f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 29f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkDebugf("%s", text); 30f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 31f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 32f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 33f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEngine::push(intptr_t value) { 34f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (fStackCurr > fStackBase) { 35f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT(fStackCurr <= fStackStop && fStackCurr > fStackBase); 36f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *--fStackCurr = value; 37f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 38f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->signal_error("overflow"); 39f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 40f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 41f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 42f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comintptr_t ForthEngine::peek(size_t index) const { 43f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT(fStackCurr < fStackStop && fStackCurr >= fStackBase); 44f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (fStackCurr + index < fStackStop) { 45f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return fStackCurr[index]; 46f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 47f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->signal_error("peek out of range"); 48f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return 0x80000001; 49f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 50f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 51f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 52f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEngine::setTop(intptr_t value) { 53f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (fStackCurr < fStackStop) { 54f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT(fStackCurr < fStackStop && fStackCurr >= fStackBase); 55f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *fStackCurr = value; 56f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 57f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->signal_error("underflow"); 58f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 59f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 60f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 61f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comintptr_t ForthEngine::pop() { 62f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (fStackCurr < fStackStop) { 63f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT(fStackCurr < fStackStop && fStackCurr >= fStackBase); 64f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return *fStackCurr++; 65f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 66f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->signal_error("underflow"); 67f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return 0x80000001; 68f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 69f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 70f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 71f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/////////////////////////////////////////////////////////////////////////////// 72f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 73f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthWord::call(ForthCallBlock* block) { 74f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com ForthEngine engine(NULL); 7519a89f287f3af6fd34470a7aab92a989109d513freed@android.com 7619a89f287f3af6fd34470a7aab92a989109d513freed@android.com // setup the initial stack with the callers input data 77f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (block) { 78f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com // walk the array backwards, so that the top of the stack is data[0] 79f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com for (size_t i = 0; i < block->in_count; i++) { 80f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com engine.push(block->in_data[i]); 81f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 82f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 8319a89f287f3af6fd34470a7aab92a989109d513freed@android.com 8419a89f287f3af6fd34470a7aab92a989109d513freed@android.com // now invoke the word 85f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->exec(&engine); 8619a89f287f3af6fd34470a7aab92a989109d513freed@android.com 8719a89f287f3af6fd34470a7aab92a989109d513freed@android.com // now copy back the stack into the caller's output data 88f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (block) { 89f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com size_t n = engine.depth(); 90f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com block->out_depth = n; 91f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (n > block->out_count) { 92f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com n = block->out_count; 93f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 94f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com for (size_t i = 0; i < n; i++) { 95f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com block->out_data[i] = engine.peek(i); 96f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 97f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 98f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 99f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 100f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/////////////////////////////////////////////////////////////////////////////// 101f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 102f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/* 103f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com reading an initial 32bit value from the code stream: 104fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 105f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com xxxxxxxx xxxxxxxx xxxxxxxx xxxxxx00 106fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 107f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com Those last two bits are always 0 for a word, so we set those bits for other 108f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com opcodes 109fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 110f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 00 -- execute this word 111f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 01 -- push (value & ~3) on the data stack 112f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 10 -- push value >> 2 on the data stack (sign extended) 113f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 11 -- switch (value >>> 2) for Code 114f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com */ 115f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 116f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comclass FCode { 117f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.compublic: 11819a89f287f3af6fd34470a7aab92a989109d513freed@android.com enum { 11919a89f287f3af6fd34470a7aab92a989109d513freed@android.com kCodeShift = 2, 12019a89f287f3af6fd34470a7aab92a989109d513freed@android.com kCodeMask = 7, 12119a89f287f3af6fd34470a7aab92a989109d513freed@android.com kCodeDataShift = 5 12219a89f287f3af6fd34470a7aab92a989109d513freed@android.com }; 12319a89f287f3af6fd34470a7aab92a989109d513freed@android.com static unsigned GetCode(intptr_t c) { 12419a89f287f3af6fd34470a7aab92a989109d513freed@android.com return ((uint32_t)c >> kCodeShift) & kCodeMask; 12519a89f287f3af6fd34470a7aab92a989109d513freed@android.com } 12619a89f287f3af6fd34470a7aab92a989109d513freed@android.com static unsigned GetCodeData(intptr_t c) { 12719a89f287f3af6fd34470a7aab92a989109d513freed@android.com return (uint32_t)c >> kCodeDataShift; 12819a89f287f3af6fd34470a7aab92a989109d513freed@android.com } 12919a89f287f3af6fd34470a7aab92a989109d513freed@android.com 130f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com enum Bits { 131f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com kWord_Bits = 0, // must be zero for function address 132f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com kDataClear2_Bits = 1, 133f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com kDataShift2_Bits = 2, 134f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com kCodeShift2_Bits = 3 135f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com }; 13619a89f287f3af6fd34470a7aab92a989109d513freed@android.com 137f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com enum Code { 13819a89f287f3af6fd34470a7aab92a989109d513freed@android.com kPushInt_Code, // for data that needs more than 30 bits 13919a89f287f3af6fd34470a7aab92a989109d513freed@android.com kIF_Code, 14019a89f287f3af6fd34470a7aab92a989109d513freed@android.com kELSE_Code, 141f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com kDone_Code 142f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com }; 14319a89f287f3af6fd34470a7aab92a989109d513freed@android.com static unsigned MakeCode(Code code) { 14419a89f287f3af6fd34470a7aab92a989109d513freed@android.com return (code << kCodeShift) | kCodeShift2_Bits; 14519a89f287f3af6fd34470a7aab92a989109d513freed@android.com } 146fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 147f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com void appendInt(int32_t); 148f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com void appendWord(ForthWord*); 14919a89f287f3af6fd34470a7aab92a989109d513freed@android.com void appendIF(); 15019a89f287f3af6fd34470a7aab92a989109d513freed@android.com bool appendELSE(); 15119a89f287f3af6fd34470a7aab92a989109d513freed@android.com bool appendTHEN(); 152f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com void done(); 153f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 154f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com intptr_t* detach() { 155f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->done(); 156f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return fData.detach(); 157f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 158f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com intptr_t* begin() { 159f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->done(); 160f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return fData.begin(); 161f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 162fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 163f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com static void Exec(const intptr_t*, ForthEngine*); 164f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 165f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comprivate: 166f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkTDArray<intptr_t> fData; 16719a89f287f3af6fd34470a7aab92a989109d513freed@android.com SkTDStack<size_t> fIfStack; 168f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com}; 169f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 170f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid FCode::appendInt(int32_t value) { 171f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if ((value & 3) == 0) { 172f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *fData.append() = value | kDataClear2_Bits; 17319a89f287f3af6fd34470a7aab92a989109d513freed@android.com } else if ((value << 2 >> 2) == value) { 17419a89f287f3af6fd34470a7aab92a989109d513freed@android.com *fData.append() = (value << 2) | kDataShift2_Bits; 175f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 176f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com intptr_t* p = fData.append(2); 177f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *p++ = (kPushInt_Code << 2) | kCodeShift2_Bits; 178f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *p++ = value; 179f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 180f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 181f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 182f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid FCode::appendWord(ForthWord* word) { 183f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT((reinterpret_cast<intptr_t>(word) & 3) == 0); 184f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *fData.append() = reinterpret_cast<intptr_t>(word); 185f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 186f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 18719a89f287f3af6fd34470a7aab92a989109d513freed@android.comvoid FCode::appendIF() { 18819a89f287f3af6fd34470a7aab92a989109d513freed@android.com size_t ifIndex = fData.count(); 18919a89f287f3af6fd34470a7aab92a989109d513freed@android.com fIfStack.push(ifIndex); 19019a89f287f3af6fd34470a7aab92a989109d513freed@android.com *fData.append() = MakeCode(kIF_Code); 19119a89f287f3af6fd34470a7aab92a989109d513freed@android.com} 19219a89f287f3af6fd34470a7aab92a989109d513freed@android.com 19319a89f287f3af6fd34470a7aab92a989109d513freed@android.combool FCode::appendELSE() { 19419a89f287f3af6fd34470a7aab92a989109d513freed@android.com if (fIfStack.empty()) { 19519a89f287f3af6fd34470a7aab92a989109d513freed@android.com return false; 19619a89f287f3af6fd34470a7aab92a989109d513freed@android.com } 19719a89f287f3af6fd34470a7aab92a989109d513freed@android.com 19819a89f287f3af6fd34470a7aab92a989109d513freed@android.com size_t elseIndex = fData.count(); 19919a89f287f3af6fd34470a7aab92a989109d513freed@android.com *fData.append() = MakeCode(kELSE_Code); 20019a89f287f3af6fd34470a7aab92a989109d513freed@android.com 20119a89f287f3af6fd34470a7aab92a989109d513freed@android.com size_t ifIndex = fIfStack.top(); 20219a89f287f3af6fd34470a7aab92a989109d513freed@android.com // record the offset in the data part of the if-code 20319a89f287f3af6fd34470a7aab92a989109d513freed@android.com fData[ifIndex] |= (elseIndex - ifIndex) << kCodeDataShift; 20419a89f287f3af6fd34470a7aab92a989109d513freed@android.com 20519a89f287f3af6fd34470a7aab92a989109d513freed@android.com // now reuse this IfStack entry to track the else 20619a89f287f3af6fd34470a7aab92a989109d513freed@android.com fIfStack.top() = elseIndex; 20719a89f287f3af6fd34470a7aab92a989109d513freed@android.com return true; 20819a89f287f3af6fd34470a7aab92a989109d513freed@android.com} 20919a89f287f3af6fd34470a7aab92a989109d513freed@android.com 21019a89f287f3af6fd34470a7aab92a989109d513freed@android.combool FCode::appendTHEN() { 21119a89f287f3af6fd34470a7aab92a989109d513freed@android.com if (fIfStack.empty()) { 21219a89f287f3af6fd34470a7aab92a989109d513freed@android.com return false; 21319a89f287f3af6fd34470a7aab92a989109d513freed@android.com } 21419a89f287f3af6fd34470a7aab92a989109d513freed@android.com 21519a89f287f3af6fd34470a7aab92a989109d513freed@android.com // this is either an IF or an ELSE 21619a89f287f3af6fd34470a7aab92a989109d513freed@android.com size_t index = fIfStack.top(); 21719a89f287f3af6fd34470a7aab92a989109d513freed@android.com // record the offset in the data part of the code 21819a89f287f3af6fd34470a7aab92a989109d513freed@android.com fData[index] |= (fData.count() - index - 1) << kCodeDataShift; 21919a89f287f3af6fd34470a7aab92a989109d513freed@android.com 22019a89f287f3af6fd34470a7aab92a989109d513freed@android.com fIfStack.pop(); 22119a89f287f3af6fd34470a7aab92a989109d513freed@android.com return true; 22219a89f287f3af6fd34470a7aab92a989109d513freed@android.com} 22319a89f287f3af6fd34470a7aab92a989109d513freed@android.com 224f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid FCode::done() { 225f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *fData.append() = (kDone_Code << 2) | kCodeShift2_Bits; 226f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 227f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 228f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid FCode::Exec(const intptr_t* curr, ForthEngine* engine) { 229f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com for (;;) { 230f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com intptr_t c = *curr++; 231f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com switch (c & 3) { 232f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com case kWord_Bits: 233f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com reinterpret_cast<ForthWord*>(c)->exec(engine); 234f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 235f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com case kDataClear2_Bits: 236f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com engine->push(c & ~3); 237f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 238f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com case kDataShift2_Bits: 239f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com engine->push(c >> 2); 240f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 241f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com case kCodeShift2_Bits: 24219a89f287f3af6fd34470a7aab92a989109d513freed@android.com switch (GetCode(c)) { 243f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com case kPushInt_Code: 244f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com engine->push(*curr++); 245f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 24619a89f287f3af6fd34470a7aab92a989109d513freed@android.com case kIF_Code: 24719a89f287f3af6fd34470a7aab92a989109d513freed@android.com if (!engine->pop()) { 24819a89f287f3af6fd34470a7aab92a989109d513freed@android.com // takes us past the ELSE or THEN 24919a89f287f3af6fd34470a7aab92a989109d513freed@android.com curr += GetCodeData(c); 25019a89f287f3af6fd34470a7aab92a989109d513freed@android.com } 25119a89f287f3af6fd34470a7aab92a989109d513freed@android.com break; 25219a89f287f3af6fd34470a7aab92a989109d513freed@android.com case kELSE_Code: 25319a89f287f3af6fd34470a7aab92a989109d513freed@android.com // takes us past the THEN 25419a89f287f3af6fd34470a7aab92a989109d513freed@android.com curr += GetCodeData(c); 25519a89f287f3af6fd34470a7aab92a989109d513freed@android.com break; 256f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com case kDone_Code: 257f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return; 258f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 259f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 260f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 261f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 262f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 263f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 264f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/////////////////////////////////////////////////////////////////////////////// 265f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 266f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comclass CustomWord : public ForthWord { 267f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.compublic: 268f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com // we assume ownership of code[] 269f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com CustomWord(intptr_t code[]) : fCode(code) {} 270f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com virtual ~CustomWord() { sk_free(fCode); } 271f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 272f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com virtual void exec(ForthEngine* engine) { 273f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com FCode::Exec(fCode, engine); 274f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 275f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 276f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comprivate: 277f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com intptr_t* fCode; 278f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com}; 279f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 280f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/////////////////////////////////////////////////////////////////////////////// 281f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 28219a89f287f3af6fd34470a7aab92a989109d513freed@android.comForthParser::ForthParser() : fDict(4096) { 28319a89f287f3af6fd34470a7aab92a989109d513freed@android.com this->addStdWords(); 28419a89f287f3af6fd34470a7aab92a989109d513freed@android.com} 285f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 28619a89f287f3af6fd34470a7aab92a989109d513freed@android.comForthParser::~ForthParser() { 2871d5aaa8ef65f312508e41ec458d4a6457f9cd39ereed@google.com SkTDict<ForthWord*>::Iter iter(fDict); 2881d5aaa8ef65f312508e41ec458d4a6457f9cd39ereed@google.com ForthWord* word; 2891d5aaa8ef65f312508e41ec458d4a6457f9cd39ereed@google.com while (iter.next(&word)) { 2901d5aaa8ef65f312508e41ec458d4a6457f9cd39ereed@google.com delete word; 2911d5aaa8ef65f312508e41ec458d4a6457f9cd39ereed@google.com } 29219a89f287f3af6fd34470a7aab92a989109d513freed@android.com} 293f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 294f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic const char* parse_error(const char msg[]) { 295f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkDebugf("-- parser error: %s\n", msg); 296f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return NULL; 297f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 298f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 299f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/** returns true if c is whitespace, including null 300f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com */ 301f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic bool is_ws(int c) { 302f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return c <= ' '; 303f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 304f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 305f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic const char* parse_token(const char** text, size_t* len) { 306f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com const char* s = *text; 307f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com while (is_ws(*s)) { 308f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (0 == *s) { 309f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return NULL; 310f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 311f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com s++; 312f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 313f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com const char* token = s++; 314f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com while (!is_ws(*s)) { 315f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com s++; 316f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 317f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *text = s; 318f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *len = s - token; 319f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return token; 320f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 321f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 322f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic bool is_digit(int c) { return (unsigned)(c - '0') <= 9; } 323f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic int hex_val(int c) { 324f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (is_digit(c)) { 325f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return c - '0'; 326f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 327f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (c <= 'Z') { 328f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return 10 + c - 'A'; 329f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else { 330f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return 10 + c - 'a'; 331f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 332f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 333f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 334f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 335f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic bool parse_num(const char str[], size_t len, int32_t* numBits) { 336f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (1 == len && !is_digit(*str)) { 337f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return false; 338f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 339f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com const char* start = str; 340f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com int32_t num = 0; 341f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com bool neg = false; 342f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (*str == '-') { 343f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com neg = true; 344f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str += 1; 345f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else if (*str == '#') { 346f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str++; 347f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com while (str - start < len) { 348f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com num = num*16 + hex_val(*str); 349f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str += 1; 350f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 351f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *numBits = num; 352f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return true; 353f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 354f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 355f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com while (is_digit(*str)) { 356f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com num = 10*num + *str - '0'; 357f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str += 1; 358f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 359f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT(str - start <= len); 360f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (str - start == len) { 361f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (neg) { 362f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com num = -num; 363f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 364f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *numBits = num; 365f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return true; 366f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 367f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com // if we're not done with the token then the next char must be a decimal 368f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (*str != '.') { 369f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return false; 370f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 371f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str += 1; 372f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com float x = num; 373f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com float denom = 1; 374f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com while (str - start < len && is_digit(*str)) { 375f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com x = 10*x + *str - '0'; 376f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com denom *= 10; 377f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str += 1; 378f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 379f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com x /= denom; 380f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (str - start == len) { 381f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (neg) { 382f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com x = -x; 383f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 384f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com *numBits = f2i_bits(x); 385f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return true; 386f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 387f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return false; 388f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 389f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 390f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comstatic const char* parse_comment(const char text[]) { 391f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkASSERT(*text == '('); 392f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com while (')' != *++text) { 393f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (0 == *text) { 394f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return NULL; 395f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 396f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 397f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return text + 1; // skip past the closing ')' 398f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 399f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 400f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comconst char* ForthParser::parse(const char text[], FCode* code) { 401f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com for (;;) { 402f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com size_t len; 403f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com const char* token = parse_token(&text, &len); 404f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (NULL == token) { 405f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 406f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 407f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (1 == len) { 408f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if ('(' == *token) { 409f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com text = parse_comment(token); 410f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (NULL == text) { 411f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return NULL; 412f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 413f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com continue; 414f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 415f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (';' == *token) { 416f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com break; 417f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 418f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (':' == *token) { 419f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com token = parse_token(&text, &len); 420f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (NULL == token) { 421f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return parse_error("missing name after ':'"); 422f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 423f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com FCode subCode; 424f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com text = this->parse(text, &subCode); 425f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (NULL == text) { 426f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return NULL; 427f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 428f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com this->add(token, len, new CustomWord(subCode.detach())); 429f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com continue; 430f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 431f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 432f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com int32_t num; 433f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (parse_num(token, len, &num)) { 434f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com // note that num is just the bit representation of the float 435f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com code->appendInt(num); 436f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else if (2 == len && memcmp(token, "IF", 2) == 0) { 437f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com code->appendIF(); 43819a89f287f3af6fd34470a7aab92a989109d513freed@android.com } else if (4 == len && memcmp(token, "ELSE", 4) == 0) { 439f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (!code->appendELSE()) { 440f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return parse_error("ELSE with no matching IF"); 441f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 44219a89f287f3af6fd34470a7aab92a989109d513freed@android.com } else if (4 == len && memcmp(token, "THEN", 4) == 0) { 443f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (!code->appendTHEN()) { 444f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return parse_error("THEN with no matching IF"); 445f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 446f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } else{ 447f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com ForthWord* word = this->find(token, len); 448f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (NULL == word) { 449f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com SkString str(token, len); 450f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com str.prepend("unknown word "); 451f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return parse_error(str.c_str()); 452f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 453f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com code->appendWord(word); 454f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 455f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 456f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return text; 457f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 458f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 459f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com/////////////////////////////////////////////////////////////////////////////// 460f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 461f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comclass ForthEnv::Impl { 462f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.compublic: 463f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com ForthParser fParser; 464f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com FCode fBuilder; 465f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com}; 466f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 467f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comForthEnv::ForthEnv() { 468f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fImpl = new Impl; 469f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 470f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 471f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comForthEnv::~ForthEnv() { 472f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com delete fImpl; 473f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 474f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 475f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEnv::addWord(const char name[], ForthWord* word) { 476f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fImpl->fParser.addWord(name, word); 477f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 478f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 479f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEnv::parse(const char text[]) { 480f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com fImpl->fParser.parse(text, &fImpl->fBuilder); 481f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 482f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 483f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comForthWord* ForthEnv::findWord(const char name[]) { 484f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com return fImpl->fParser.find(name, strlen(name)); 485f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 486f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 487f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEnv::run(ForthOutput* output) { 488f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com ForthEngine engine(output); 489f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com FCode::Exec(fImpl->fBuilder.begin(), &engine); 490f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 491f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 492f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com#if 0 493f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.comvoid ForthEnv::run(const char text[], ForthOutput* output) { 494f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com FCode builder; 495f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com 496f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com if (fImpl->fParser.parse(text, &builder)) { 497f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com ForthEngine engine(output); 498f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com FCode::Exec(builder.begin(), &engine); 499f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com } 500f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com} 501f56e295e88f4ed42f4c94c54d5fc544ed0f45f18reed@android.com#endif 502