[Gridflow-cvs] [svn] commit: r6362 - in /trunk: doc/flow_classes/#expr-help.pd src/expr.cxx

svn-gridflow at artengine.ca svn-gridflow at artengine.ca
Sun Sep 26 22:34:17 EDT 2010


Author: matju
Date: Sun Sep 26 22:34:17 2010
New Revision: 6362

Log:
support [#expr foo[$f1]]

Modified:
    trunk/doc/flow_classes/#expr-help.pd
    trunk/src/expr.cxx

Modified: trunk/doc/flow_classes/#expr-help.pd
==============================================================================
--- trunk/doc/flow_classes/#expr-help.pd (original)
+++ trunk/doc/flow_classes/#expr-help.pd Sun Sep 26 22:34:17 2010
@@ -1,19 +1,19 @@
-#N canvas 467 25 632 642 10;
+#N canvas 467 24 632 642 10;
 #X obj 0 0 doc_h;
-#X obj 3 671 doc_also;
-#X obj 0 691 doc_f;
-#X obj 3 383 doc_c 1..;
-#X obj 14 413 doc_cc any;
-#X obj 97 413 doc_m cany <atom>;
-#X text 232 413 floats and symbols (and commas and semicolons) that
+#X obj 3 685 doc_also;
+#X obj 0 705 doc_f;
+#X obj 3 425 doc_c 1..;
+#X obj 14 455 doc_cc any;
+#X obj 97 455 doc_m cany <atom>;
+#X text 232 455 floats and symbols (and commas and semicolons) that
 will be joined together to form a string which will be interpreted
 in a manner quite similar to what [expr] does.;
-#X obj 14 501 doc_ii 0;
-#X obj 97 501 doc_m i0 bang;
-#X text 232 501 evaluate expression and output result.;
-#X obj 103 671 expr;
-#X obj 139 671 expr~;
-#X obj 181 671 fexpr~;
+#X obj 14 543 doc_ii 0;
+#X obj 97 543 doc_m i0 bang;
+#X text 232 543 evaluate expression and output result.;
+#X obj 103 685 expr;
+#X obj 139 685 expr~;
+#X obj 181 685 fexpr~;
 #X obj 98 43 #expr;
 #X text 135 43 computes the result of the formula(s) you write in it.
 ;
@@ -29,17 +29,17 @@
 like [%].;
 #X text 96 188 it supports $f1 \, $f2 \, $f3 \, etc.;
 #X text 96 203 it does not support $s1 \, $v1 \, etc.;
-#X obj 3 471 doc_i 1..;
-#X obj 97 523 doc_m i0 float;
-#X text 232 523 set value of $f1 and then do like bang.;
+#X obj 3 513 doc_i 1..;
+#X obj 97 565 doc_m i0 float;
+#X text 232 565 set value of $f1 and then do like bang.;
 #X obj 14 546 doc_ii other;
 #X obj 97 545 doc_m iother float;
 #X text 232 545 set value of any other $f variable \, such as $f2 \,
 $f3 \, etc. \; for example \, a float into inlet 6 will set $f7.;
-#X obj 3 583 doc_o 1..;
-#X obj 14 613 doc_oo any;
-#X obj 97 613 doc_m oany float;
-#X text 232 613 the results \, output from right to left \, even though
+#X obj 3 597 doc_o 1..;
+#X obj 14 627 doc_oo any;
+#X obj 97 627 doc_m oany float;
+#X text 232 627 the results \, output from right to left \, even though
 they get computed left-to-right. [#expr] makes a list of the results
 and then outputs it in reverse order.;
 #X text 120 248 [#expr rand($f1)] is the same as [expr random(0 \,
@@ -55,6 +55,8 @@
 $f1>$f2)];
 #X text 119 348 [#expr rem($f1 \, $f2)] = [expr $f1 % $f2];
 #X text 122 363 ...;
+#X text 97 381 it supports table lookup but only with a constant table
+name (no $s1);
 #X connect 1 1 10 0;
 #X connect 1 1 11 0;
 #X connect 1 1 12 0;

