1 /*
2  * The Doomsday Engine Project -- libcore
3  *
4  * Copyright © 2004-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
5  *
6  * @par License
7  * LGPL: http://www.gnu.org/licenses/lgpl.html
8  *
9  * <small>This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or (at your
12  * option) any later version. This program is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
15  * General Public License for more details. You should have received a copy of
16  * the GNU Lesser General Public License along with this program; if not, see:
17  * http://www.gnu.org/licenses</small>
18  */
19 
20 #ifndef LIBDENG2_EXPRESSION_H
21 #define LIBDENG2_EXPRESSION_H
22 
23 #include "../ISerializable"
24 
25 #include <QFlags>
26 
27 namespace de {
28 
29 class Evaluator;
30 class Value;
31 class Record;
32 
33 /**
34  * Base class for expressions.
35  *
36  * @note  All expression classes must call the serialization methods of this class
37  *        so that the expression flags are properly serialized.
38  *
39  * @ingroup script
40  */
41 class DENG2_PUBLIC Expression : public ISerializable
42 {
43 public:
44     /// Deserialization of an expression failed. @ingroup errors
45     DENG2_ERROR(DeserializationError);
46 
47     // Flags for evaluating expressions.
48     // Note: these are serialized as is, so don't change the existing values.
49     enum Flag
50     {
51         /// Evaluates to a value. In conjunction with IMPORT, causes the imported
52         /// record to be copied to the local namespace.
53         ByValue = 0x1,
54 
55         /// Evaluates to a reference.
56         ByReference = 0x2,
57 
58         /// If missing, create a new variable.
59         NewVariable = 0x4,
60 
61         /// If missing, create a new subrecord (i.e., Variable that owns a Record).
62         NewSubrecord = 0x8,
63 
64         /// Identifier must exist and will be deleted.
65         //Delete = 0x10,
66 
67         /// Imports an external namespace into the local namespace (as a reference).
68         Import = 0x20,
69 
70         /// Look for object in local namespace only.
71         LocalOnly = 0x40,
72 
73         /// If the identifier is in scope, returns a reference to the process's
74         /// throwaway variable.
75         ThrowawayIfInScope = 0x80,
76 
77         /// Identifier must not already exist in scope.
78         NotInScope = 0x100,
79 
80         /// Variable will be set to read-only mode.
81         ReadOnly = 0x200,
82 
83         // Variable will be raised into a higher namespace.
84         //Export = 0x400,
85 
86         /// If missing, create a new subrecord. Otherwise, reuse the existing record.
87         NewSubrecordIfNotInScope = 0x800
88     };
89     Q_DECLARE_FLAGS(Flags, Flag)
90 
91 public:
92     Expression();
93 
94     virtual ~Expression();
95 
96     virtual void push(Evaluator &evaluator, Value *scope = 0) const;
97 
98     virtual Value *evaluate(Evaluator &evaluator) const = 0;
99 
100     /**
101      * Returns the flags of the expression.
102      */
103     Flags const &flags () const;
104 
105     /**
106      * Sets the flags of the expression.
107      *
108      * @param f          Flags to set.
109      * @param operation  Operation to perform on the flags.
110      */
111     void setFlags(Flags f, FlagOp operation = ReplaceFlags);
112 
113     /**
114      * Subclasses must call this in their serialization method.
115      */
116     void operator >> (Writer &to) const;
117 
118     /**
119      * Subclasses must call this in their deserialization method.
120      */
121     void operator << (Reader &from);
122 
123 public:
124     /**
125      * Constructs an expression by deserializing one from a reader.
126      *
127      * @param reader  Reader.
128      *
129      * @return  The deserialized expression. Caller gets ownership.
130      */
131     static Expression *constructFrom(Reader &reader);
132 
133 protected:
134     typedef dbyte SerialId;
135 
136     enum SerialIds {
137         ARRAY,
138         BUILT_IN,
139         CONSTANT,
140         DICTIONARY,
141         NAME,
142         OPERATOR
143     };
144 
145 private:
146     Flags _flags;
147 };
148 
149 Q_DECLARE_OPERATORS_FOR_FLAGS(Expression::Flags)
150 
151 } // namespace de
152 
153 #endif /* LIBDENG2_EXPRESSION_H */
154