1 /**
2 * projectM -- Milkdrop-esque visualisation SDK
3 * Copyright (C)2003-2007 projectM Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * See 'LICENSE.txt' included within this release
19 *
20 */
21 /**
22 * $Id$
23 *
24 * Expression
25 *
26 * $Log$
27 */
28
29 #ifndef _EXPR_H
30 #define _EXPR_H
31
32 #include "config.h"
33 #include "dlldefs.h"
34 #include "CValue.hpp"
35 #include "Func.hpp"
36 #include <iostream>
37 #include <vector>
38
39 class Test;
40 class Param;
41 class LValue;
42 class JitContext;
43
44 #ifdef HAVE_LLVM
45 namespace llvm {
46 class Value;
47 }
48 #endif
49
50 #define CONST_STACK_ELEMENT 0
51 #define EXPR_STACK_ELEMENT 1
52
53 #define EVAL_ERROR -1
54
55 /* Infix Operator Function */
56 class InfixOp
57 {
58 public:
59 int type;
60 int precedence;
61
62 InfixOp( int type, int precedence );
63 };
64
65 /** Term */
66 class Term
67 {
68 public:
69 float constant; /* static variable */
70 Param *param; /* pointer to a changing variable */
71
Term()72 Term() { this->constant = 0; this->param = 0; }
73 };
74
75
76 enum ExprClass
77 {
78 TREE, CONSTANT, PARAMETER, FUNCTION, ASSIGN, PROGRAM, JIT, OTHER
79 };
80
81 class Expr
82 {
83 public:
84 ExprClass clazz;
Expr(ExprClass c)85 explicit Expr(ExprClass c) : clazz(c) {};
86 virtual ~Expr() = default;
87
isConstant()88 virtual bool isConstant() { return false; };
89 virtual float eval(int mesh_i, int mesh_j) = 0;
to_string(std::ostream & out)90 virtual std::ostream& to_string(std::ostream &out)
91 {
92 std::cout << "nyi"; return out;
93 }
94
95 static Test *test();
96 static Expr *const_to_expr( float val );
97 static Expr *param_to_expr( Param *param );
98 static Expr *prefun_to_expr( Func *func, Expr **expr_list );
99 static Expr *create_assignment(class LValue *lhs, Expr *rhs);
100 static Expr *create_matrix_assignment(class LValue *lhs, Expr *rhs);
101 // TODO eventually the ownSteps param needs to go away (but for now the individual expressions might be held by the preset)
102 static Expr *create_program_expr(std::vector<Expr*> &steps_, bool ownSteps);
103
delete_expr(Expr * expr)104 static void delete_expr(Expr *expr) { if (nullptr != expr) expr->_delete_from_tree(); }
105 static Expr *optimize(Expr *root);
106 static Expr *jit(Expr *root, std::string name="Expr::jit");
107
108 public: // but don't call these from outside Expr.cpp
109
_optimize()110 virtual Expr *_optimize() { return this; };
111 #if HAVE_LLVM
112 static llvm::Value *llvm(JitContext &jit, Expr *);
113 virtual llvm::Value *_llvm(JitContext &jit) = 0; //ONLY called by llvm()
114 static llvm::Value *generate_eval_call(JitContext &jit, Expr *expr, const char *name=nullptr);
115 static llvm::Value *generate_set_call(JitContext &jitx, Expr *expr, llvm::Value *value);
116 static llvm::Value *generate_set_matrix_call(JitContext &jitx, Expr *expr, llvm::Value *value);
117 #endif
118
119 // override if this expr is not 'owned' by the containg expression tree
_delete_from_tree()120 virtual void _delete_from_tree()
121 {
122 delete this;
123 }
124 };
125
126
operator <<(std::ostream & out,Expr * expr)127 inline std::ostream& operator<<(std::ostream& out, Expr *expr)
128 {
129 if (nullptr == expr)
130 out << "NULL";
131 else
132 expr->to_string(out);
133 return out;
134 }
135
136
137 /* A binary expression tree ordered by operator precedence */
138 class TreeExpr : public Expr
139 {
140 protected:
141 TreeExpr( InfixOp *infix_op, Expr *gen_expr, Expr *left, Expr *right );
142 public:
143 static TreeExpr *create( InfixOp *infix_op, Expr *gen_expr, TreeExpr *left, TreeExpr *right );
144 static TreeExpr *create( InfixOp *infix_op, Expr *left, Expr *right );
145
146 InfixOp * infix_op; /* null if leaf */
147 Expr * gen_expr;
148 // NOTE: before optimize() left and right will always be TreeExpr
149 Expr *left, *right;
150 // these are for type-safe access in Parser.cpp
leftTree()151 TreeExpr *leftTree() { return dynamic_cast<TreeExpr *>(left); }
rightTree()152 TreeExpr *rightTree() { return dynamic_cast<TreeExpr *>(right); }
153
154 ~TreeExpr() override;
155
156 Expr *_optimize() override;
157 float eval(int mesh_i, int mesh_j) override;
158 #if HAVE_LLVM
159 llvm::Value *_llvm(JitContext &jitx) override;
160 #endif
161 std::ostream& to_string(std::ostream &out) override;
162 };
163
164
165 class LValue : public Expr
166 {
167 public:
LValue(ExprClass c)168 explicit LValue(ExprClass c) : Expr(c) {};
169 virtual void set(float value) = 0;
170 virtual void set_matrix(int mesh_i, int mesh_j, float value) = 0;
171 #if HAVE_LLVM
_llvm_set_matrix(JitContext & jitx,llvm::Value * rhs)172 virtual llvm::Value *_llvm_set_matrix(JitContext &jitx, llvm::Value *rhs)
173 {
174 Expr::generate_set_matrix_call(jitx, this, rhs);
175 return rhs;
176 }
177 #endif
178 };
179
180
181
182 #endif /** _EXPR_H */
183