From ca45da0925cabc3bbf0d22d5d23ccb9a25d8e228 Mon Sep 17 00:00:00 2001 From: tomsmeding Date: Fri, 10 Feb 2017 23:35:02 +0100 Subject: Preliminary 'compiling' --- evaluate.cpp | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 4 deletions(-) (limited to 'evaluate.cpp') diff --git a/evaluate.cpp b/evaluate.cpp index ebfb773..550fc49 100644 --- a/evaluate.cpp +++ b/evaluate.cpp @@ -5,12 +5,31 @@ using namespace std; +ExecutionError::ExecutionError(const string &what_arg) + :runtime_error(what_arg){} +ExecutionError::ExecutionError(const char *what_arg) + :runtime_error(what_arg){} + +CompilationError::CompilationError(const string &what_arg) + :runtime_error(what_arg){} +CompilationError::CompilationError(const char *what_arg) + :runtime_error(what_arg){} +CompilationError::CompilationError(Site site,const string &what_arg) + :runtime_error(site.filename+":"+to_string(site.lnum)+":"+to_string(site.linex)+": "+what_arg){} + + +Value::Value() + :type(Type::nil){} Value::Value(double numval) :type(Type::number),numval(numval){} Value::Value(const string &strval) :type(Type::string),strval(strval){} -Value::Value(ScopeVal *scope) - :type(Type::scope),scope(scope){} +Value::Value(ScopeVal *scopeval) + :type(Type::scope),scopeval(scopeval){} + + +ScopeVal::ScopeVal(const ScopeDef &scopeDef) + :scopeDef(scopeDef){} namespace A { @@ -51,9 +70,152 @@ namespace A { it->second.count--; } } + + void unref_all(){ + for(const pair &p : collection){ + p.second.deleter(p.first); + } + } +} + + +Assembly::Instruction::Instruction(Type type):type(type){ + if(type==Type::pushnum||type==Type::pushstr||type==Type::pushscope|| + type==Type::create||type==Type::store||type==Type::load||type==Type::call){ + throw runtime_error("Instruction(type) called with invalid type "+to_string((int)type)); + } +} +Assembly::Instruction::Instruction(Type type,double num):type(type),num(num){ + if(type!=Type::pushnum){ + throw runtime_error("Instruction(type,num) called with invalid type "+to_string((int)type)); + } +} +Assembly::Instruction::Instruction(Type type,const string &arg):type(type){ + if(type==Type::pushstr){ + str=arg; + } else if(type==Type::create||type==Type::store||type==Type::load){ + name=arg; + } else { + throw runtime_error("Instruction(type,string) called with invalid type "+to_string((int)type)); + } +} +Assembly::Instruction::Instruction(Type type,ScopeDef *scope):type(type),scope(scope){ + if(type!=Type::pushscope){ + throw runtime_error("Instruction(type,scope) called with invalid type "+to_string((int)type)); + } +} +Assembly::Instruction::Instruction(Type type,int nargs):type(type),nargs(nargs){ + if(type!=Type::call){ + throw runtime_error("Instruction(type,nargs) called with invalid type "+to_string((int)type)); + } +} + +void Assembly::codegen(const StatementList &stl){ + for(const Statement &stmt : stl){ + codegen(stmt); + } +} + +void Assembly::codegen(const Statement &stmt){ + switch(stmt.type){ + case Statement::Type::create: + codegen(stmt.expr); + listing.emplace_back(Instruction::Type::create,stmt.dstvar); + break; + + case Statement::Type::assign: + codegen(stmt.expr); + listing.emplace_back(Instruction::Type::store,stmt.dstvar); + break; + + case Statement::Type::expression: + codegen(stmt.expr); + listing.emplace_back(Instruction::Type::pop); + break; + } +} + +void Assembly::codegen(const Expression &expr){ + switch(expr.type){ + case Expression::Type::binop: + codegen(expr.args[0]); + codegen(expr.args[1]); + if(expr.name=="+")listing.emplace_back(Instruction::Type::add); + else if(expr.name=="-")listing.emplace_back(Instruction::Type::sub); + else if(expr.name=="*")listing.emplace_back(Instruction::Type::mul); + else if(expr.name=="/")listing.emplace_back(Instruction::Type::div); + else if(expr.name=="%")listing.emplace_back(Instruction::Type::mod); + else throw runtime_error("Unknown binop name '"+expr.name+"'"); + break; + + case Expression::Type::unop: + throw runtime_error("No unary operators known?"); + + case Expression::Type::call: + case Expression::Type::dive: + if(expr.name=="nil"){ + if(expr.args.size()!=0||expr.type==Expression::Type::dive){ + if(expr.type==Expression::Type::call)throw CompilationError(expr.site,"Cannot call nil"); + else throw CompilationError(expr.site,"Cannot dive into nil"); + } + listing.emplace_back(Instruction::Type::pushnil); + break; + } + listing.emplace_back(Instruction::Type::load,expr.name); + for(const Expression &arg : expr.args){ + codegen(arg); + } + if(expr.args.size()!=0){ + listing.emplace_back(Instruction::Type::call,(int)expr.args.size()); + } + if(expr.type==Expression::Type::dive){ + listing.emplace_back(Instruction::Type::enter); + assert(expr.scope.type==ScopeDef::Type::direct); + codegen(expr.scope.body); + listing.emplace_back(Instruction::Type::leave); + } + break; + + case Expression::Type::number: + listing.emplace_back(Instruction::Type::pushnum,expr.numval); + break; + + case Expression::Type::string: + listing.emplace_back(Instruction::Type::pushstr,expr.strval); + break; + + case Expression::Type::scope: + listing.emplace_back(Instruction::Type::pushscope,new ScopeDef(expr.scope)); + break; + } +} + +Assembly::Assembly(const StatementList &stl){ + codegen(stl); } -void evaluateSTL(const StatementList &stl){ - ; +ostream& operator<<(ostream &os,const Assembly &as){ + for(const Assembly::Instruction &ins : as.listing){ + switch(ins.type){ + case Assembly::Instruction::Type::pushnil: os<<"pushnil\n"; break; + case Assembly::Instruction::Type::pushnum: os<<"pushnum "<