#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< &args) :type(type),body(body),args(args){} /*ScopeDef::ScopeDef(Type type,const StatementList &body,const vector &nameargs) :type(type),body(body){ for(const Name &n : nameargs){ args.emplace_back(Expression::Type::call,n,vector()); } }*/ string indent(int amount){ return string(amount,'\t'); } ostream& operator<<(ostream &os,const ScopeDef &scope){ switch(scope.type){ case ScopeDef::Type::direct: break; case ScopeDef::Type::lazy: os<<'?'; break; case ScopeDef::Type::function: os<<"??"; break; } if(scope.args.size()!=0){ os<<'('; bool first=true; for(const Name &name : scope.args){ if(!first)os<<", "; else first=false; os< &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 &args,const ScopeDef &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 ScopeDef &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 &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<<'('<=32&&c<=126)os<