1 // -*- Mode: C++; tab-width:2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi:tw=80:et:ts=2:sts=2
3 //
4 // -----------------------------------------------------------------------
5 //
6 // This file is part of libreallive, a dependency of RLVM.
7 //
8 // -----------------------------------------------------------------------
9 //
10 // Copyright (c) 2006 Peter Jolly
11 // Copyright (c) 2007 Elliot Glaysher
12 //
13 // Permission is hereby granted, free of charge, to any person
14 // obtaining a copy of this software and associated documentation
15 // files (the "Software"), to deal in the Software without
16 // restriction, including without limitation the rights to use, copy,
17 // modify, merge, publish, distribute, sublicense, and/or sell copies
18 // of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 // SOFTWARE.
32 //
33 // -----------------------------------------------------------------------
34 
35 #ifndef SRC_LIBREALLIVE_EXPRESSION_H_
36 #define SRC_LIBREALLIVE_EXPRESSION_H_
37 
38 #include <memory>
39 #include <string>
40 #include <vector>
41 
42 #include "machine/reference.h"
43 
44 class RLMachine;
45 
46 namespace libreallive {
47 
48 // Size of expression functions
49 size_t NextToken(const char* src);
50 size_t NextExpression(const char* src);
51 size_t NextString(const char* src);
52 size_t NextData(const char* src);
53 
54 // Parse expression functions
55 class ExpressionPiece;
56 ExpressionPiece GetExpressionToken(const char*& src);
57 ExpressionPiece GetExpressionTerm(const char*& src);
58 ExpressionPiece GetExpressionArithmatic(const char*& src);
59 ExpressionPiece GetExpressionCondition(const char*& src);
60 ExpressionPiece GetExpressionBoolean(const char*& src);
61 ExpressionPiece GetExpression(const char*& src);
62 ExpressionPiece GetAssignment(const char*& src);
63 ExpressionPiece GetData(const char*& src);
64 ExpressionPiece GetComplexParam(const char*& src);
65 
66 std::string EvaluatePRINT(RLMachine& machine, const std::string& in);
67 
68 // Converts a parameter string (as read from the binary SEEN.TXT file)
69 // into a human readable (and printable) format.
70 std::string ParsableToPrintableString(const std::string& src);
71 
72 // Converts a printable string (i.e., "$ 05 [ $ FF EE 03 00 00 ]")
73 // into one that can be parsed by all the get_expr family of functions.
74 std::string PrintableToParsableString(const std::string& src);
75 
76 enum ExpressionValueType {
77   ValueTypeInteger,
78   ValueTypeString
79 };
80 
81 enum ExpressionPieceType {
82   TYPE_STORE_REGISTER,
83   TYPE_INT_CONSTANT,
84   TYPE_STRING_CONSTANT,
85   TYPE_MEMORY_REFERENCE,
86   TYPE_SIMPLE_MEMORY_REFERENCE,
87   TYPE_UNIARY_EXPRESSION,
88   TYPE_BINARY_EXPRESSION,
89   TYPE_SIMPLE_ASSIGNMENT,
90   TYPE_COMPLEX_EXPRESSION,
91   TYPE_SPECIAL_EXPRESSION,
92   TYPE_INVALID
93 };
94 
95 struct invalid_expression_piece_t {};
96 
97 class ExpressionPiece {
98  public:
99   static ExpressionPiece StoreRegister();
100   static ExpressionPiece IntConstant(const int constant);
101   static ExpressionPiece StrConstant(const std::string constant);
102   static ExpressionPiece MemoryReference(const int type,
103                                          ExpressionPiece location);
104   static ExpressionPiece UniaryExpression(const char operation,
105                                           ExpressionPiece operand);
106   static ExpressionPiece BinaryExpression(const char operation,
107                                           ExpressionPiece lhs,
108                                           ExpressionPiece rhs);
109   static ExpressionPiece ComplexExpression();
110   static ExpressionPiece SpecialExpression(const int tag);
111 
112   ExpressionPiece(invalid_expression_piece_t);
113   ExpressionPiece(const ExpressionPiece& rhs);
114   ExpressionPiece(ExpressionPiece&& rhs);
115   ~ExpressionPiece();
116 
117   ExpressionPiece& operator=(const ExpressionPiece& rhs);
118   ExpressionPiece& operator=(ExpressionPiece&& rhs);
119 
is_valid()120   bool is_valid() const { return piece_type != TYPE_INVALID; }
121 
122   // Capability method; returns false by default. Override when
123   // ExpressionPiece subclass accesses a piece of memory.
124   bool IsMemoryReference() const;
125 
126   // Capability method; returns false by default. Override only in
127   // classes that represent a complex parameter to the type system.
128   // @see Complex_T
129   bool IsComplexParameter() const;
130 
131   // Capability method; returns false by default. Override only in
132   // classes that represent a special parameter to the type system.
133   // @see Special_T
134   bool IsSpecialParameter() const;
135 
136   // Returns the value type of this expression (i.e. string or
137   // integer)
138   ExpressionValueType GetExpressionValueType() const;
139 
140   // Assigns the value into the memory location represented by the
141   // current expression. Not all ExpressionPieces can do this, so
142   // there is a default implementation which does nothing.
143   void SetIntegerValue(RLMachine& machine, int rvalue);
144 
145   // Returns the integer value of this expression; this can either be
146   // a memory access or a calculation based on some subexpressions.
147   int GetIntegerValue(RLMachine& machine) const;
148 
149   void SetStringValue(RLMachine& machine, const std::string& rvalue);
150   const std::string& GetStringValue(RLMachine& machine) const;
151 
152   // I used to be able to just static cast any ExpressionPiece to a
153   // MemoryReference if I wanted/needed a corresponding iterator. Haeleth's
154   // rlBabel library instead uses the store register as an argument to a
155   // function that takes a integer reference. So this needs to be here now.
156   IntReferenceIterator GetIntegerReferenceIterator(RLMachine& machine) const;
157   StringReferenceIterator GetStringReferenceIterator(RLMachine& machine) const;
158 
159   // A persistable version of this value. This method should return RealLive
160   // bytecode equal to this ExpressionPiece with all references returned.
161   std::string GetSerializedExpression(RLMachine& machine) const;
162 
163   // A printable representation of the expression itself. Used to dump our
164   // parsing of the bytecode to the console.
165   std::string GetDebugString() const;
166 
167   // In the case of Complex and Special types, adds an expression piece to the
168   // list.
169   void AddContainedPiece(ExpressionPiece piece);
170 
171   const std::vector<ExpressionPiece>& GetContainedPieces() const;
172 
173   int GetOverloadTag() const;
174 
175  private:
176   ExpressionPiece();
177 
178   // Frees all possible memory and sets |piece_type| to TYPE_INVALID.
179   void Invalidate();
180 
181   // Implementations of some of the public interface where they aren't one
182   // liners.
183   std::string GetComplexSerializedExpression(RLMachine& machine) const;
184   std::string GetSpecialSerializedExpression(RLMachine& machine) const;
185 
186   std::string GetMemoryDebugString(int type,
187                                    const std::string& location) const;
188   std::string GetUniaryDebugString() const;
189   std::string GetBinaryDebugString(char operation,
190                                    const std::string& lhs,
191                                    const std::string& rhs) const;
192   std::string GetComplexDebugString() const;
193   std::string GetSpecialDebugString() const;
194 
195   int PerformUniaryOperationOn(int int_operand) const;
196   static int PerformBinaryOperationOn(char operand, int lhs, int rhs);
197 
198   ExpressionPieceType piece_type;
199 
200   union {
201     // TYPE_INT_CONSTANT
202     int int_constant;
203 
204     // TYPE_STRING_CONSTANT
205     std::string str_constant;
206 
207     // TYPE_MEMORY_REFERENCE
208     struct {
209       int type;
210       ExpressionPiece* location;
211     } mem_reference;
212 
213     // TYPE_SIMPLE_MEMORY_REFERENCE
214     struct {
215       int type;
216       int location;
217     } simple_mem_reference;
218 
219     // TYPE_UNIARY_EXPRESSION
220     struct {
221       char operation;
222       ExpressionPiece* operand;
223     } uniary_expression;
224 
225     // TYPE_BINARY_EXPRESSION
226     struct {
227       char operation;
228       ExpressionPiece* left_operand;
229       ExpressionPiece* right_operand;
230     } binary_expression;
231 
232     // TYPE_SIMPLE_ASSIGNMENT
233     struct {
234       int type;
235       int location;
236       int value;
237     } simple_assignment;
238 
239     // TYPE_COMPLEX_EXPRESSION
240     std::vector<ExpressionPiece> complex_expression;
241 
242     // TYPE_SPECIAL_EXPRESSION
243     struct {
244       int overload_tag;
245       std::vector<ExpressionPiece> pieces;
246     } special_expression;
247   };
248 };
249 
250 typedef std::vector<libreallive::ExpressionPiece> ExpressionPiecesVector;
251 
252 }  // namespace libreallive
253 
254 #endif  // SRC_LIBREALLIVE_EXPRESSION_H_
255