Modified: trunk/src/expr.cxx
==============================================================================
--- trunk/src/expr.cxx (original)
+++ trunk/src/expr.cxx Sun Sep 26 22:34:17 2010
@@ -29,15 +29,20 @@
 
 \class GFExpr : FObject {
 	/* only between next() and parse() */
-	#define A_OPEN  t_atomtype(0x1000) // '('
-	#define A_CLOSE t_atomtype(0x1001) // ')'
-	#define A_BRA   t_atomtype(0x1008) // '['
-	#define A_KET   t_atomtype(0x1009) // ']'
-	#define A_VAR   t_atomtype(0x1002) /* for $f1-style variables, not other variables */
-	#define A_OP1   t_atomtype(0x1003) /* unary prefix operator or unary function */
-	#define A_OP    t_atomtype(0x1004) /* operator: binary infix, or not parsed yet */
+	#define A_OPEN    t_atomtype(0x1000) // '('
+	#define A_CLOSE   t_atomtype(0x1001) // ')'
+	#define A_SQOPEN  t_atomtype(0x1008) // '['
+	#define A_SQCLOSE t_atomtype(0x1009) // ']'
+	/* used for bytecode */
+	#define A_VAR      t_atomtype(0x1002) /* for $f1-style variables, not other variables */
+	#define A_OP1      t_atomtype(0x1003) /* unary prefix operator or unary function */
+	#define A_OP       t_atomtype(0x1004) /* operator: binary infix, or not parsed yet */
+	//#define A_VAR_V    t_atomtype(0x1005) /* [v] read */
+	#define A_VAR_A    t_atomtype(0x1006) /* [tabread] */
+	/* used for both */
         //      A_SYMBOL for [v] names and [table] names; also used between next() and parse() for function names.
         //      A_FLOAT  for float literals (unlike [expr], there are no integer literals)
+        /* end */
 	string args;
 	vector<t_atom2> toks;
 	vector<t_atom2> code;
@@ -58,8 +63,8 @@
 		}
 		else if (*s=='(') {s++; tok.a_type=A_OPEN;}
 		else if (*s==')') {s++; tok.a_type=A_CLOSE;}
-		else if (*s=='[') {s++; tok.a_type=A_BRA;}
-		else if (*s==']') {s++; tok.a_type=A_KET;}
+		else if (*s=='[') {s++; tok.a_type=A_SQOPEN;}
+		else if (*s==']') {s++; tok.a_type=A_SQCLOSE;}
 		else if (*s==';') {s++; tok.a_type=A_SEMI;}
 		else if (*s==',') {s++; tok.a_type=A_COMMA;}
 		else if (*s=='$') {
@@ -87,15 +92,15 @@
 		} else code.push_back(a);
 	}
 	// context: 0=outside, 1=plain parens; 2=func parens; 3=brackets
