diff options
Diffstat (limited to 'ast.cpp')
-rw-r--r-- | ast.cpp | 207 |
1 files changed, 207 insertions, 0 deletions
@@ -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; +} |