建立映射關係 首先變數表應該採取一種將變數名對應到變數的方法,這種方法大致兩種,一種是將變數名parse時hash成數字,一種是直接建立string value的map。 + int |速度快|動態性弱,無法實現諸如getvar("abc")的功能 + string|速度慢|動態性強 其次選擇數據結
建立映射關係
首先變數表應該採取一種將變數名對應到變數的方法,這種方法大致兩種,一種是將變數名parse時hash成數字,一種是直接建立string->value的map。
- int|速度快|動態性弱,無法實現諸如getvar("abc")的功能
- string|速度慢|動態性強
其次選擇數據結構 - 平衡樹|速度慢,費空間
- hash表|速度快,省空間
數組|速度巨快,費空間(因為變數hash後的數字是不連續的)
註:當然也可以採用那個類似編譯型語言的在棧上分配記憶體,不過這樣犧牲了語言的動態性
處理繼承關係
-----
我們使用鏈表結構,每一個塊狀作用域指向父作用域,介面實現getvar()方法,遞歸查找變數,利用exception機制處理未定義變數行為。class VariableTable { public: VariableTable *prev; unordered_map<int,Value*> table; VariableTable() { prev = nullptr; } VariableTable(VariableTable * t) { prev = t; } void defineVar( int name ) { auto t = table.find(name); if (t != table.end()) throw RedefinedVariableException(name); this->table.emplace(name, new Value()); } Value & getVar( const int & name ) { auto t = table.find(name); if (t == table.end()) { if (prev == nullptr) throw UndefinedVariableException(name); else return prev->getVar(name); } else { return *t->second; } } ~VariableTable() { for (auto &x : table) delete x.second; } };
### Object類型的屬性
我們完全可以採用類似思路。
const int __proto__ = getNameInt("__proto__"); class Object { public: bool mark; unordered_map<int, Value*> data; Object() { } Value & __getVar(int name) { auto t = data.find(name); if (t != data.end())return *t->second; else { auto pro = data.find(__proto__); if (pro == data.end() || pro->second->type != Value::Type::Obj) throw UndefinedVariableException(1); else return pro->second->data.Obj->__getVar(name); } } inline Value & getVar(int name) { try { return this->__getVar(name); } catch (UndefinedVariableException) { data.emplace(name, new Value()); return this->__getVar(name); } } ~Object() { for (auto &x : data) delete x.second; } };