Commit c0d6ff36 authored by Jonathan Wilkes's avatar Jonathan Wilkes

Merge branch 'update-expr'

parents 77536614 232d14c9
Pipeline #1022 canceled with stage
in 5 minutes and 48 seconds
#N canvas 430 58 448 350 10;
#N canvas 416 53 448 471 10;
#X obj 1 1 cnv 15 445 20 empty \$0-pddp.cnv.header expr_and_value 20
10 1 18 -261106 -33289 0;
#X obj 407 2 pddp/pddplink http://puredata.info/dev/pddp -text pddp
......@@ -23,7 +23,7 @@ aren't the names of functions or operators like some_number \, below:
\, \$0-foo is interpretated as "\$0 minus foo". Additionally \, \$0
cannot be at the beginning of the variable name (e.g. \, \$0foo). Underscores
provide a workable \, if clunky \, solution:;
#X obj 1 328 cnv 15 445 20 empty \$0-pddp.cnv.footer empty 20 12 0
#X obj 1 478 cnv 15 445 20 empty \$0-pddp.cnv.footer empty 20 12 0
14 -233017 -33289 0;
#N canvas 373 194 494 164 META 0;
#X text 12 105 HELP_PATCH_AUTHORS Dave Sabine \, May 5 \, 2003 . Jonathan
......@@ -34,16 +34,26 @@ Wilkes revised the patch to conform to the PDDP template for Pd version
two Pd objects;
#X text 12 25 KEYWORDS expr expr~ fexpr~ value all_about_pd nonlocal
;
#X restore 392 330 pd META;
#X restore 392 480 pd META;
#N canvas 218 216 428 141 Related_objects 0;
#X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0
14 -261106 -33289 0;
#X text 7 2 [expr] and [value]- Related Objects;
#X restore 103 330 pd Related_objects;
#X obj 6 330 pddp/pddplink all_about.pd -text All About Pd;
#X restore 103 480 pd Related_objects;
#X obj 6 480 pddp/pddplink all_about.pd -text All About Pd;
#X text 21 324 You can also use the assignment operator "=" to assign
a new value to a [value] variable:;
#X floatatom 24 368 5 0 0 0 - - -, f 5;
#X obj 24 388 expr _\$0_foo = $f1 + 42;
#X msg 215 366 bang;
#X obj 215 388 v _\$0_foo;
#X floatatom 215 410 5 0 0 0 - - -, f 5;
#X connect 3 0 5 0;
#X connect 4 0 3 0;
#X connect 6 0 2 0;
#X connect 7 0 11 0;
#X connect 8 0 12 0;
#X connect 12 0 9 0;
#X connect 20 0 21 0;
#X connect 22 0 23 0;
#X connect 23 0 24 0;
......@@ -20,6 +20,17 @@
* Oct 2015
* $x[-1] was not equal $x1[-1], not accessing the previous block
* (bug fix by Dan Ellis)
* July 2017 --sdy
* - Version 0.55
*
* - The arrays now redraw after a store into one of their members
* - ex_if() (the "if()" function is reworked to only evaluate either
* the left or the right args depending on the truth value of the condition.
* However, if the condition is a vector, both the left and the right
* are evaluated regradless.
* - priority of ',' and '=' was switched ot fix the bug of using store "=" in
* functions with multiple arguments, which caused an error during execution.
* - The number of inlet and outlets (MAX_VARS) is now set at 100
*/
/*
......@@ -256,6 +267,12 @@ expr_donew(struct expr *expr, int ac, t_atom *av)
}
expr->exp_stack[expr->exp_nexpr] =
(struct ex_ex *)fts_malloc(max_node * sizeof (struct ex_ex));
if (!expr->exp_stack[expr->exp_nexpr]) {
post_error( (fts_object_t *) expr,
"expr: malloc for expr nodes failed\n");
goto error;
}
expr->exp_stack[expr->exp_nexpr][max_node-1].ex_type=0;
expr->exp_nexpr++;
ret = ex_match(list, (long)0);
if (expr->exp_nexpr > MAX_VARS)
......@@ -272,6 +289,7 @@ expr_donew(struct expr *expr, int ac, t_atom *av)
list, expr->exp_stack[expr->exp_nexpr - 1], (long *)0);
if (!ret)
goto error;
fts_free(list);
}
*ret = nullex;
t_freebytes(exp_string, exp_strlen+1);
......@@ -496,7 +514,7 @@ ex_match(struct ex_ex *eptr, long int op)
}
/*
* ex_parse -- This function if called when we have already done some
* ex_parse -- This function is called when we have already done some
* parsing on the expression, and we have already matched
* our brackets and parenthesis. The main job of this
* function is to convert the infix expression to the
......@@ -518,6 +536,7 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
struct ex_ex *eptr;
struct ex_ex *lowpre = 0; /* pointer to the lowest precedence */
struct ex_ex savex;
struct ex_ex *tmpex;
long pre = HI_PRE;
long count;
......@@ -551,7 +570,9 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
case ET_VI:
case ET_VAR:
if (!count && !eptr[1].ex_type) {
*optr++ = *eptr;
*optr = *eptr;
tmpex = optr;
tmpex->ex_end = ++optr;
return (optr);
}
break;
......@@ -569,9 +590,10 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
!((struct ex_ex *) eptr[1].ex_ptr)[1].ex_type) {
savex = *((struct ex_ex *) eptr[1].ex_ptr);
*((struct ex_ex *) eptr[1].ex_ptr) = nullex;
*optr++ = *eptr;
lowpre = ex_parse(x, &eptr[2], optr, (long *)0);
*optr = *eptr;
lowpre = ex_parse(x, &eptr[2], optr + 1, (long *)0);
*((struct ex_ex *) eptr[1].ex_ptr) = savex;
optr->ex_end = lowpre;
return(lowpre);
}
eptr = (struct ex_ex *) eptr[1].ex_ptr;
......@@ -612,8 +634,8 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
ac = 0;
savex = *((struct ex_ex *) eptr[1].ex_ptr);
*((struct ex_ex *) eptr[1].ex_ptr) = nullex;
*optr++ = *eptr;
lowpre = ex_parse(x, &eptr[2], optr, &ac);
*optr = *eptr;
lowpre = ex_parse(x, &eptr[2], optr + 1, &ac);
if (!lowpre)
return (exNULL);
ac++;
......@@ -625,6 +647,7 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
return (exNULL);
}
*((struct ex_ex *) eptr[1].ex_ptr) = savex;
optr->ex_end = lowpre;
return (lowpre);
}
eptr = (struct ex_ex *) eptr[1].ex_ptr;
......@@ -643,6 +666,7 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
*((struct ex_ex *) eptr->ex_ptr) = nullex;
lowpre = ex_parse(x, &eptr[1], optr, (long *)0);
*((struct ex_ex *) eptr->ex_ptr) = savex;
optr->ex_end = lowpre;
return (lowpre);
}
eptr = (struct ex_ex *)eptr->ex_ptr;
......@@ -674,16 +698,17 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
ex_print(iptr);
return (exNULL);
}
*optr++ = *lowpre;
eptr = ex_parse(x, &lowpre[1], optr, argc);
*optr = *lowpre;
eptr = ex_parse(x, &lowpre[1], optr + 1, argc);
optr->ex_end = eptr;
return (eptr);
}
/* this is the case of using unary operator as a binary opetator */
if (count == 3 && unary_op(lowpre->ex_op)) {
post("expr: syntax error, missing operand before unary operator\n");
ex_print(iptr);
return (exNULL);
}
/* this is the case of using unary operator as a binary opetator */
if (count == 3 && unary_op(lowpre->ex_op)) {
post("expr: syntax error, missing operand before unary operator\n");
ex_print(iptr);
return (exNULL);
}
if (lowpre == iptr) {
post("expr: syntax error: mission operand\n");
ex_print(iptr);
......@@ -691,15 +716,18 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc)
}
savex = *lowpre;
*lowpre = nullex;
if (savex.ex_op != OP_COMMA)
*optr++ = savex;
else
(*argc)++;
eptr = ex_parse(x, iptr, optr, argc);
if (savex.ex_op != OP_COMMA) {
*optr = savex;
eptr = ex_parse(x, iptr, optr + 1, argc);
} else {
(*argc)++;
eptr = ex_parse(x, iptr, optr, argc);
}
if (eptr) {
eptr = ex_parse(x, &lowpre[1], eptr, argc);
*lowpre = savex;
}
optr->ex_end = eptr;
return (eptr);
}
......@@ -1225,6 +1253,9 @@ ex_eval(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
return (eptr);
}
extern struct ex_ex * ex_if(t_expr *expr, struct ex_ex *eptr,
struct ex_ex *optr,struct ex_ex *argv, int idx);
/*
* eval_func -- evaluate a function, call ex_eval() on all the arguments
* so that all of them are terminal nodes. The call the
......@@ -1249,12 +1280,24 @@ eval_func(struct expr *expr, struct ex_ex *eptr, struct ex_ex *optr, int idx)
return (exNULL);
}
for (i = 0; i < f->f_argc; i++) {
/*
* We treat the "if" function differently to be able to evaluate
* the args selectively based on the truth value of the "condition"
*/
if (f->f_func != (void (*)) ex_if) {
for (i = 0; i < f->f_argc; i++) {
args[i].ex_type = 0;
args[i].ex_int = 0;
eptr = ex_eval(expr, eptr, &args[i], idx);
}
(*f->f_func)(expr, f->f_argc, args, optr);
}
(*f->f_func)(expr, f->f_argc, args, optr);
} else {
for (i = 0; i < f->f_argc; i++) {
args[i].ex_type = 0;
args[i].ex_int = 0;
}
eptr = ex_if(expr, eptr, optr, args, idx);
}
for (i = 0; i < f->f_argc; i++) {
if (args[i].ex_type == ET_VEC)
fts_free(args[i].ex_vec);
......@@ -1956,99 +1999,6 @@ atoif(char *s, long int *value, long int *type)
return (p);
}
#ifdef notdef
/*
* atoif -- ascii to float or integer (understands hex numbers also)
*/
char *
atoif(char *s, long int *value, long int *type)
{
char *p;
long int_val = 0;
int flt = 0;
t_float pos = 0;
t_float flt_val = 0;
int base = 10;
p = s;
if (*p == '0' && (p[1] == 'x' || p[1] == 'X')) {
base = 16;
p += 2;
}
while (8) {
switch (*p) {
case '.':
if (flt || base != 10) {
post("expr: syntax error: %s\n", s);
return ((char *) 0);
}
flt++;
pos = 10;
flt_val = int_val;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (flt) {
flt_val += (*p - '0') / pos;
pos *= 10;
} else {
int_val *= base;
int_val += (*p - '0');
}
break;
case 'e':
if (base != 16) {
if (
case 'a':
case 'b':
case 'c':
case 'd':
case 'f':
if (base != 16 || flt) {
post("expr: syntax error: %s\n", s);
return ((char *) 0);
}
int_val *= base;
int_val += (*p - 'a' + 10);
break;
case 'E':
case 'A':
case 'B':
case 'C':
case 'D':
case 'F':
if (base != 16 || flt) {
post("expr: syntax error: %s\n", s);
return ((char *) 0);
}
int_val *= base;
int_val += (*p - 'A' + 10);
break;
default:
if (flt) {
*type = ET_FLT;
*((t_float *) value) = flt_val;
} else {
*type = ET_INT;
*value = int_val;
}
return (p);
}
p++;
}
}
#endif
/*
* find_func -- returns a pointer to the found function structure
* otherwise it returns 0
......@@ -2072,8 +2022,10 @@ find_func(char *s)
void
ex_print(struct ex_ex *eptr)
{
struct ex_ex *extmp;
while (eptr->ex_type) {
extmp = eptr->ex_end;
while (eptr->ex_type && eptr != extmp) {
switch (eptr->ex_type) {
case ET_INT:
post("%ld ", eptr->ex_int);
......@@ -2085,10 +2037,10 @@ ex_print(struct ex_ex *eptr)
post("%s ", eptr->ex_ptr);
break;
case ET_TBL:
if (!eptr->ex_ptr) { /* special case of $# processing */
if (!eptr->ex_ptr) { /* special case of $# processing */
post("%s ", "$$");
break;
}
break;
}
case ET_VAR:
post("%s ", ex_symname((fts_symbol_t )eptr->ex_ptr));
break;
......
......@@ -5,17 +5,17 @@
/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */
/* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */
//#define MSP
//#ifdef PD
//#undef MSP
//#endif
#define MSP
#ifdef PD
#undef MSP
#endif
//#ifdef PD
#ifdef PD
#include "m_pd.h"
//#else /* MSP */
//#include "ext.h"
//#include "z_dsp.h"
//#endif
#else /* MSP */
#include "ext.h"
#include "z_dsp.h"
#endif
#define fts_malloc malloc
#define fts_calloc calloc
......@@ -57,7 +57,7 @@ void pd_error(void *object, char *fmt, ...);
* is 10.
*/
#define MAX_VARS 9
#define MAX_VARS 100
#define MINODES 10 /* was 200 */
/* terminal defines */
......@@ -70,8 +70,8 @@ void pd_error(void *object, char *fmt, ...);
*/
#define OP_SEMI ((long)(1<<16|1)) /* ; */
#define OP_STORE ((long)(2<<16|28)) /* = */
#define OP_COMMA ((long)(3<<16|2)) /* , */
#define OP_COMMA ((long)(2<<16|2)) /* , */
#define OP_STORE ((long)(3<<16|28)) /* = */
#define OP_LOR ((long)(4<<16|3)) /* || */
#define OP_LAND ((long)(5<<16|4)) /* && */
#define OP_OR ((long)(6<<16|5)) /* | */
......@@ -100,8 +100,6 @@ void pd_error(void *object, char *fmt, ...);
#define HI_PRE ((long)(100<<16)) /* infinite precedence */
#define PRE_MASK ((long)0xffff0000) /* precedence level mask */
struct ex_ex;
#define name_ok(c) (((c)=='_') || ((c)>='a' && (c)<='z') || \
((c)>='A' && (c)<='Z') || ((c) >= '0' && (c) <= '9'))
#define unary_op(x) ((x) == OP_NOT || (x) == OP_NEG || (x) == OP_UMINUS)
......@@ -120,6 +118,7 @@ struct ex_ex {
#define ex_op ex_cont.op
#define ex_ptr ex_cont.ptr
long ex_type; /* type of the node */
struct ex_ex *ex_end; /* the node after the end of this expression */
};
#define exNULL ((struct ex_ex *)0)
......
......@@ -46,6 +46,9 @@
* - fixed sum("table"), and Sum("table", x, y)
* - deleted avg(), Avg() as they can be simple expressions
* - deleted store as this can be achieved by the '=' operator
* July 2017 --sdy
*
* - ex_if() is reworked to only evaluate either the left or the right arg
*/
......@@ -77,6 +80,9 @@
#include "x_vexp.h"
struct ex_ex *ex_eval(struct expr *expr, struct ex_ex *eptr,
struct ex_ex *optr, int i);
/* forward declarations */
static void ex_min(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr);
......@@ -108,11 +114,12 @@ static void ex_abs(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex
static void ex_fmod(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_ceil(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_floor(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_if(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
struct ex_ex * ex_if(t_expr *expr, struct ex_ex *argv, struct ex_ex *optr,
struct ex_ex *args, int idx);
static void ex_ldexp(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_imodf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_modf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
#ifndef _WIN32
#if !defined(_MSC_VER) || (_MSC_VER >= 17000)
static void ex_cbrt(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_erf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
static void ex_erfc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr);
......@@ -162,27 +169,27 @@ t_ex_func ex_funcs[] = {
{"fact", ex_fact, 1},
{"random", ex_random, 2}, /* random number */
{"abs", ex_abs, 1},
{"if", ex_if, 3},
{"if", (void (*))ex_if, 3},
{"ldexp", ex_ldexp, 2},
{"imodf", ex_imodf, 1},
{"modf", ex_modf, 1},
#ifndef _WIN32
#if !defined(_MSC_VER) || (_MSC_VER >= 17000)
{"asinh", ex_asinh, 1},
{"acosh", ex_acosh, 1},
{"atanh", ex_atanh, 1}, /* hyperbolic atan */
{"isnan", ex_isnan, 1},
{"cbrt", ex_cbrt, 1},
{"round", ex_round, 1},
{"trunc", ex_trunc, 1},
{"erf", ex_erf, 1},
{"erfc", ex_erfc, 1},
{"expm1", ex_expm1, 1},
{"log1p", ex_log1p, 1},
{"isinf", ex_isinf, 1},
{"finite", ex_finite, 1},
{"isnan", ex_isnan, 1},
{"nearbyint", ex_nearbyint, 1},
{"copysign", ex_copysign, 2},
{"isinf", ex_isinf, 1},
{"remainder", ex_remainder, 2},
{"asinh", ex_asinh, 1},
{"acosh", ex_acosh, 1},
{"atanh", ex_atanh, 1}, /* hyperbolic atan */
{"round", ex_round, 1},
{"trunc", ex_trunc, 1},
{"nearbyint", ex_nearbyint, 1},
#endif
#ifdef PD
{"size", ex_size, 1},
......@@ -861,7 +868,7 @@ ex_tanh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
}
#ifndef _WIN32
#if !defined(_MSC_VER) || (_MSC_VER >= 17000)
static void
ex_asinh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr)
{
......@@ -979,10 +986,10 @@ ex_abs(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
}
/*
*ex_if -- floating point modulo
* ex_if -- if function
*/
static void
ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
struct ex_ex *
ex_if(t_expr *e, struct ex_ex *eptr, struct ex_ex *optr, struct ex_ex *argv, int idx)
{
struct ex_ex *left, *right, *cond, *res;
t_float *op; /* output pointer */
......@@ -990,10 +997,14 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
t_float *cp; /* condition pointer */
t_float leftvalue, rightvalue;
int j;
int condtrue = 0;
// evaluate the condition
eptr = ex_eval(e, eptr, argv, idx);
cond = argv++;
left = argv++;
right = argv;
// only either the left or right will be evaluated depending
// on the truth value of the condition
// However, if the condition is a vector, both args will be evaluated
switch (cond->ex_type) {
case ET_VEC:
......@@ -1002,12 +1013,25 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
if (optr->ex_type == ET_VI) {
/* SDY remove this test */
post("expr~: Int. error %d", __LINE__);
return;
return (eptr);
}
optr->ex_type = ET_VEC;
optr->ex_vec = (t_float *)
optr->ex_type = ET_VEC;
optr->ex_vec = (t_float *)
fts_malloc(sizeof (t_float) * e->exp_vsize);
if (!optr->ex_vec) {
post("expr:if: no mem");
/* pass over the left and right args */
return(cond->ex_end->ex_end);
}
}
/*
* if the condition is a vector
* the left and the right args both will get processed
*/
eptr = ex_eval(e, eptr, argv, idx);
left = argv++;
eptr = ex_eval(e, eptr, argv, idx);
right = argv;
op = optr->ex_vec;
j = e->exp_vsize;
cp = cond->ex_vec;
......@@ -1023,7 +1047,7 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
else
*op++ = rightvalue;
}
return;
return (eptr);
case ET_FLT:
rightvalue = right->ex_flt;
while (j--) {
......@@ -1032,7 +1056,7 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
else
*op++ = rightvalue;
}
return;
return (eptr);
case ET_VEC:
case ET_VI:
rp = right->ex_vec;
......@@ -1043,13 +1067,13 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
*op++ = *rp;
rp++;
}
return;
return (eptr);
case ET_SYM:
default:
post_error((fts_object_t *) e,
"expr: FUNC_EVAL(%d): bad right type %ld\n",
__LINE__, right->ex_type);
return;
return (eptr);
}
case ET_FLT:
leftvalue = left->ex_flt;
......@@ -1062,7 +1086,7 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
else
*op++ = rightvalue;
}
return;
return (eptr);
case ET_FLT:
rightvalue = right->ex_flt;
while (j--) {
......@@ -1071,7 +1095,7 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
else
*op++ = rightvalue;
}
return;
return (eptr);
case ET_VEC:
case ET_VI:
rp = right->ex_vec;
......@@ -1082,13 +1106,13 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
*op++ = *rp;
rp++;
}
return;
return (eptr);
case ET_SYM:
default:
post_error((fts_object_t *) e,
"expr: FUNC_EVAL(%d): bad right type %ld\n",
__LINE__, right->ex_type);
return;
return (eptr);
}
case ET_VEC:
case ET_VI:
......@@ -1103,7 +1127,7 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
*op++ = rightvalue;
lp++;
}
return;
return (eptr);
case ET_FLT:
rightvalue = right->ex_flt;
while (j--) {
......@@ -1113,7 +1137,7 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
*op++ = rightvalue;
lp++;
}
return;
return (eptr);
case ET_VEC:
case ET_VI:
rp = right->ex_vec;
......@@ -1124,77 +1148,91 @@ ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)
*op++ = *rp;
lp++; rp++;
}
return;
return (eptr);
case ET_SYM:
default: