summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2017-02-11 22:54:35 +0100
committertomsmeding <tom.smeding@gmail.com>2017-02-11 22:55:53 +0100
commit164a8d297429d58d216b9fa44e0cb42db5d23e2c (patch)
treeb6ca185472108fe4de3578b9efd8d46dd2476582
parent15d1419c0d97d63a70271c451fdeef1e69ad7d96 (diff)
Handle functions better in 'compilation'
-rw-r--r--evaluate.cpp39
-rw-r--r--evaluate.h10
-rw-r--r--test.squig17
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;
}
diff --git a/evaluate.h b/evaluate.h
index e2dc241..9571626 100644
--- a/evaluate.h
+++ b/evaluate.h
@@ -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);
diff --git a/test.squig b/test.squig
index 1e83fb2..c45cdb2 100644
--- a/test.squig
+++ b/test.squig
@@ -1 +1,16 @@
-a := 1
+v := "first v value"
+
+f := ??{
+ puts("function")
+ x := v
+}
+
+f {
+ puts(x)
+}
+
+v = "second v value"
+
+f {
+ puts(x)
+}