summaryrefslogtreecommitdiff
path: root/evaluate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'evaluate.cpp')
-rw-r--r--evaluate.cpp39
1 files changed, 35 insertions, 4 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;
}