#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 Assembly; class Value{ public: enum class Type{ nil, 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(); Value& operator=(const Value &other) = delete; Value& operator=(Value &&other) = delete; }; 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{ pushnil, // [ -> nil] pushnum, // [ -> this.num] pushstr, // [ -> this.str] pushscope, // [ -> this.scope] pushfunc, // [ -> Value(function,this.asmval)] newscope, // [ -> {}] 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 -> scope] Copies the given scope to 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=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(); Instruction& operator=(const Instruction &other) = delete; Instruction& operator=(Instruction &&other) = delete; }; vector listing; void codegen(const StatementList &stl); void codegen(const Statement &stmt); void codegen(const Expression &expr); Assembly(const ScopeDef &scopeDef); 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); };