|  |  | 
|  | /* | 
|  | * Copyright 2011 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef Forth_DEFINED | 
|  | #define Forth_DEFINED | 
|  |  | 
|  | #include "SkTypes.h" | 
|  |  | 
|  | class ForthOutput { | 
|  | public: | 
|  | virtual void show(const char output[]) = 0; | 
|  | }; | 
|  |  | 
|  | union FloatIntDual { | 
|  | int32_t fInt; | 
|  | float   fFloat; | 
|  | }; | 
|  |  | 
|  | static inline int32_t f2i_bits(float x) { | 
|  | FloatIntDual d; | 
|  | d.fFloat = x; | 
|  | return d.fInt; | 
|  | } | 
|  |  | 
|  | static inline float i2f_bits(int32_t x) { | 
|  | FloatIntDual d; | 
|  | d.fInt = x; | 
|  | return d.fFloat; | 
|  | } | 
|  |  | 
|  | class ForthEngine { | 
|  | public: | 
|  | ForthEngine(ForthOutput*); | 
|  | ~ForthEngine(); | 
|  |  | 
|  | int         depth() const { return fStackStop - fStackCurr; } | 
|  | void        clearStack() { fStackCurr = fStackStop; } | 
|  |  | 
|  | void        push(intptr_t value); | 
|  | intptr_t    top() const { return this->peek(0); } | 
|  | intptr_t    peek(size_t index) const; | 
|  | void        setTop(intptr_t value); | 
|  | intptr_t    pop(); | 
|  |  | 
|  | void        fpush(float value) { this->push(f2i_bits(value)); } | 
|  | float       fpeek(size_t i) const { return i2f_bits(this->fpeek(i)); } | 
|  | float       ftop() const { return i2f_bits(this->top()); } | 
|  | void        fsetTop(float value) { this->setTop(f2i_bits(value)); } | 
|  | float       fpop() { return i2f_bits(this->pop()); } | 
|  |  | 
|  | void sendOutput(const char text[]); | 
|  |  | 
|  | private: | 
|  | ForthOutput* fOutput; | 
|  | intptr_t*   fStackBase; | 
|  | intptr_t*   fStackCurr; | 
|  | intptr_t*   fStackStop; | 
|  |  | 
|  | void signal_error(const char msg[]) const { | 
|  | SkDebugf("ForthEngine error: %s\n", msg); | 
|  | } | 
|  | }; | 
|  |  | 
|  | struct ForthCallBlock { | 
|  | const intptr_t* in_data; | 
|  | size_t          in_count; | 
|  | intptr_t*       out_data; | 
|  | size_t          out_count; | 
|  | size_t          out_depth; | 
|  | }; | 
|  |  | 
|  | class ForthWord { | 
|  | public: | 
|  | virtual ~ForthWord() {} | 
|  | virtual void exec(ForthEngine*) = 0; | 
|  |  | 
|  | // todo: return error state of the engine | 
|  | void call(ForthCallBlock*); | 
|  | }; | 
|  |  | 
|  | class ForthEnv { | 
|  | public: | 
|  | ForthEnv(); | 
|  | ~ForthEnv(); | 
|  |  | 
|  |  | 
|  | void addWord(const char name[], ForthWord*); | 
|  |  | 
|  | void parse(const char code[]); | 
|  |  | 
|  | ForthWord* findWord(const char name[]); | 
|  |  | 
|  | void run(ForthOutput* = NULL); | 
|  |  | 
|  | private: | 
|  | class Impl; | 
|  | Impl* fImpl; | 
|  | }; | 
|  |  | 
|  | #endif |