summaryrefslogtreecommitdiff
path: root/ast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ast.cpp')
-rw-r--r--ast.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/ast.cpp b/ast.cpp
index e69de29..d1742e2 100644
--- a/ast.cpp
+++ b/ast.cpp
@@ -0,0 +1,207 @@
+#include "ast.h"
+
+using namespace std;
+
+
+static int indent_level_index=ios_base::xalloc();
+
+
+namespace std{
+ string to_string(Expression::Type type){
+ switch(type){
+ case Expression::Type::binop: return "binop";
+ case Expression::Type::unop: return "unop";
+ case Expression::Type::call: return "call";
+ case Expression::Type::dive: return "dive";
+ case Expression::Type::number: return "number";
+ case Expression::Type::string: return "string";
+ case Expression::Type::scope: return "scope";
+ default: return to_string((int)type);
+ }
+ }
+
+ string to_string(Statement::Type type){
+ switch(type){
+ case Statement::Type::create: return "create";
+ case Statement::Type::assign: return "assign";
+ case Statement::Type::expression: return "expression";
+ default: return to_string((int)type);
+ }
+ }
+}
+
+
+Site::Site():lnum(-1),linex(-1){}
+Site::Site(const string &filename,i64 lnum,i64 linex)
+ :filename(filename),lnum(lnum),linex(linex){}
+
+Site Site::addX(i64 dx){
+ return Site(filename,lnum,linex+dx);
+}
+
+ostream& operator<<(ostream &os,Site site){
+ return os<<site.filename<<':'<<site.lnum<<':'<<site.linex;
+}
+
+
+Scope::Scope():type(Type::direct){}
+Scope::Scope(Type type,const StatementList &body,const vector<Expression> &args)
+ :type(type),body(body),args(args){}
+/*Scope::Scope(Type type,const StatementList &body,const vector<Name> &nameargs)
+ :type(type),body(body){
+ for(const Name &n : nameargs){
+ args.emplace_back(Expression::Type::call,n,vector<Expression>());
+ }
+}*/
+
+string indent(int amount){
+ return string(amount*4,' ');
+}
+
+ostream& operator<<(ostream &os,const Scope &scope){
+ switch(scope.type){
+ case Scope::Type::direct: break;
+ case Scope::Type::lazy: os<<'?'; break;
+ case Scope::Type::function: os<<"??"; break;
+ }
+ if(scope.args.size()!=0){
+ os<<'(';
+ bool first=true;
+ for(const Expression &ex : scope.args){
+ if(!first)os<<", ";
+ else first=false;
+ os<<ex;
+ }
+ os<<')';
+ }
+ os<<"{\n";
+ os.iword(indent_level_index)++;
+ int level=os.iword(indent_level_index);
+
+ os<<scope.body;
+
+ os.iword(indent_level_index)--;
+ return os<<'\n'<<indent(level)<<'}';
+}
+
+
+Expression::Expression(Type type,const Name &name,const vector<Expression> &args)
+ :type(type),name(name),args(args){
+ if(type!=Type::binop&&type!=Type::call){
+ throw runtime_error("Expression(type,name,args) called with invalid type "+to_string(type));
+ }
+}
+Expression::Expression(Type type,const Name &name,const Expression &arg)
+ :type(type),name(name),args({arg}){
+ if(type!=Type::unop){
+ throw runtime_error("Expression(type,name,arg) called with invalid type "+to_string(type));
+ }
+}
+Expression::Expression(Type type,const Name &name,const vector<Expression> &args,const Scope &scope)
+ :type(type),name(name),args(args),scope(scope){
+ if(type!=Type::dive){
+ throw runtime_error("Expression(type,name,args,scope) called with invalid type "+to_string(type));
+ }
+}
+Expression::Expression(Type type,double numval)
+ :type(type),numval(numval){
+ if(type!=Type::number){
+ throw runtime_error("Expression(type,numval) called with invalid type "+to_string(type));
+ }
+}
+Expression::Expression(Type type,const string &strval)
+ :type(type),strval(strval){
+ if(type!=Type::string){
+ throw runtime_error("Expression(type,strval) called with invalid type "+to_string(type));
+ }
+}
+Expression::Expression(Type type,const Scope &scope)
+ :type(type),scope(scope){
+ if(type!=Type::scope){
+ throw runtime_error("Expression(type,scope) called with invalid type "+to_string(type));
+ }
+}
+Expression::Expression(Type type,const vector<Expression> &args)
+ :type(type),args(args){
+ if(type!=Type::cond){
+ throw runtime_error("Expression(type,args) called with invalid type "+to_string(type));
+ }
+}
+
+ostream& operator<<(ostream &os,const Expression &expr){
+ switch(expr.type){
+ case Expression::Type::binop:
+ return os<<'('<<expr.args[0]<<' '<<expr.name<<' '<<expr.args[1]<<')';
+
+ case Expression::Type::unop:
+ return os<<expr.name<<expr.args[0];
+
+ case Expression::Type::call:
+ case Expression::Type::dive:
+ os<<expr.name;
+ if(expr.args.size()!=0){
+ os<<'(';
+ bool first=true;
+ for(const auto &a : expr.args){
+ if(!first)os<<", ";
+ else first=false;
+ os<<a;
+ }
+ os<<')';
+ }
+ if(expr.type==Expression::Type::dive){
+ os<<expr.scope;
+ }
+ return os;
+
+ case Expression::Type::number:
+ return os<<expr.numval;
+
+ case Expression::Type::string:
+ return os<<expr.strval;
+
+ case Expression::Type::scope:
+ throw runtime_error("operator<< on Expression:scope not implemented");
+
+ case Expression::Type::cond:
+ return os<<"if "<<expr.args[0]<<" then "<<expr.args[1]<<" else "<<expr.args[2];
+ }
+}
+
+
+Statement::Statement(Type type,const Name &dstvar,const Expression &expr)
+ :type(type),dstvar(dstvar),expr(expr){
+ if(type!=Type::create&&type!=Type::assign){
+ throw runtime_error("Statement(type,dstvar,expr) called with invalid type "+to_string(type));
+ }
+}
+Statement::Statement(Type type,const Expression &expr)
+ :type(type),expr(expr){
+ if(type!=Type::expression){
+ throw runtime_error("Statement(type,expr) called with invalid type "+to_string(type));
+ }
+}
+
+
+ostream& operator<<(ostream &os,const Statement &st){
+ switch(st.type){
+ case Statement::Type::create:
+ return os<<st.dstvar<<" := "<<st.expr;
+
+ case Statement::Type::assign:
+ return os<<st.dstvar<<" = "<<st.expr;
+
+ case Statement::Type::expression:
+ return os<<st.expr;
+ }
+}
+
+ostream& operator<<(ostream &os,const StatementList &stl){
+ bool first=true;
+ for(const Statement &st : stl){
+ if(!first)os<<'\n'<<indent(os.iword(indent_level_index));
+ else first=false;
+ os<<st;
+ }
+ return os;
+}