Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: forth/Forth.cpp

Issue 1559823002: remove forth experiment (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « forth/Forth.h ('k') | forth/ForthParser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: forth/Forth.cpp
diff --git a/forth/Forth.cpp b/forth/Forth.cpp
deleted file mode 100644
index 1dd4c73e4a9ee1753c30211015e356c88c1df6a0..0000000000000000000000000000000000000000
--- a/forth/Forth.cpp
+++ /dev/null
@@ -1,501 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "Forth.h"
-#include "ForthParser.h"
-#include "SkTDArray.h"
-#include "SkString.h"
-#include "SkTDStack.h"
-
-ForthEngine::ForthEngine(ForthOutput* output) : fOutput(output) {
- size_t size = 32 * sizeof(intptr_t);
- fStackBase = reinterpret_cast<intptr_t*>(sk_malloc_throw(size));
- fStackStop = fStackBase + size/sizeof(intptr_t);
- fStackCurr = fStackStop;
-}
-
-ForthEngine::~ForthEngine() {
- sk_free(fStackBase);
-}
-
-void ForthEngine::sendOutput(const char text[]) {
- if (fOutput) {
- fOutput->show(text);
- } else {
- SkDebugf("%s", text);
- }
-}
-
-void ForthEngine::push(intptr_t value) {
- if (fStackCurr > fStackBase) {
- SkASSERT(fStackCurr <= fStackStop && fStackCurr > fStackBase);
- *--fStackCurr = value;
- } else {
- this->signal_error("overflow");
- }
-}
-
-intptr_t ForthEngine::peek(size_t index) const {
- SkASSERT(fStackCurr < fStackStop && fStackCurr >= fStackBase);
- if (fStackCurr + index < fStackStop) {
- return fStackCurr[index];
- } else {
- this->signal_error("peek out of range");
- return 0x80000001;
- }
-}
-
-void ForthEngine::setTop(intptr_t value) {
- if (fStackCurr < fStackStop) {
- SkASSERT(fStackCurr < fStackStop && fStackCurr >= fStackBase);
- *fStackCurr = value;
- } else {
- this->signal_error("underflow");
- }
-}
-
-intptr_t ForthEngine::pop() {
- if (fStackCurr < fStackStop) {
- SkASSERT(fStackCurr < fStackStop && fStackCurr >= fStackBase);
- return *fStackCurr++;
- } else {
- this->signal_error("underflow");
- return 0x80000001;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void ForthWord::call(ForthCallBlock* block) {
- ForthEngine engine(NULL);
-
- // setup the initial stack with the callers input data
- if (block) {
- // walk the array backwards, so that the top of the stack is data[0]
- for (size_t i = 0; i < block->in_count; i++) {
- engine.push(block->in_data[i]);
- }
- }
-
- // now invoke the word
- this->exec(&engine);
-
- // now copy back the stack into the caller's output data
- if (block) {
- size_t n = engine.depth();
- block->out_depth = n;
- if (n > block->out_count) {
- n = block->out_count;
- }
- for (size_t i = 0; i < n; i++) {
- block->out_data[i] = engine.peek(i);
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-/*
- reading an initial 32bit value from the code stream:
-
- xxxxxxxx xxxxxxxx xxxxxxxx xxxxxx00
-
- Those last two bits are always 0 for a word, so we set those bits for other
- opcodes
-
- 00 -- execute this word
- 01 -- push (value & ~3) on the data stack
- 10 -- push value >> 2 on the data stack (sign extended)
- 11 -- switch (value >>> 2) for Code
- */
-
-class FCode {
-public:
- enum {
- kCodeShift = 2,
- kCodeMask = 7,
- kCodeDataShift = 5
- };
- static unsigned GetCode(intptr_t c) {
- return ((uint32_t)c >> kCodeShift) & kCodeMask;
- }
- static unsigned GetCodeData(intptr_t c) {
- return (uint32_t)c >> kCodeDataShift;
- }
-
- enum Bits {
- kWord_Bits = 0, // must be zero for function address
- kDataClear2_Bits = 1,
- kDataShift2_Bits = 2,
- kCodeShift2_Bits = 3
- };
-
- enum Code {
- kPushInt_Code, // for data that needs more than 30 bits
- kIF_Code,
- kELSE_Code,
- kDone_Code
- };
- static unsigned MakeCode(Code code) {
- return (code << kCodeShift) | kCodeShift2_Bits;
- }
-
- void appendInt(int32_t);
- void appendWord(ForthWord*);
- void appendIF();
- bool appendELSE();
- bool appendTHEN();
- void done();
-
- intptr_t* detach() {
- this->done();
- return fData.detach();
- }
- intptr_t* begin() {
- this->done();
- return fData.begin();
- }
-
- static void Exec(const intptr_t*, ForthEngine*);
-
-private:
- SkTDArray<intptr_t> fData;
- SkTDStack<size_t> fIfStack;
-};
-
-void FCode::appendInt(int32_t value) {
- if ((value & 3) == 0) {
- *fData.append() = value | kDataClear2_Bits;
- } else if ((value << 2 >> 2) == value) {
- *fData.append() = (value << 2) | kDataShift2_Bits;
- } else {
- intptr_t* p = fData.append(2);
- *p++ = (kPushInt_Code << 2) | kCodeShift2_Bits;
- *p++ = value;
- }
-}
-
-void FCode::appendWord(ForthWord* word) {
- SkASSERT((reinterpret_cast<intptr_t>(word) & 3) == 0);
- *fData.append() = reinterpret_cast<intptr_t>(word);
-}
-
-void FCode::appendIF() {
- size_t ifIndex = fData.count();
- fIfStack.push(ifIndex);
- *fData.append() = MakeCode(kIF_Code);
-}
-
-bool FCode::appendELSE() {
- if (fIfStack.empty()) {
- return false;
- }
-
- size_t elseIndex = fData.count();
- *fData.append() = MakeCode(kELSE_Code);
-
- size_t ifIndex = fIfStack.top();
- // record the offset in the data part of the if-code
- fData[ifIndex] |= (elseIndex - ifIndex) << kCodeDataShift;
-
- // now reuse this IfStack entry to track the else
- fIfStack.top() = elseIndex;
- return true;
-}
-
-bool FCode::appendTHEN() {
- if (fIfStack.empty()) {
- return false;
- }
-
- // this is either an IF or an ELSE
- size_t index = fIfStack.top();
- // record the offset in the data part of the code
- fData[index] |= (fData.count() - index - 1) << kCodeDataShift;
-
- fIfStack.pop();
- return true;
-}
-
-void FCode::done() {
- *fData.append() = (kDone_Code << 2) | kCodeShift2_Bits;
-}
-
-void FCode::Exec(const intptr_t* curr, ForthEngine* engine) {
- for (;;) {
- intptr_t c = *curr++;
- switch (c & 3) {
- case kWord_Bits:
- reinterpret_cast<ForthWord*>(c)->exec(engine);
- break;
- case kDataClear2_Bits:
- engine->push(c & ~3);
- break;
- case kDataShift2_Bits:
- engine->push(c >> 2);
- break;
- case kCodeShift2_Bits:
- switch (GetCode(c)) {
- case kPushInt_Code:
- engine->push(*curr++);
- break;
- case kIF_Code:
- if (!engine->pop()) {
- // takes us past the ELSE or THEN
- curr += GetCodeData(c);
- }
- break;
- case kELSE_Code:
- // takes us past the THEN
- curr += GetCodeData(c);
- break;
- case kDone_Code:
- return;
- }
- break;
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class CustomWord : public ForthWord {
-public:
- // we assume ownership of code[]
- CustomWord(intptr_t code[]) : fCode(code) {}
- virtual ~CustomWord() { sk_free(fCode); }
-
- virtual void exec(ForthEngine* engine) {
- FCode::Exec(fCode, engine);
- }
-
-private:
- intptr_t* fCode;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-ForthParser::ForthParser() : fDict(4096) {
- this->addStdWords();
-}
-
-ForthParser::~ForthParser() {
- SkTDict<ForthWord*>::Iter iter(fDict);
- ForthWord* word;
- while (iter.next(&word)) {
- delete word;
- }
-}
-
-static const char* parse_error(const char msg[]) {
- SkDebugf("-- parser error: %s\n", msg);
- return NULL;
-}
-
-/** returns true if c is whitespace, including null
- */
-static bool is_ws(int c) {
- return c <= ' ';
-}
-
-static const char* parse_token(const char** text, size_t* len) {
- const char* s = *text;
- while (is_ws(*s)) {
- if (0 == *s) {
- return NULL;
- }
- s++;
- }
- const char* token = s++;
- while (!is_ws(*s)) {
- s++;
- }
- *text = s;
- *len = s - token;
- return token;
-}
-
-static bool is_digit(int c) { return (unsigned)(c - '0') <= 9; }
-static int hex_val(int c) {
- if (is_digit(c)) {
- return c - '0';
- } else {
- if (c <= 'Z') {
- return 10 + c - 'A';
- } else {
- return 10 + c - 'a';
- }
- }
-}
-
-static bool parse_num(const char str[], size_t len, int32_t* numBits) {
- if (1 == len && !is_digit(*str)) {
- return false;
- }
- const char* start = str;
- int32_t num = 0;
- bool neg = false;
- if (*str == '-') {
- neg = true;
- str += 1;
- } else if (*str == '#') {
- str++;
- while (str - start < len) {
- num = num*16 + hex_val(*str);
- str += 1;
- }
- *numBits = num;
- return true;
- }
-
- while (is_digit(*str)) {
- num = 10*num + *str - '0';
- str += 1;
- }
- SkASSERT(str - start <= len);
- if (str - start == len) {
- if (neg) {
- num = -num;
- }
- *numBits = num;
- return true;
- }
- // if we're not done with the token then the next char must be a decimal
- if (*str != '.') {
- return false;
- }
- str += 1;
- float x = num;
- float denom = 1;
- while (str - start < len && is_digit(*str)) {
- x = 10*x + *str - '0';
- denom *= 10;
- str += 1;
- }
- x /= denom;
- if (str - start == len) {
- if (neg) {
- x = -x;
- }
- *numBits = f2i_bits(x);
- return true;
- }
- return false;
-}
-
-static const char* parse_comment(const char text[]) {
- SkASSERT(*text == '(');
- while (')' != *++text) {
- if (0 == *text) {
- return NULL;
- }
- }
- return text + 1; // skip past the closing ')'
-}
-
-const char* ForthParser::parse(const char text[], FCode* code) {
- for (;;) {
- size_t len;
- const char* token = parse_token(&text, &len);
- if (NULL == token) {
- break;
- }
- if (1 == len) {
- if ('(' == *token) {
- text = parse_comment(token);
- if (NULL == text) {
- return NULL;
- }
- continue;
- }
- if (';' == *token) {
- break;
- }
- if (':' == *token) {
- token = parse_token(&text, &len);
- if (NULL == token) {
- return parse_error("missing name after ':'");
- }
- FCode subCode;
- text = this->parse(text, &subCode);
- if (NULL == text) {
- return NULL;
- }
- this->add(token, len, new CustomWord(subCode.detach()));
- continue;
- }
- }
- int32_t num;
- if (parse_num(token, len, &num)) {
- // note that num is just the bit representation of the float
- code->appendInt(num);
- } else if (2 == len && memcmp(token, "IF", 2) == 0) {
- code->appendIF();
- } else if (4 == len && memcmp(token, "ELSE", 4) == 0) {
- if (!code->appendELSE()) {
- return parse_error("ELSE with no matching IF");
- }
- } else if (4 == len && memcmp(token, "THEN", 4) == 0) {
- if (!code->appendTHEN()) {
- return parse_error("THEN with no matching IF");
- }
- } else{
- ForthWord* word = this->find(token, len);
- if (NULL == word) {
- SkString str(token, len);
- str.prepend("unknown word ");
- return parse_error(str.c_str());
- }
- code->appendWord(word);
- }
- }
- return text;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class ForthEnv::Impl {
-public:
- ForthParser fParser;
- FCode fBuilder;
-};
-
-ForthEnv::ForthEnv() {
- fImpl = new Impl;
-}
-
-ForthEnv::~ForthEnv() {
- delete fImpl;
-}
-
-void ForthEnv::addWord(const char name[], ForthWord* word) {
- fImpl->fParser.addWord(name, word);
-}
-
-void ForthEnv::parse(const char text[]) {
- fImpl->fParser.parse(text, &fImpl->fBuilder);
-}
-
-ForthWord* ForthEnv::findWord(const char name[]) {
- return fImpl->fParser.find(name, strlen(name));
-}
-
-void ForthEnv::run(ForthOutput* output) {
- ForthEngine engine(output);
- FCode::Exec(fImpl->fBuilder.begin(), &engine);
-}
-
-#if 0
-void ForthEnv::run(const char text[], ForthOutput* output) {
- FCode builder;
-
- if (fImpl->fParser.parse(text, &builder)) {
- ForthEngine engine(output);
- FCode::Exec(builder.begin(), &engine);
- }
-}
-#endif
« no previous file with comments | « forth/Forth.h ('k') | forth/ForthParser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698