summaryrefslogtreecommitdiff
path: root/evaluate.h
blob: 50166cdaadfe23aebab84d7416c8b52852db0544 (plain)
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
#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;

	Value();
	Value(double numval);
	Value(const string &strval);
	Value(ScopeVal *scopeval);
};

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{  // 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<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);
};