1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#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=nullptr;
Value();
Value(double numval);
Value(const string &strval);
Value(ScopeVal *scopeval);
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<string,Value> values;
ScopeVal(const ScopeDef &scopeDef);
};
namespace A {
template <typename T>
T* ref(T *value);
template <typename T>
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]
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;
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(const Instruction &other);
Instruction(Instruction &&other);
~Instruction();
Instruction& operator=(const Instruction &other) = delete;
Instruction& operator=(Instruction &&other) = delete;
};
vector<Instruction> 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<ScopeVal> sstack;
public:
void evaluate(const Assembly &as);
};
|