#pragma once #include #include #include #include "ast.h" using namespace std; class CompilationError : public runtime_error{ public: explicit CompilationError(const string &what_arg); explicit CompilationError(const char *what_arg); CompilationError(Site site,const string &what_arg); }; class ExecutionError : public runtime_error{ public: explicit ExecutionError(const string &what_arg); explicit ExecutionError(const char *what_arg); }; class ScopeVal; class Value{ public: enum class Type{ nil, number, // numval string, // strval scope, // scopeval }; Type type; double numval; string strval; ScopeVal *scopeval; Value(); Value(double numval); Value(const string &strval); Value(ScopeVal *scopeval); }; class ScopeVal{ public: ScopeDef scopeDef; unordered_map values; ScopeVal(const ScopeDef &scopeDef); }; namespace A { template T* ref(T *value); template void unref(T *value); void unref_all(); } class Assembly{ class Instruction{ public: enum class Type{ // Effect on the value stack is given pushnil, // [ -> nil] pushnum, // [ -> this.num] pushstr, // [ -> this.str] pushscope, // [ -> this.scope] pop, // [x -> ] swap, // [x,y -> y,x] add, // [x,y -> x+y] sub, // [x,y -> x-y] mul, // [x,y -> x*y] div, // [x,y -> x/y] mod, // [x,y -> x%y] create, // [value -> ] Creates binding this.name in the top scope store, // [value -> ] Stores in the first scope to contain a this.name binding load, // [ -> value] Retrieves from the first scope to contain a this.name binding enter, // [scope -> ] Pushes the given scope on the scope stack leave, // [ -> ] Pops from the scope stack call, // [scope,arg,...,arg -> scope] Pops this.nargs arguments and replaces for names from scope.scopeDef.args }; Type type; double num; string str; ScopeDef *scope; string name; int nargs; 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 }; vector listing; void codegen(const StatementList &stl); void codegen(const Statement &stmt); void codegen(const Expression &expr); public: Assembly(const StatementList &stl); friend ostream& operator<<(ostream &os,const Assembly &as); }; ostream& operator<<(ostream &os,const Assembly &as); class Context{ vector sstack; public: void evaluate(const Assembly &as); };