1 #ifndef _GNM_EXPR_H_
2 # define _GNM_EXPR_H_
3 
4 G_BEGIN_DECLS
5 
6 #include <gnumeric.h>
7 #include <position.h>
8 
9 /* Warning: if you add something here, see do_expr_as_string   ! */
10 /* Warning: if you add something here, see ms-formula-write.c  ! */
11 typedef enum {
12 	GNM_EXPR_OP_PAREN,	/* Parentheses for clarity */
13 	GNM_EXPR_OP_EQUAL,	/* Compare value equal */
14 	GNM_EXPR_OP_GT,		/* Compare value greather than  */
15 	GNM_EXPR_OP_LT,		/* Compare value less than */
16 	GNM_EXPR_OP_GTE,	/* Compare value greather or equal than */
17 	GNM_EXPR_OP_LTE,	/* Compare value less or equal than */
18 	GNM_EXPR_OP_NOT_EQUAL,	/* Compare for non equivalence */
19 
20 	GNM_EXPR_OP_ADD,	/* Add  */
21 	GNM_EXPR_OP_SUB,	/* Subtract */
22 	GNM_EXPR_OP_MULT,	/* Multiply */
23 	GNM_EXPR_OP_DIV,	/* Divide */
24 	GNM_EXPR_OP_EXP,	/* Exponentiate */
25 	GNM_EXPR_OP_CAT,	/* String concatenation */
26 
27 	GNM_EXPR_OP_FUNCALL,	/* Function call invocation */
28 
29 	GNM_EXPR_OP_NAME,	/* Name reference */
30 
31         GNM_EXPR_OP_CONSTANT,	/* Constant value */
32 	GNM_EXPR_OP_CELLREF,	/* Cell content lookup (variable) */
33 	GNM_EXPR_OP_UNARY_NEG,	/* Sign inversion */
34 	GNM_EXPR_OP_UNARY_PLUS,	/* Mark as positive */
35 	GNM_EXPR_OP_PERCENTAGE,	/* Percentage (value/100) */
36 	GNM_EXPR_OP_ARRAY_CORNER,/* Top Corner of an array */
37 	GNM_EXPR_OP_ARRAY_ELEM,	/* General Array element */
38 	GNM_EXPR_OP_SET,	/* A set of expressions */
39 	GNM_EXPR_OP_RANGE_CTOR,	/* A constructed range eg A1:index(1,2) */
40 	GNM_EXPR_OP_INTERSECT	/* The intersection of multiple ranges */
41 } GnmExprOp;
42 
43 /* Shorthands for case statements.  Easy to read, easy to maintain.  */
44 #define GNM_EXPR_OP_ANY_BINARY GNM_EXPR_OP_EQUAL: case GNM_EXPR_OP_GT: case GNM_EXPR_OP_LT: case GNM_EXPR_OP_GTE: \
45 	case GNM_EXPR_OP_LTE: case GNM_EXPR_OP_NOT_EQUAL: \
46 	case GNM_EXPR_OP_ADD: case GNM_EXPR_OP_SUB: case GNM_EXPR_OP_MULT: case GNM_EXPR_OP_DIV: \
47 	case GNM_EXPR_OP_EXP: case GNM_EXPR_OP_CAT
48 #define GNM_EXPR_OP_ANY_UNARY GNM_EXPR_OP_PAREN: case GNM_EXPR_OP_UNARY_NEG: case GNM_EXPR_OP_UNARY_PLUS: case GNM_EXPR_OP_PERCENTAGE
49 
50 GType          gnm_expr_get_type        (void);
51 GType	       gnm_expr_array_corner_get_type (void); /* boxed type */
52 GnmExpr const *gnm_expr_new_constant	(GnmValue *v);
53 GnmExpr const *gnm_expr_new_unary	(GnmExprOp op, GnmExpr const *e);
54 GnmExpr const *gnm_expr_new_binary	(GnmExpr const *l, GnmExprOp op,
55 					 GnmExpr const *r);
56 GnmExpr const *gnm_expr_new_funcall	(GnmFunc *func,
57 					 GnmExprList *args);
58 GnmExpr const *gnm_expr_new_funcall1	(GnmFunc *func,
59 					 GnmExpr const *arg0);
60 GnmExpr const *gnm_expr_new_funcall2	(GnmFunc *func,
61 					 GnmExpr const *arg0,
62 					 GnmExpr const *arg1);
63 GnmExpr const *gnm_expr_new_funcall3	(GnmFunc *func,
64 					 GnmExpr const *arg0,
65 					 GnmExpr const *arg1,
66 					 GnmExpr const *arg2);
67 GnmExpr const *gnm_expr_new_funcall4	(GnmFunc *func,
68 					 GnmExpr const *arg0,
69 					 GnmExpr const *arg1,
70 					 GnmExpr const *arg2,
71 					 GnmExpr const *arg3);
72 GnmExpr const *gnm_expr_new_funcall5	(GnmFunc *func,
73 					 GnmExpr const *arg0,
74 					 GnmExpr const *arg1,
75 					 GnmExpr const *arg2,
76 					 GnmExpr const *arg3,
77 					 GnmExpr const *arg4);
78 GnmExpr const *gnm_expr_new_name	(GnmNamedExpr *name,
79 					 Sheet *sheet_scope, Workbook *wb_scope);
80 GnmExpr const *gnm_expr_new_cellref	(GnmCellRef const *cr);
81 GnmExpr const *gnm_expr_new_set		(GnmExprList *args);
82 GnmExpr const *gnm_expr_new_range_ctor  (GnmExpr const *l, GnmExpr const *r);
83 
84 GnmValue      *gnm_expr_get_range    (GnmExpr const *expr);
85 GnmFunc       *gnm_expr_get_func_def (GnmExpr const *expr);
86 GnmExpr const *gnm_expr_get_func_arg (GnmExpr const *expr, int i);
87 
88 void	  gnm_expr_free              (GnmExpr const *expr);
89 GnmExpr const *gnm_expr_copy         (GnmExpr const *expr);
90 gboolean  gnm_expr_equal (GnmExpr const *a, GnmExpr const *b);
91 gboolean  gnm_expr_is_rangeref	     (GnmExpr const *expr);
92 gboolean  gnm_expr_is_data_table     (GnmExpr const *expr,
93 				      GnmCellPos *c_in, GnmCellPos *r_in);
94 gboolean  gnm_expr_is_empty          (GnmExpr const *expr);
95 
96 GnmValue const *gnm_expr_get_constant	(GnmExpr const *expr);
97 
98 GnmNamedExpr const *gnm_expr_get_name	(GnmExpr const *expr);
99 
100 GnmCellRef const*gnm_expr_get_cellref	(GnmExpr const *expr);
101 
102 void	  gnm_expr_as_gstring	     (GnmExpr const *expr,
103 				      GnmConventionsOut *out);
104 char	 *gnm_expr_as_string	     (GnmExpr const *expr, GnmParsePos const *pp,
105 				      GnmConventions const *convs);
106 void      gnm_expr_list_as_string    (int argc, GnmExprConstPtr const *argv,
107 				      GnmConventionsOut *out);
108 gboolean  gnm_expr_contains_subtotal (GnmExpr const *expr);
109 
110 GnmValue *gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
111 			 GnmExprEvalFlags flags);
112 
113 GnmExpr const *gnm_expr_simplify_if  (GnmExpr const *expr);
114 
115 typedef struct GnmExprWalk_ {
116 	/* User data */
117 	gpointer user;
118 
119 	/* Flags the walker callback can use to signal the engine.  */
120 	gboolean stop;
121 
122 	/* Internal flags.  */
123 	guint flags;
124 } GnmExprWalk;
125 typedef GnmExpr const * (*GnmExprWalkerFunc) (GnmExpr const *expr, GnmExprWalk *data);
126 GnmExpr const *gnm_expr_walk (GnmExpr const *expr, GnmExprWalkerFunc walker, gpointer user);
127 
128 /*****************************************************************************/
129 
130 #define gnm_expr_list_append(l,e)  g_slist_append ((l), (gpointer)(e))
131 #define gnm_expr_list_prepend(l,e) g_slist_prepend ((l), (gpointer)(e))
132 #define gnm_expr_list_length(l)	   g_slist_length((GSList *)(l)) /* const cast */
133 #define gnm_expr_list_free	   g_slist_free
134 void	 gnm_expr_list_unref	  (GnmExprList *list);
135 GnmExprList *gnm_expr_list_copy	  (GnmExprList *list);
136 
137 /*****************************************************************************/
138 
139 #define GNM_EXPR_TOP_MAGIC 0x42
140 #define GNM_IS_EXPR_TOP(et) ((et) && (et)->magic == GNM_EXPR_TOP_MAGIC)
141 
142 struct _GnmExprTop {
143 	unsigned magic : 8;
144 	unsigned hash : 24;  /* Zero meaning not yet computed.  */
145 	guint32 refcount;
146 	GnmExpr const *expr;
147 };
148 
149 GnmExprTop const *gnm_expr_top_new		(GnmExpr const *e);
150 GnmExprTop const *gnm_expr_top_new_constant	(GnmValue *v);
151 GnmExprTop const *gnm_expr_top_new_array_corner (int cols, int rows, GnmExpr const *expr);
152 GnmExprTop const *gnm_expr_top_new_array_elem	(int x, int y);
153 
154 GType		gnm_expr_top_get_type (void);
155 GnmExprTop const *gnm_expr_top_ref		(GnmExprTop const *texpr);
156 void		gnm_expr_top_unref		(GnmExprTop const *texpr);
157 gboolean	gnm_expr_top_equal		(GnmExprTop const *te1, GnmExprTop const *te2);
158 guint           gnm_expr_top_hash               (GnmExprTop const *texpr);
159 gboolean	gnm_expr_top_is_shared		(GnmExprTop const *texpr);
160 gboolean	gnm_expr_top_is_err		(GnmExprTop const *texpr, GnmStdError e);
161 gboolean	gnm_expr_top_is_rangeref	(GnmExprTop const *texpr);
162 gboolean	gnm_expr_top_is_array_elem	(GnmExprTop const *texpr, int *x, int *y);
163 gboolean	gnm_expr_top_is_array_corner	(GnmExprTop const *texpr);
164 gboolean	gnm_expr_top_is_array		(GnmExprTop const *texpr);
165 void		gnm_expr_top_get_array_size	(GnmExprTop const *texpr, int *cols, int *rows);
166 GnmValue       *gnm_expr_top_get_array_value	(GnmExprTop const *texpr);
167 GnmExpr const  *gnm_expr_top_get_array_expr	(GnmExprTop const *texpr);
168 GnmValue       *gnm_expr_top_get_range		(GnmExprTop const *texpr);
169 GSList	       *gnm_expr_top_get_ranges		(GnmExprTop const *texpr);
170 GnmValue const *gnm_expr_top_get_constant	(GnmExprTop const *texpr);
171 GnmCellRef const*gnm_expr_top_get_cellref	(GnmExprTop const *texpr);
172 void		gnm_expr_top_get_boundingbox	(GnmExprTop const *texpr,
173 						 Sheet const *sheet,
174 						 GnmRange *bound);
175 gboolean	gnm_expr_top_contains_subtotal	(GnmExprTop const *texpr);
176 gboolean	gnm_expr_top_is_volatile	(GnmExprTop const *texpr);
177 GSList	       *gnm_expr_top_referenced_sheets	(GnmExprTop const *texpr);
178 GnmExpr const  *gnm_expr_top_first_funcall	(GnmExprTop const *texpr);
179 GnmExprTop const *gnm_expr_top_transpose        (GnmExprTop const *texpr);
180 
181 struct _GnmExprRelocateInfo {
182 	GnmParsePos pos;
183 
184 	GnmRange   origin;	    /* References to cells in origin_sheet!range */
185 	Sheet     *origin_sheet;    /* should to adjusted */
186 	Sheet     *target_sheet;    /* to point at this sheet */
187 	int col_offset, row_offset; /* and offset by this amount */
188 	enum {
189 		/* invalidate references to any sheets with
190 		 *	Sheet::being_invalidated == TRUE */
191 		GNM_EXPR_RELOCATE_INVALIDATE_SHEET,
192 		GNM_EXPR_RELOCATE_MOVE_RANGE,
193 		GNM_EXPR_RELOCATE_COLS,		/* ins/del col */
194 		GNM_EXPR_RELOCATE_ROWS		/* ins/del row */
195 	} reloc_type;
196 
197 	/* Valid for COLS/ROWS only.  Assumed by MOVE_RANGE.  If TRUE,
198 	   ranges ending at the edge of the sheet will keep the end
199 	   there.  */
200 	gboolean sticky_end;
201 
202 };
203 GnmExprTop const *gnm_expr_top_relocate	 (GnmExprTop const *texpr,
204 					  GnmExprRelocateInfo const *rinfo,
205 					  gboolean include_rel);
206 GnmExprTop const * gnm_expr_top_relocate_sheet (GnmExprTop const *texpr,
207 						Sheet const *src,
208 						Sheet const *dst);
209 
210 GnmValue *gnm_expr_top_eval	  (GnmExprTop const *texpr,
211 				   GnmEvalPos const *pos,
212 				   GnmExprEvalFlags flags);
213 char	 *gnm_expr_top_as_string  (GnmExprTop const *texpr,
214 				   GnmParsePos const *pp,
215 				   GnmConventions const *convs);
216 void	  gnm_expr_top_as_gstring (GnmExprTop const *texpr,
217 				   GnmConventionsOut *out);
218 char	 *gnm_expr_top_multiple_as_string  (GnmExprTop const *texpr,
219 					    GnmParsePos const *pp,
220 					    GnmConventions const *convs);
221 
222 GnmValue *gnm_expr_top_eval_fake_array (GnmExprTop const *texpr,
223 					GnmEvalPos const *pos,
224 					GnmExprEvalFlags flags);
225 
226 /*****************************************************************************/
227 
228 GType             gnm_expr_sharer_get_type (void);
229 GnmExprSharer *   gnm_expr_sharer_new  (void);
230 void              gnm_expr_sharer_unref (GnmExprSharer *es);
231 GnmExprTop const *gnm_expr_sharer_share (GnmExprSharer *es, GnmExprTop const *texpr);
232 void              gnm_expr_sharer_report (GnmExprSharer *es);
233 
234 /*****************************************************************************/
235 
236 void gnm_expr_init_ (void);
237 void gnm_expr_shutdown_ (void);
238 
239 G_END_DECLS
240 
241 #endif /* _GNM_EXPR_H_ */
242