summaryrefslogtreecommitdiff
path: root/evaluate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'evaluate.cpp')
-rw-r--r--evaluate.cpp170
1 files changed, 166 insertions, 4 deletions
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<void*,CollItem> &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 "<<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::pop: os<<"pop\n"; break;
+ case Assembly::Instruction::Type::swap: os<<"swap\n"; break;
+ case Assembly::Instruction::Type::add: os<<"add\n"; break;
+ case Assembly::Instruction::Type::sub: os<<"sub\n"; break;
+ case Assembly::Instruction::Type::mul: os<<"mul\n"; break;
+ case Assembly::Instruction::Type::div: os<<"div\n"; break;
+ case Assembly::Instruction::Type::mod: os<<"mod\n"; break;
+ case Assembly::Instruction::Type::create: os<<"create "<<ins.name<<"\n"; break;
+ case Assembly::Instruction::Type::store: os<<"store "<<ins.name<<"\n"; break;
+ case Assembly::Instruction::Type::load: os<<"load "<<ins.name<<"\n"; break;
+ case Assembly::Instruction::Type::enter: os<<"enter\n"; break;
+ case Assembly::Instruction::Type::leave: os<<"leave\n"; break;
+ case Assembly::Instruction::Type::call: os<<"call "<<ins.nargs<<"\n"; break;
+ }
+ }
+ return os;
}