diff options
-rw-r--r-- | evaluate.cpp | 39 | ||||
-rw-r--r-- | evaluate.h | 10 | ||||
-rw-r--r-- | test.squig | 17 |
3 files changed, 61 insertions, 5 deletions
diff --git a/evaluate.cpp b/evaluate.cpp index e808b95..bc02a8f 100644 --- a/evaluate.cpp +++ b/evaluate.cpp @@ -26,6 +26,11 @@ Value::Value(const string &strval) :type(Type::string),strval(strval){} Value::Value(ScopeVal *scopeval) :type(Type::scope),scopeval(scopeval){} +Value::Value(Type type,Assembly *asmval):type(type),asmval(asmval){ + if(type!=Type::lazy&&type!=Type::function){ + throw runtime_error("Value(type,asmval) called with invalid type "+to_string((int)type)); + } +} Value::Value(const Value &other):type(other.type),numval(other.numval),strval(other.strval){ if(other.scopeval){ scopeval=new ScopeVal(*other.scopeval); @@ -124,11 +129,19 @@ Assembly::Instruction::Instruction(Type type,int nargs):type(type),nargs(nargs){ throw runtime_error("Instruction(type,nargs) called with invalid type "+to_string((int)type)); } } +Assembly::Instruction::Instruction(Type type,Assembly *asmval):type(type),asmval(asmval){ + if(type!=Type::pushfunc){ + throw runtime_error("Instruction(type,asmval) called with invalid type "+to_string((int)type)); + } +} Assembly::Instruction::Instruction(const Instruction &other) :type(other.type),num(other.num),str(other.str),name(other.name),nargs(other.nargs){ if(other.scope){ scope=new ScopeDef(*other.scope); } + if(other.asmval){ + asmval=new Assembly(*other.asmval); + } } Assembly::Instruction::Instruction(Instruction &&other) :type(other.type),num(other.num),str(other.str), @@ -137,6 +150,10 @@ Assembly::Instruction::Instruction(Instruction &&other) other.type=Type::pushnil; other.scope=nullptr; } + if(other.asmval){ + other.type=Type::pushnil; + other.asmval=nullptr; + } } Assembly::Instruction::~Instruction(){ if(scope)delete scope; @@ -203,10 +220,8 @@ void Assembly::codegen(const Expression &expr){ if(expr.type==Expression::Type::dive){ assert(expr.scope.type==ScopeDef::Type::direct); listing.emplace_back(Instruction::Type::enter); - listing.emplace_back(Instruction::Type::pop); codegen(expr.scope.body); listing.emplace_back(Instruction::Type::leave); - listing.emplace_back(Instruction::Type::pushnil); } break; @@ -219,7 +234,6 @@ void Assembly::codegen(const Expression &expr){ break; case Expression::Type::scope: - // listing.emplace_back(Instruction::Type::pushscope,new ScopeDef(expr.scope)); switch(expr.scope.type){ case ScopeDef::Type::direct: assert(expr.scope.args.size()==0); @@ -230,11 +244,16 @@ void Assembly::codegen(const Expression &expr){ break; case ScopeDef::Type::lazy: + throw runtime_error("Lazy scopes not implemented"); + case ScopeDef::Type::function: - listing.emplace_back(Instruction::Type::pushscope,new ScopeDef(expr.scope)); + listing.emplace_back(Instruction::Type::pushfunc,new Assembly(expr.scope)); break; } break; + + case Expression::Type::cond: + throw runtime_error("Conditions not implemented"); } } @@ -242,14 +261,25 @@ Assembly::Assembly(const StatementList &stl){ codegen(stl); } +Assembly::Assembly(const ScopeDef &scopeDef){ + for(int i=scopeDef.args.size()-1;i>=0;i--){ + listing.emplace_back(Instruction::Type::create,scopeDef.args[i]); + } + codegen(scopeDef.body); +} + ostream& operator<<(ostream &os,const Assembly &as){ + static int depth=0; + depth++; for(const Assembly::Instruction &ins : as.listing){ + os<<string((depth-1)*2,' '); switch(ins.type){ case Assembly::Instruction::Type::pushnil: os<<"pushnil\n"; break; case Assembly::Instruction::Type::pushnum: os<<"pushnum "<<ins.num<<"\n"; break; case Assembly::Instruction::Type::pushstr: os<<"pushstr \""<<ins.str<<"\"\n"; break; case Assembly::Instruction::Type::pushscope: os<<"pushscope "<<*ins.scope<<"\n"; break; + case Assembly::Instruction::Type::pushfunc: os<<"pushfunc:\n"<<*ins.asmval; break; case Assembly::Instruction::Type::newscope: os<<"newscope\n"; break; case Assembly::Instruction::Type::pop: os<<"pop\n"; break; case Assembly::Instruction::Type::swap: os<<"swap\n"; break; @@ -266,5 +296,6 @@ ostream& operator<<(ostream &os,const Assembly &as){ case Assembly::Instruction::Type::call: os<<"call "<<ins.nargs<<"\n"; break; } } + depth--; return os; } @@ -23,6 +23,7 @@ public: class ScopeVal; +class Assembly; class Value{ public: @@ -31,17 +32,21 @@ public: number, // numval string, // strval scope, // scopeval + lazy, // asmval + function, // asmval }; Type type; double numval; string strval; ScopeVal *scopeval=nullptr; + Assembly *asmval=nullptr; Value(); Value(double numval); Value(const string &strval); Value(ScopeVal *scopeval); + Value(Type type,Assembly *asmval); // lazy, function Value(const Value &other); Value(Value &&other); ~Value(); @@ -80,6 +85,7 @@ class Assembly{ pushnum, // [ -> this.num] pushstr, // [ -> this.str] pushscope, // [ -> this.scope] + pushfunc, // [ -> Value(function,this.asmval)] newscope, // [ -> {}] pop, // [x -> ] swap, // [x,y -> y,x] @@ -102,12 +108,14 @@ class Assembly{ ScopeDef *scope=nullptr; string name; int nargs; + Assembly *asmval=nullptr; Instruction(Type type); Instruction(Type type,double num); // pushnum Instruction(Type type,const string &str); // pushstr, create, store, load Instruction(Type type,ScopeDef *scope); // pushscope Instruction(Type type,int nargs); // call + Instruction(Type type,Assembly *asmval); // pushfunc Instruction(const Instruction &other); Instruction(Instruction &&other); ~Instruction(); @@ -122,6 +130,8 @@ class Assembly{ void codegen(const Statement &stmt); void codegen(const Expression &expr); + Assembly(const ScopeDef &scopeDef); + public: Assembly(const StatementList &stl); @@ -1 +1,16 @@ -a := 1 +v := "first v value" + +f := ??{ + puts("function") + x := v +} + +f { + puts(x) +} + +v = "second v value" + +f { + puts(x) +} |