-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexpression.hpp
170 lines (121 loc) · 5.17 KB
/
expression.hpp
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*! \file expression.hpp
Defines the Expression type and assiciated functions.
*/
#ifndef EXPRESSION_HPP
#define EXPRESSION_HPP
#include "token.hpp"
#include "atom.hpp"
#include "layout_parameters.h"
#include <vector>
#include <string>
#include <utility>
#include <map>
// forward declare Environment
class Environment;
/*! \class Expression
\brief An expression is a tree of Atoms.
An expression is an atom called the head followed by a (possibly empty)
list of expressions called the tail.
*/
class Expression {
public:
// Labels for the formatted data containers stored in formatted Expressions
typedef std::string String;
typedef std::vector<Expression> List;
typedef std::pair<List, Expression> Lambda;
typedef std::pair<double, double> Point;
// convenience typedef
typedef std::vector<Expression>::const_iterator ConstIteratorType;
/// Default construct and Expression, whose type in NoneType
Expression();
/*! Construct an Expression with given Atom as head an empty tail
\param atom the atom to make the head
*/
Expression(const Atom & a);
/// deep-copy construct an expression (recursive)
Expression(const Expression & a);
// List Type constructor
Expression(const List & list);
// Lambda Type constructor
Expression(const List & parameters, const Expression & function);
/// deep-copy assign an expression (recursive)
Expression & operator=(const Expression & a);
/// return a reference to the head Atom
Atom & head();
/// return a const-reference to the head Atom
const Atom & head() const;
/// append Atom to tail of the expression
void append(const Atom & a);
/// append Atom to tail of the expression
void append(const Expression & e);
/// return a pointer to the last expression in the tail, or nullptr
Expression * tail();
/// return a const-iterator to the beginning of tail
ConstIteratorType tailConstBegin() const noexcept;
/// return a const-iterator to the tail end
ConstIteratorType tailConstEnd() const noexcept;
/// convienience member to determine if tail is empty
bool isTailEmpty() const noexcept;
/// convienience member to determine if head atom is a number
bool isHeadNumber() const noexcept;
/// convienience member to determine if head atom is a symbol
bool isHeadSymbol() const noexcept;
/// convienience member to determine if head atom is a symbol
bool isHeadComplex() const noexcept;
/// convienience member to determine if head atom is a string literal
bool isHeadString() const noexcept;
/// convienience member to determine if head atom is a list
bool isHeadList() const noexcept;
/// convienience member to determine if head atom is a lambda
bool isHeadLambda() const noexcept;
/// value of Expression as a List vector, return empty List vector if not a List
List asList() const noexcept;
/// value of Expression as a Lambda pair (params, proc), return empty pair if not a Lambda
Lambda asLambda() const noexcept;
// Convenience member for external checks
String asString() const noexcept;
// Convenient helper method for special-form equivalent
void setProperty(const String key, Expression value);
// Convenient helper method for special-form equivalent
Expression getProperty(const String key) const noexcept;
/// convienience member to determine if Expression is a Graphic Primitive Point
bool isPointG() const noexcept;
/// convienience member to determine if Expression is a Graphic Primitive Line
bool isLineG() const noexcept;
/// convienience member to determine if Expression is a Graphic Primitive Text
bool isTextG() const noexcept;
// Convenient helper method for built-in procedure equivalent
static List makeDiscretePlot(const List & data, const List & options);
/// Evaluate expression using a post-order traversal (recursive)
Expression eval(Environment & env);
// Apply operation to evaluated expression
Expression apply(const Atom & op, const List & args, const Environment & env);
/// equality comparison for two expressions (recursive)
bool operator==(const Expression & exp) const noexcept;
private:
// the head of the expression
Atom m_head;
// the tail list is expressed as a vector for access efficiency
// and cache coherence, at the cost of wasted memory.
std::vector<Expression> m_tail;
// Property list
std::map<String, Expression> m_props;
// convenience typedef
typedef std::vector<Expression>::iterator IteratorType;
// internal helper methods
Expression handle_lookup(const Atom & head, const Environment & env);
Expression handle_define(Environment & env);
Expression handle_begin(Environment & env);
Expression handle_lambda();
// Built-In Functions
Expression call_lambda(Expression & lambda, const List & args, const Environment & env);
Expression handle_apply(Environment & env);
Expression handle_map(Environment & env);
Expression set_property(Environment & env);
Expression get_property(Environment & env);
};
/// Render expression to output stream
std::ostream & operator<<(std::ostream & out, const Expression & exp);
/// inequality comparison for two expressions (recursive)
bool operator!=(const Expression & left, const Expression & right) noexcept;
#endif