-	int parse (int level, int context, t_atom2 prevop=t_atom2(A_NULL,0)) {
+	int parse (int context, t_atom2 prevop=t_atom2(A_NULL,0)) {
            	next(s);
 		switch (int(tok.a_type)) {
 		  case A_OP: { // unary
 			t_symbol *o = tok.a_symbol;
-			if      (o==gensym("+")) {parse(level,context,t_atom2(A_OP1,tok.a_symbol));}
-			else if (o==gensym("-")) {parse(level,context,t_atom2(A_OP1,gensym("inv+")));}
-			else if (o==gensym("!")) {parse(level,context,t_atom2(A_OP1,gensym("==")));}
-			else if (o==gensym("~")) {parse(level,context,t_atom2(A_OP1,tok.a_symbol));}
+			if      (o==gensym("+")) {parse(context,t_atom2(A_OP1,tok.a_symbol));}
+			else if (o==gensym("-")) {parse(context,t_atom2(A_OP1,gensym("inv+")));}
+			else if (o==gensym("!")) {parse(context,t_atom2(A_OP1,gensym("==")));}
+			else if (o==gensym("~")) {parse(context,t_atom2(A_OP1,tok.a_symbol));}
 			else RAISE("can't use '%s' as a unary prefix operator",tok.a_symbol->s_name);
 		  } break;
 		  case A_FLOAT: case A_SYMBOL: case A_VAR:
@@ -107,56 +112,58 @@
 				int priority1 = prevop.a_type!=A_NULL ? priorities[prevop] : 42;
 				int priority2 =                         priorities[tok];
 				if (!priority2) RAISE("unknown operator '%s'",tok.a_symbol->s_name);
-				if (priority1 <= priority2) {add(prevop); parse(level,context,tok);}
-				else {parse(level,context,tok); if (prevop.a_type!=A_NULL) add(prevop);}
-			  } break;
-			  case A_OPEN: { // function (1 arg only)
+				if (priority1 <= priority2) {add(prevop); parse(context,tok);}
+				else {parse(context,tok); if (prevop.a_type!=A_NULL) add(prevop);}
+			  } break;
+			  case A_OPEN: { // function (1 or 2 args)
 				t_atom2 a = code.back(); code.pop_back();
 				if (a.a_type!=A_SYMBOL) {
 					string z=tok.to_s(), zt=atomtype_to_s(tok.a_type);
-					RAISE("syntax error (%dc) tok=%s type=%s",level,z.data(),zt.data());
+					RAISE("syntax error (c) tok=%s type=%s",z.data(),zt.data());
 				}
 				t_symbol *o = a.a_symbol; int e=1;
 				if   (a==gensym("abs"))                {a=t_atom2(A_OP1,gensym("abs-"));}
 				else if (priorities[t_atom2(A_OP1,o)]) {a=t_atom2(A_OP1,o);}
 				else if (priorities[t_atom2(A_OP ,o)]) {a=t_atom2(A_OP ,o); e=2;}
 				else RAISE("unknown function '%s'",o->s_name);
-				if (parse(level,2)!=e) RAISE("wrong number of arguments for '%s'",o->s_name);
+				if (parse(2)!=e) RAISE("wrong number of arguments for '%s'",o->s_name);
 				code.push_back(a);
 			  } break;
 			  case A_CLOSE: {
-				if (int(tok.a_type)==A_CLOSE && context!=1 && context!=2) RAISE("can't close a parenthesis at this pojnt");
+				if (int(tok.a_type)==A_CLOSE && context!=1 && context!=2) RAISE("can't close a parenthesis at this point");
 				if (prevop.a_type!=A_NULL) add(prevop);
 			  } break;
 			  case A_NULL: case A_SEMI: {
-				if (level) RAISE("forgot to close parens or brackets %d times",level);
+				if (context!=0) RAISE("unexpected end of expression");
 				if (prevop.a_type!=A_NULL) add(prevop);
-				if (tok.a_type==A_SEMI) {add(tok); int elems=parse(level,0); post("A_SEMI: elems=%d",elems);}
-			  } break;
-			  case A_BRA: {
-				t_atom2 a = code.back(); code.pop_back();
+				if (tok.a_type==A_SEMI) {add(tok); int elems=parse(0); post("A_SEMI: elems=%d",elems);}
+			  } break;
+			  case A_SQOPEN: {
+				t_atom2 a = code.back();
 				if (a.a_type!=A_SYMBOL) {
 					string z=tok.to_s(), zt=atomtype_to_s(tok.a_type);
-					RAISE("syntax error (%dc) tok=%s type=%s",level,z.data(),zt.data());
+					RAISE("syntax error (d) tok=%s type=%s",z.data(),zt.data());
 				}
+				parse(3);
+				code.push_back(t_atom2(A_VAR_A,0));
 			  }  break;
-			  case A_KET: {
-				if (context!=3) RAISE("can't close a bracket at this level");
+			  case A_SQCLOSE: {
+				if (context!=3) RAISE("can't close a bracket at this point");
 			  }  break;
 			  case A_COMMA: {
 			  	if (context!=2) RAISE("can't use comma in this context");
-				return 1+parse(level,context);
+				return 1+parse(context);
 			  }
 			  default: {
 				string z=tok.to_s(), zt=atomtype_to_s(tok.a_type);
-				RAISE("syntax error (%db) tok=%s type=%s",level,z.data(),zt.data());
+				RAISE("syntax error (b) tok=%s type=%s",z.data(),zt.data());
 			  }
 			}
 		  break;
-		  case A_OPEN: {parse(level+1,1); goto infix;}
+		  case A_OPEN: {parse(1); goto infix;}
 		  default: {
 			  string z=tok.to_s(), zt=atomtype_to_s(tok.a_type);
-			  RAISE("syntax error (%da) tok=%s type=%s",level,z.data(),zt.data());
+			  RAISE("syntax error (a) tok=%s type=%s",z.data(),zt.data());
 		  }
 		};
 		return 1;
@@ -165,41 +172,52 @@
 		prev=0; //toks.clear(); code.clear();
 		if (argc) args = join(argc,argv); else args = "0";
 		s = args.data();
-		int elems = parse(0,0);
+		int elems = parse(0);
 		post("A_NULL: elems=%d",elems);
 		for (size_t i=0; i<inputs.size(); i++) inputs[i]=0;
 		//try {parse(s);} // should use fclasses_pd[pd_class(x)]->name->s_name
 		//catch (Barf &oozy) {oozy.error(gensym("#expr"),argc,argv);}
 		if (*s) RAISE("expression not finished parsing");
 	}
