Commit b261e986 authored by Arturo Espinosa's avatar Arturo Espinosa

Lots of things today:



Lots of things today:

- New functions implemented:
	SELECTION(),  SUM(),  IF()

- Autocompute of an expression that applies to the selection.

- Added comparission to the expression grammar.

- Added array values.

Bug fixes as usual and lots other thingies I forget.

Miguel
parent b3dbeffe
1998-08-06 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_selection_changed_hook): Autocomputation
routine. Whenever selection changes this routine will execute an
arbitrary expression (kept in the workbook) and display the
result.
1998-08-05 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/expr.c (value_release): Release the value.
(value_release): Add support for arrays.
* src/symbol.c (g_strcase_hash): Use case insensitive hash tables.
* src/item-bar.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-grid.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-cursor.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize.
(item_cursor_point): Implement correctly.
* src/expr.c, parser.y (eval_expr): Added comparission operators.
* src/fn-sheet.c (gnumeric_if):
Implemented IF function.
Implemented SELECTION function.
* src/func.c (gnumeric_sum):
Implement SUM function.
1998-08-05 <miguel@nuclecu.unam.mx>
* src/expr.c (eval_funcall): No need for the the extra argc
......
1998-08-06 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_selection_changed_hook): Autocomputation
routine. Whenever selection changes this routine will execute an
arbitrary expression (kept in the workbook) and display the
result.
1998-08-05 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/expr.c (value_release): Release the value.
(value_release): Add support for arrays.
* src/symbol.c (g_strcase_hash): Use case insensitive hash tables.
* src/item-bar.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-grid.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-cursor.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize.
(item_cursor_point): Implement correctly.
* src/expr.c, parser.y (eval_expr): Added comparission operators.
* src/fn-sheet.c (gnumeric_if):
Implemented IF function.
Implemented SELECTION function.
* src/func.c (gnumeric_sum):
Implement SUM function.
1998-08-05 <miguel@nuclecu.unam.mx>
* src/expr.c (eval_funcall): No need for the the extra argc
......
1998-08-06 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_selection_changed_hook): Autocomputation
routine. Whenever selection changes this routine will execute an
arbitrary expression (kept in the workbook) and display the
result.
1998-08-05 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/expr.c (value_release): Release the value.
(value_release): Add support for arrays.
* src/symbol.c (g_strcase_hash): Use case insensitive hash tables.
* src/item-bar.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-grid.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-cursor.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize.
(item_cursor_point): Implement correctly.
* src/expr.c, parser.y (eval_expr): Added comparission operators.
* src/fn-sheet.c (gnumeric_if):
Implemented IF function.
Implemented SELECTION function.
* src/func.c (gnumeric_sum):
Implement SUM function.
1998-08-05 <miguel@nuclecu.unam.mx>
* src/expr.c (eval_funcall): No need for the the extra argc
......
1998-08-06 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/sheet.c (sheet_selection_changed_hook): Autocomputation
routine. Whenever selection changes this routine will execute an
arbitrary expression (kept in the workbook) and display the
result.
1998-08-05 Miguel de Icaza <miguel@nuclecu.unam.mx>
* src/expr.c (value_release): Release the value.
(value_release): Add support for arrays.
* src/symbol.c (g_strcase_hash): Use case insensitive hash tables.
* src/item-bar.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-grid.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize
* src/item-cursor.c (item_bar_unrealize): Call parent unrealize
(item_bar_realize): Call parent realize.
(item_cursor_point): Implement correctly.
* src/expr.c, parser.y (eval_expr): Added comparission operators.
* src/fn-sheet.c (gnumeric_if):
Implemented IF function.
Implemented SELECTION function.
* src/func.c (gnumeric_sum):
Implement SUM function.
1998-08-05 <miguel@nuclecu.unam.mx>
* src/expr.c (eval_funcall): No need for the the extra argc
......
......@@ -18,6 +18,8 @@ GNUMERIC_BASE_SOURCES = \
expr.c \
expr.h \
func.c \
func.h \
fn-sheet.c \
gnumeric-sheet.c \
gnumeric-sheet.h \
gnumeric.h \
......
......@@ -40,7 +40,7 @@ expr_parse_string (char *expr, int col, int row, char **error_msg)
* This releases all of the resources used by a tree.
* It is only used internally by eval_expr_unref
*/
static void
void
eval_expr_release (ExprTree *tree)
{
g_return_if_fail (tree != NULL);
......@@ -113,9 +113,21 @@ value_release (Value *value)
mpf_clear (value->v.v_float);
break;
case VALUE_ARRAY: {
GList *l;
for (l = value->v.array; l; l = l->next)
value_release (l->data);
g_list_free (l);
}
case VALUE_CELLRANGE:
break;
default:
g_warning ("Unknown value type passed to value_release\n");
}
g_free (value);
}
/*
......@@ -140,6 +152,33 @@ value_cast_to_float (Value *v)
return newv;
}
int
value_get_bool (Value *v, int *err)
{
*err = 0;
if (v->type == VALUE_STRING)
return atoi (v->v.str->str);
if (v->type == VALUE_CELLRANGE){
*err = 1;
return 0;
}
if (v->type == VALUE_INTEGER)
return v->v.v_int != 0;
if (v->type == VALUE_FLOAT)
return v->v.v_float != 0.0;
if (v->type == VALUE_ARRAY)
return 0;
g_warning ("Unhandled value in value_get_boolean");
return 0;
}
float_t
value_get_as_double (Value *v)
{
......@@ -155,6 +194,9 @@ value_get_as_double (Value *v)
if (v->type == VALUE_INTEGER)
return (float_t) v->v.v_int;
if (v->type == VALUE_ARRAY)
return 0.0;
return (float_t) v->v.v_float;
}
......@@ -181,7 +223,13 @@ eval_cell_value (Sheet *sheet, Value *value)
mpf_init (res->v.v_float);
mpf_set (res->v.v_float, value->v.v_float);
break;
case VALUE_ARRAY:
g_warning ("VALUE_ARRAY not handled in eval_cell_value\n");
res->type = VALUE_INTEGER;
res->v.v_int = 0;
break;
case VALUE_CELLRANGE:
res->v.cell_range = value->v.cell_range;
break;
......@@ -243,6 +291,19 @@ eval_funcall (Sheet *sheet, ExprTree *tree, int eval_col, int eval_row, char **e
return v;
}
enum {
IS_EQUAL,
IS_LESS,
IS_BIGGER,
};
static int
compare (Value *a, Value *b)
{
g_warning ("Value comparission is not yet implemented\n");
return IS_EQUAL;
}
Value *
eval_expr (void *asheet, ExprTree *tree, int eval_col, int eval_row, char **error_string)
{
......@@ -250,6 +311,63 @@ eval_expr (void *asheet, ExprTree *tree, int eval_col, int eval_row, char **erro
Sheet *sheet = asheet;
switch (tree->oper){
case OP_EQUAL:
case OP_NOT_EQUAL:
case OP_GT:
case OP_GTE:
case OP_LT:
case OP_LTE: {
int comp;
a = eval_expr (sheet, tree->u.binary.value_a,
eval_col, eval_row, error_string);
b = eval_expr (sheet, tree->u.binary.value_b,
eval_col, eval_row, error_string);
if (!(a && b)){
if (a)
value_release (a);
if (b)
value_release (b);
return NULL;
}
res = g_new (Value, 1);
res->type = VALUE_INTEGER;
comp = compare (a, b);
switch (tree->oper){
case OP_EQUAL:
res->v.v_int = comp == IS_EQUAL;
break;
case OP_GT:
res->v.v_int = comp == IS_BIGGER;
break;
case OP_LT:
res->v.v_int = comp == IS_LESS;
break;
case OP_LTE:
res->v.v_int = (comp == IS_EQUAL || comp == IS_LESS);
break;
case OP_GTE:
res->v.v_int = (comp == IS_EQUAL || comp == IS_BIGGER);
break;
case OP_NOT_EQUAL:
res->v.v_int = comp != IS_EQUAL;
break;
default:
g_warning ("This should never be reached: comparission ops\n");
}
value_release (a);
value_release (b);
return res;
}
case OP_ADD:
case OP_SUB:
case OP_MULT:
......@@ -292,7 +410,7 @@ eval_expr (void *asheet, ExprTree *tree, int eval_col, int eval_row, char **erro
case OP_MULT:
mpz_mul (res->v.v_int, a->v.v_int, b->v.v_int);
break;
case OP_DIV:
if (mpz_cmp_si (b->v.v_int, 0)){
value_release (a);
......
......@@ -2,6 +2,13 @@
#define EXPR_H
typedef enum {
OP_EQUAL,
OP_GT,
OP_LT,
OP_GTE,
OP_LTE,
OP_NOT_EQUAL,
OP_ADD,
OP_SUB,
OP_MULT,
......@@ -20,7 +27,8 @@ typedef enum {
VALUE_STRING,
VALUE_INTEGER,
VALUE_FLOAT,
VALUE_CELLRANGE
VALUE_CELLRANGE,
VALUE_ARRAY
} ValueType;
/*
......@@ -48,6 +56,7 @@ typedef struct {
CellRef cell_b;
} cell_range;
GList *array; /* a list of Values */
String *str;
Symbol *sym;
float_t v_float; /* floating point */
......@@ -112,7 +121,7 @@ typedef struct {
* b for boolean
*/
char *args;
ValueType ret_type;
char *named_arguments;
Value *(*expr_fn)(void *sheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string);
......@@ -129,16 +138,20 @@ ExprTree *expr_parse_string (char *expr, int col, int row, char **error_msg)
void expr_tree_ref (ExprTree *tree);
void expr_tree_unref (ExprTree *tree);
/* Do not use this routine, it is intended to be used internally */
void eval_expr_release (ExprTree *tree);
Value *eval_expr (void *asheet, ExprTree *tree,
int col, int row,
char **error_string);
void value_release (Value *value);
Value *value_cast_to_float (Value *v);
int value_get_bool (Value *v, int *err);
float_t value_get_as_double (Value *v);
void value_dump (Value *value);
char *value_string (Value *value);
float_t value_get_as_double (Value *v);
int yyparse (void);
void functions_init (void);
......
/*
* func.c: Built in sheet functions
* (C) 1998 The Free Software Foundation
*
* Author:
* Miguel de Icaza (miguel@gnu.org)
*
*/
#include <config.h>
#include <gnome.h>
#include "math.h"
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "func.h"
static Value *
gnumeric_if (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
ExprTree *expr;
Value *value;
int err, ret;
/* Type checking */
if (g_list_length (expr_node_list) != 3){
*error_string = _("Invalid number of arguments");
return NULL;
}
/* Compute the if part */
value = eval_expr (tsheet, (ExprTree *) expr_node_list->data, eval_col, eval_row, error_string);
if (value == NULL)
return NULL;
/* Choose which expression we will evaluate */
ret = value_get_bool (value, &err);
if (err)
return NULL;
if (ret)
expr = (ExprTree *) expr_node_list->next->data;
else
expr = (ExprTree *) expr_node_list->next->next->data;
value_release (value);
/* Return the result */
return eval_expr (tsheet, (ExprTree *) expr, eval_col, eval_row, error_string);
}
static Value *
gnumeric_selection (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
Sheet *sheet = (Sheet *) tsheet;
Value *value;
GList *l, *array;
/* Type checking */
if (expr_node_list != NULL){
*error_string = _("Invalid number of arguments");
return NULL;
}
value = g_new (Value, 1);
value->type = VALUE_ARRAY;
/* Create an array */
array = NULL;
for (l = sheet->selections; l; l = l->next){
SheetSelection *ss = (SheetSelection *) l->data;
Value *single_value;
CellRef *cell_ref;
/* Create the value */
single_value = g_new (Value, 1);
single_value->type = VALUE_CELLRANGE;
/* Fill it in */
/* start */
cell_ref = &single_value->v.cell_range.cell_a;
cell_ref->col_relative = 0;
cell_ref->row_relative = 0;
cell_ref->col = ss->start_col;
cell_ref->row = ss->start_row;
/* end */
cell_ref = &single_value->v.cell_range.cell_b;
cell_ref->col_relative = 0;
cell_ref->row_relative = 0;
cell_ref->col = ss->end_col;
cell_ref->row = ss->end_row;
array = g_list_prepend (array, single_value);
}
value->v.array = array;
return value;
}
static Value *
gnumeric_count (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
*error_string = "not yet implemented";
return NULL;
}
static Value *
gnumeric_average (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
*error_string = "not yet implemented";
return NULL;
}
FunctionDefinition sheet_functions [] = {
{ "if", 0, "logical_test,value_if_true,value_if_false",
gnumeric_if, NULL },
{ "selection", 0, "", gnumeric_selection, NULL },
{ "count", 0, "", gnumeric_count, NULL },
{ "average", 0, "", gnumeric_average, NULL },
{ NULL, NULL }
};
/*
* func.c: Built in functions
* func.c: Built in mathematical functions and functions registration
* (C) 1998 The Free Software Foundation
*
* Author:
......@@ -12,6 +12,7 @@
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "func.h"
static Value *
gnumeric_abs (Value *argv [], char **error_string)
......@@ -297,28 +298,91 @@ gnumeric_sinh (Value *argv [], char **error_string)
return v;
}
typedef struct {
Sheet *sheet;
int eval_col, eval_row;
float_t total;
} sum_data_t;
static float_t
gnumeric_sum_add_value (Sheet *sheet, Value *v)
{
float_t total = 0.0;
switch (v->type){
case VALUE_INTEGER:
return v->v.v_int;
break;
case VALUE_FLOAT:
return v->v.v_float;
break;
case VALUE_STRING:
return atof (v->v.str->str);
break;
case VALUE_CELLRANGE: {
int col = v->v.cell_range.cell_a.col;
int frow = v->v.cell_range.cell_a.row;
int top_col = v->v.cell_range.cell_b.col;
int top_row = v->v.cell_range.cell_b.row;
int row;
Cell *cell;
{
static warn_shown;
if (!warn_shown){
g_warning ("SUM is not being smart right now, "
"it should use the cell iterator\n");
warn_shown = 1;
}
}
for (; col <= top_col; col++){
for (row = frow; row <= top_row; row++){
cell = sheet_cell_get (sheet, col, row);
if (!cell)
continue;
if (!cell->value)
continue;
total += gnumeric_sum_add_value (sheet, cell->value);
}
}
return total;
}
case VALUE_ARRAY: {
GList *l;
for (l = v->v.array; l; l = l->next)
total += gnumeric_sum_add_value (sheet, l->data);
return total;
}
default:
g_warning ("VALUE type not handled in SUM\n");
return 0.0;
}
}
static Value *
gnumeric_sum (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
sum_data_t data;
data.sheet = tsheet;
data.eval_col = eval_col;
data.eval_row = eval_row;
data.total = 0.0;
Value *result;
Sheet *sheet = (Sheet *) tsheet;
float_t total = 0.0;
result = g_new (Value, 1);
result->type = VALUE_FLOAT;
for (; expr_node_list; expr_node_list = expr_node_list->next){
}
ExprTree *tree = (ExprTree *) expr_node_list->data;
Value *v;
*error_string = _("SUM not yet implemented");
return NULL;
v = eval_expr (tsheet, tree, eval_col, eval_row, error_string);
total += gnumeric_sum_add_value (sheet, v);
value_release (v);
}
result->v.v_float = total;
return result;
}
static Value *
......@@ -354,43 +418,48 @@ gnumeric_pi (Value *argv [], char **error_string)
return v;
}
FunctionDefinition internal_functions [] = {
{ "abs", "f", VALUE_FLOAT, NULL, gnumeric_abs },
{ "acos", "f", VALUE_FLOAT, NULL, gnumeric_acos },
{ "acosh", "f", VALUE_FLOAT, NULL, gnumeric_acosh },
{ "asin", "f", VALUE_FLOAT, NULL, gnumeric_asin },
{ "asinh", "f", VALUE_FLOAT, NULL, gnumeric_asinh },
{ "atan", "f", VALUE_FLOAT, NULL, gnumeric_atan },
{ "atanh", "f", VALUE_FLOAT, NULL, gnumeric_atanh },
{ "atan2", "ff", VALUE_FLOAT, NULL, gnumeric_atan2 },
{ "cos", "f", VALUE_FLOAT, NULL, gnumeric_cos },
{ "cosh", "f", VALUE_FLOAT, NULL, gnumeric_cosh },
{ "ceil", "f", VALUE_FLOAT, NULL, gnumeric_ceil },
{ "degrees", "f", VALUE_FLOAT, NULL, gnumeric_degrees },
{ "exp", "f", VALUE_FLOAT, NULL, gnumeric_exp },
{ "floor", "f", VALUE_FLOAT, NULL, gnumeric_floor },
{ "int", "f", VALUE_FLOAT, NULL, gnumeric_int },
{ "log", "f", VALUE_FLOAT, NULL, gnumeric_log },
{ "log2", "f", VALUE_FLOAT, NULL, gnumeric_log2 },
{ "log10", "f", VALUE_FLOAT, NULL, gnumeric_log10 },
{ "radians", "f", VALUE_FLOAT, NULL, gnumeric_radians },
{ "sin", "f", VALUE_FLOAT, NULL, gnumeric_sin },
{ "sinh", "f", VALUE_FLOAT, NULL, gnumeric_sinh },
{ "sum", 0, VALUE_FLOAT, gnumeric_sum, NULL },
{ "tan", "f", VALUE_FLOAT, NULL, gnumeric_tan },
{ "tanh", "f", VALUE_FLOAT, NULL, gnumeric_tanh },
{ "pi", "", VALUE_FLOAT, NULL, gnumeric_pi },
FunctionDefinition math_functions [] = {
{ "abs", "f", "number", NULL, gnumeric_abs },
{ "acos", "f", "number", NULL, gnumeric_acos },
{ "acosh", "f", "number", NULL, gnumeric_acosh },
{ "asin", "f", "number", NULL, gnumeric_asin },
{ "asinh", "f", "number", NULL, gnumeric_asinh },
{ "atan", "f", "number", NULL, gnumeric_atan },
{ "atanh", "f", "number", NULL, gnumeric_atanh },
{ "atan2", "ff", "xnum,ynum", NULL, gnumeric_atan2 },
{ "cos", "f", "number", NULL, gnumeric_cos },
{ "cosh", "f", "number", NULL, gnumeric_cosh },
{ "ceil", "f", "number", NULL, gnumeric_ceil },
{ "degrees", "f", "number", NULL, gnumeric_degrees },
{ "exp", "f", "number", NULL, gnumeric_exp },
{ "floor", "f", "number", NULL, gnumeric_floor },
{ "int", "f", "number", NULL, gnumeric_int },
{ "log", "f", "number", NULL, gnumeric_log },
{ "log2", "f", "number", NULL, gnumeric_log2 },
{ "log10", "f", "number", NULL, gnumeric_log10 },
{ "radians", "f", "number", NULL, gnumeric_radians },