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