+	t_atom2 lookup (const t_atom2 &a) {
+		if (a.a_type!=A_SYMBOL) return a;
+		float f; t_symbol *s=a;
+		if (value_getfloat(s,&f)) RAISE("unknown variable '%s'",s->s_name);
+		return f;//stack.push_back(f);
+	}
 	\decl 0 bang () {
 		//post("----------------------------------------------------------------");
 		//string t = join(toks.size(),toks.data()); post("#expr toks: %s",t.data());
 		//string c = join(code.size(),code.data()); post("#expr code: %s",c.data());
-		vector<float> stack;
+		vector<t_atom2> stack;
 		int n = code.size();
 		for (int i=0; i<n; i++) {
-			{string z = code[i].to_s(); post("interpreting %s",z.data());}
+			//{string z = code[i].to_s(); post("interpreting %s",z.data());}
 			switch (int(code[i].a_type)) {
-			  case A_FLOAT: stack.push_back(code[i]); break;
-			  case A_SYMBOL: {
-				float f;
-				if (value_getfloat(code[i],&f)) RAISE("unknown variable '%s'",code[i].a_symbol->s_name);
-				stack.push_back(f);
+			  case A_FLOAT: case A_SYMBOL: stack.push_back(code[i]); break;
+			  //case A_VAR_V: {
+			  //} break;
+			  case A_VAR_A: {
+				int i = lookup(stack.back()); stack.pop_back();
+				t_symbol *t = stack.back(); stack.pop_back();
+				t_garray *a = (t_garray *)pd_findbyclass(t, garray_class); if (!a) RAISE("%s: no such array", t->s_name);
+				int npoints; t_word *vec;
+				if (!garray_getfloatwords(a, &npoints, &vec)) RAISE("%s: bad template for tabread", t->s_name);
+				stack.push_back(npoints ? vec[clip(i,0,npoints-1)].w_float : 0);
 			  } break;
 			  case A_VAR: {
 				stack.push_back(inputs[code[i].a_index & 255]);
 			  } break;
 			  case A_OP: {
 				Numop *op = TO(Numop *,t_atom2(code[i].a_symbol->s_name));
-				float b = stack.back(); stack.pop_back();
-				float a = stack.back(); stack.pop_back();
+				float b = lookup(stack.back()); stack.pop_back();
+				float a = lookup(stack.back()); stack.pop_back();
 				op->map(1,&a,b);
 				stack.push_back(a);
 			  } break;
 			  case A_OP1: {
 				Numop *op = TO(Numop *,t_atom2(code[i].a_symbol->s_name));
-				float a = stack.back(); stack.pop_back();
+				float a = lookup(stack.back()); stack.pop_back();
 				op->map(1,&a,0.f);
 				stack.push_back(a);
 			  } break;



More information about the Gridflow-cvs mailing list