|
FAUST compiler
0.9.9.6b8
|
00001 /************************************************************************ 00002 ************************************************************************ 00003 FAUST compiler 00004 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale 00005 --------------------------------------------------------------------- 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 ************************************************************************ 00020 ************************************************************************/ 00021 #define TRACE 00022 00032 #include "eval.hh" 00033 #include <stdio.h> 00034 #include "errormsg.hh" 00035 #include "ppbox.hh" 00036 #include "simplify.hh" 00037 #include "propagate.hh" 00038 #include "patternmatcher.hh" 00039 #include "signals.hh" 00040 #include "xtended.hh" 00041 #include "loopDetector.hh" 00042 #include "property.hh" 00043 #include "names.hh" 00044 #include "compatibility.hh" 00045 00046 00047 #include <assert.h> 00048 extern SourceReader gReader; 00049 extern int gMaxNameSize; 00050 extern bool gSimpleNames; 00051 extern bool gSimplifyDiagrams; 00052 // History 00053 // 23/05/2005 : New environment management 00054 00055 00056 //-------------- prototypes --------------------------------------------------------- 00057 static Tree a2sb(Tree exp); 00058 static Tree eval (Tree exp, Tree visited, Tree localValEnv); 00059 static Tree realeval (Tree exp, Tree visited, Tree localValEnv); 00060 static Tree revEvalList (Tree lexp, Tree visited, Tree localValEnv); 00061 static Tree applyList (Tree fun, Tree larg); 00062 static Tree iteratePar (Tree var, int num, Tree body, Tree visited, Tree localValEnv); 00063 static Tree iterateSeq (Tree id, int num, Tree body, Tree visited, Tree localValEnv); 00064 static Tree iterateSum (Tree id, int num, Tree body, Tree visited, Tree localValEnv); 00065 static Tree iterateProd (Tree id, int num, Tree body, Tree visited, Tree localValEnv); 00066 static Tree larg2par (Tree larg); 00067 static int eval2int (Tree exp, Tree visited, Tree localValEnv); 00068 static double eval2double (Tree exp, Tree visited, Tree localValEnv); 00069 static const char * evalLabel (const char* l, Tree visited, Tree localValEnv); 00070 00071 static Tree evalIdDef(Tree id, Tree visited, Tree env); 00072 00073 00074 00075 static Tree evalCase(Tree rules, Tree env); 00076 static Tree evalRuleList(Tree rules, Tree env); 00077 static Tree evalRule(Tree rule, Tree env); 00078 static Tree evalPatternList(Tree patterns, Tree env); 00079 static Tree evalPattern(Tree pattern, Tree env); 00080 00081 static Tree patternSimplification (Tree pattern); 00082 static bool isBoxNumeric (Tree in, Tree& out); 00083 00084 static Tree vec2list(const vector<Tree>& v); 00085 static void list2vec(Tree l, vector<Tree>& v); 00086 static Tree listn (int n, Tree e); 00087 00088 static Tree boxSimplification(Tree box); 00089 00090 // Public Interface 00091 //---------------------- 00092 00093 00101 Tree evalprocess (Tree eqlist) 00102 { 00103 Tree b = a2sb(eval(boxIdent("process"), nil, pushMultiClosureDefs(eqlist, nil, nil))); 00104 00105 if (gSimplifyDiagrams) { 00106 b = boxSimplification(b); 00107 } 00108 00109 return b; 00110 } 00111 00112 00113 /* Eval a documentation expression. */ 00114 00115 Tree evaldocexpr (Tree docexpr, Tree eqlist) 00116 { 00117 return a2sb(eval(docexpr, nil, pushMultiClosureDefs(eqlist, nil, nil))); 00118 } 00119 00120 00121 00122 // Private Implementation 00123 //------------------------ 00124 00132 property<Tree> gSymbolicBoxProperty; 00133 00134 static Tree real_a2sb(Tree exp); 00135 00136 static Tree a2sb(Tree exp) 00137 { 00138 Tree result; 00139 Tree id; 00140 00141 if (gSymbolicBoxProperty.get(exp, result)) { 00142 return result; 00143 } 00144 00145 result = real_a2sb(exp); 00146 if (result != exp && getDefNameProperty(exp, id)) { 00147 setDefNameProperty(result, id); // propagate definition name property when needed 00148 } 00149 gSymbolicBoxProperty.set(exp, result); 00150 return result; 00151 } 00152 00153 static int gBoxSlotNumber = 0; 00154 00155 static Tree real_a2sb(Tree exp) 00156 { 00157 Tree abstr, visited, unusedEnv, localValEnv, var, name, body; 00158 00159 if (isClosure(exp, abstr, unusedEnv, visited, localValEnv)) { 00160 00161 if (isBoxIdent(abstr)) { 00162 // special case introduced with access and components 00163 Tree result = a2sb(eval(abstr, visited, localValEnv)); 00164 00165 // propagate definition name property when needed 00166 if (getDefNameProperty(exp, name)) setDefNameProperty(result, name); 00167 return result; 00168 00169 } else if (isBoxAbstr(abstr, var, body)) { 00170 // Here we have remaining abstraction that we will try to 00171 // transform in a symbolic box by applying it to a slot 00172 00173 Tree slot = boxSlot(++gBoxSlotNumber); 00174 stringstream s; s << boxpp(var); 00175 setDefNameProperty(slot, s.str() ); // ajout YO 00176 00177 // Apply the abstraction to the slot 00178 Tree result = boxSymbolic(slot, a2sb(eval(body, visited, pushValueDef(var, slot, localValEnv)))); 00179 00180 // propagate definition name property when needed 00181 if (getDefNameProperty(exp, name)) setDefNameProperty(result, name); 00182 return result; 00183 00184 } else if (isBoxEnvironment(abstr)) { 00185 return abstr; 00186 00187 } else { 00188 evalerror(yyfilename, -1, " a2sb : internal error : not an abstraction inside closure ", exp); 00189 exit(1); 00190 } 00191 00192 } else if (isBoxPatternMatcher(exp)) { 00193 // Here we have remaining PM rules that we will try to 00194 // transform in a symbolic box by applying it to a slot 00195 00196 Tree slot = boxSlot(++gBoxSlotNumber); 00197 stringstream s; s << "PM" << gBoxSlotNumber; 00198 setDefNameProperty(slot, s.str() ); 00199 00200 // apply the PM rules to the slot and transfoms the result in a symbolic box 00201 Tree result = boxSymbolic(slot, a2sb(applyList(exp, cons(slot,nil)))); 00202 00203 // propagate definition name property when needed 00204 if (getDefNameProperty(exp, name)) setDefNameProperty(result, name); 00205 return result; 00206 00207 } else { 00208 // it is a constructor : transform each branches 00209 unsigned int ar = exp->arity(); 00210 tvec B(ar); 00211 bool modified = false; 00212 for (unsigned int i = 0; i < ar; i++) { 00213 Tree b = exp->branch(i); 00214 Tree m = a2sb(b); 00215 B[i] = m; 00216 if (b != m) modified=true; 00217 } 00218 Tree r = (modified) ? CTree::make(exp->node(), B) : exp; 00219 return r; 00220 } 00221 } 00222 00223 static bool autoName(Tree exp , Tree& id) 00224 { 00225 stringstream s; s << boxpp(exp); 00226 id = tree(s.str().c_str()); 00227 return true; 00228 } 00229 00230 bool getArgName(Tree t, Tree& id) 00231 { 00232 //return getDefNameProperty(t, id) || autoName(t, id) ; 00233 return autoName(t, id) ; 00234 } 00235 00236 00237 00247 static loopDetector LD(1024, 512); 00248 00249 00250 static Node EVALPROPERTY(symbol("EvalProperty")); 00251 00258 void setEvalProperty(Tree box, Tree env, Tree value) 00259 { 00260 setProperty(box, tree(EVALPROPERTY,env), value); 00261 } 00262 00263 00271 bool getEvalProperty(Tree box, Tree env, Tree& value) 00272 { 00273 return getProperty(box, tree(EVALPROPERTY,env), value); 00274 } 00275 00276 00277 static Tree eval (Tree exp, Tree visited, Tree localValEnv) 00278 { 00279 Tree id; 00280 Tree result; 00281 00282 if (!getEvalProperty(exp, localValEnv, result)) { 00283 LD.detect(cons(exp,localValEnv)); 00284 //cerr << "ENTER eval("<< *exp << ") with env " << *localValEnv << endl; 00285 result = realeval(exp, visited, localValEnv); 00286 setEvalProperty(exp, localValEnv, result); 00287 //cerr << "EXIT eval(" << *exp << ") IS " << *result << " with env " << *localValEnv << endl; 00288 if (getDefNameProperty(exp, id)) { 00289 setDefNameProperty(result, id); // propagate definition name property 00290 } 00291 } 00292 return result; 00293 } 00294 00305 static Tree realeval (Tree exp, Tree visited, Tree localValEnv) 00306 { 00307 //Tree def; 00308 Tree fun; 00309 Tree arg; 00310 Tree var, num, body, ldef; 00311 Tree label; 00312 Tree cur, lo, hi, step; 00313 Tree e1, e2, exp2, notused, visited2, lenv2; 00314 Tree rules; 00315 Tree id; 00316 00317 //cerr << "EVAL " << *exp << " (visited : " << *visited << ")" << endl; 00318 //cerr << "REALEVAL of " << *exp << endl; 00319 00320 xtended* xt = (xtended*) getUserData(exp); 00321 00322 00323 // constants 00324 //----------- 00325 00326 if ( xt || 00327 isBoxInt(exp) || isBoxReal(exp) || 00328 isBoxWire(exp) || isBoxCut(exp) || 00329 isBoxPrim0(exp) || isBoxPrim1(exp) || 00330 isBoxPrim2(exp) || isBoxPrim3(exp) || 00331 isBoxPrim4(exp) || isBoxPrim5(exp) || 00332 isBoxFFun(exp) || isBoxFConst(exp) || isBoxFVar(exp) ) { 00333 return exp; 00334 00335 // block-diagram constructors 00336 //--------------------------- 00337 00338 } else if ( isBoxSeq(exp, e1, e2) ) { 00339 return boxSeq(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00340 00341 } else if ( isBoxPar(exp, e1, e2) ) { 00342 return boxPar(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00343 00344 } else if ( isBoxRec(exp, e1, e2) ) { 00345 return boxRec(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00346 00347 } else if ( isBoxSplit(exp, e1, e2) ) { 00348 return boxSplit(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00349 00350 } else if ( isBoxMerge(exp, e1, e2) ) { 00351 return boxMerge(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00352 00353 // Modules 00354 //-------- 00355 00356 } else if (isBoxAccess(exp, body, var)) { 00357 Tree val = eval(body, visited, localValEnv); 00358 if (isClosure(val, exp2, notused, visited2, lenv2)) { 00359 // it is a closure, we have an environment to access 00360 return eval(closure(var,notused,visited2,lenv2), visited, localValEnv); 00361 } else { 00362 evalerror(getDefFileProp(exp), getDefLineProp(exp), "No environment to access ", exp); 00363 exit(1); 00364 } 00365 00367 00368 } else if (isBoxModifLocalDef(exp, body, ldef)) { 00369 Tree val = eval(body, visited, localValEnv); 00370 if (isClosure(val, exp2, notused, visited2, lenv2)) { 00371 // we rebuild the closure using a copy of the original environment 00372 // modified with some new definitions 00373 Tree lenv3 = copyEnvReplaceDefs(lenv2, ldef, visited2, localValEnv); 00374 return eval(closure(exp2,notused,visited2,lenv3), visited, localValEnv); 00375 } else { 00376 00377 evalerror(getDefFileProp(exp), getDefLineProp(exp), "not a closure ", val); 00378 evalerror(getDefFileProp(exp), getDefLineProp(exp), "No environment to access ", exp); 00379 exit(1); 00380 } 00381 00383 00384 } else if (isBoxComponent(exp, label)) { 00385 string fname = tree2str(label); 00386 Tree eqlst = gReader.expandlist(gReader.getlist(fname)); 00387 Tree res = closure(boxIdent("process"), nil, nil, pushMultiClosureDefs(eqlst, nil, nil)); 00388 setDefNameProperty(res, label); 00389 //cerr << "component is " << boxpp(res) << endl; 00390 return res; 00391 00392 } else if (isBoxLibrary(exp, label)) { 00393 string fname = tree2str(label); 00394 Tree eqlst = gReader.expandlist(gReader.getlist(fname)); 00395 Tree res = closure(boxEnvironment(), nil, nil, pushMultiClosureDefs(eqlst, nil, nil)); 00396 setDefNameProperty(res, label); 00397 //cerr << "component is " << boxpp(res) << endl; 00398 return res; 00399 00400 00401 // user interface elements 00402 //------------------------ 00403 00404 } else if (isBoxButton(exp, label)) { 00405 const char* l1 = tree2str(label); 00406 const char* l2= evalLabel(l1, visited, localValEnv); 00407 //cout << "button label : " << l1 << " become " << l2 << endl; 00408 return ((l1 == l2) ? exp : boxButton(tree(l2))); 00409 00410 } else if (isBoxCheckbox(exp, label)) { 00411 const char* l1 = tree2str(label); 00412 const char* l2= evalLabel(l1, visited, localValEnv); 00413 //cout << "check box label : " << l1 << " become " << l2 << endl; 00414 return ((l1 == l2) ? exp : boxCheckbox(tree(l2))); 00415 00416 } else if (isBoxVSlider(exp, label, cur, lo, hi, step)) { 00417 const char* l1 = tree2str(label); 00418 const char* l2= evalLabel(l1, visited, localValEnv); 00419 return ( boxVSlider(tree(l2), 00420 tree(eval2double(cur, visited, localValEnv)), 00421 tree(eval2double(lo, visited, localValEnv)), 00422 tree(eval2double(hi, visited, localValEnv)), 00423 tree(eval2double(step, visited, localValEnv)))); 00424 00425 } else if (isBoxHSlider(exp, label, cur, lo, hi, step)) { 00426 const char* l1 = tree2str(label); 00427 const char* l2= evalLabel(l1, visited, localValEnv); 00428 return ( boxHSlider(tree(l2), 00429 tree(eval2double(cur, visited, localValEnv)), 00430 tree(eval2double(lo, visited, localValEnv)), 00431 tree(eval2double(hi, visited, localValEnv)), 00432 tree(eval2double(step, visited, localValEnv)))); 00433 00434 } else if (isBoxNumEntry(exp, label, cur, lo, hi, step)) { 00435 const char* l1 = tree2str(label); 00436 const char* l2= evalLabel(l1, visited, localValEnv); 00437 return (boxNumEntry(tree(l2), 00438 tree(eval2double(cur, visited, localValEnv)), 00439 tree(eval2double(lo, visited, localValEnv)), 00440 tree(eval2double(hi, visited, localValEnv)), 00441 tree(eval2double(step, visited, localValEnv)))); 00442 00443 } else if (isBoxVGroup(exp, label, arg)) { 00444 const char* l1 = tree2str(label); 00445 const char* l2= evalLabel(l1, visited, localValEnv); 00446 return boxVGroup(tree(l2), eval(arg, visited, localValEnv) ); 00447 00448 } else if (isBoxHGroup(exp, label, arg)) { 00449 const char* l1 = tree2str(label); 00450 const char* l2= evalLabel(l1, visited, localValEnv); 00451 return boxHGroup(tree(l2), eval(arg, visited, localValEnv) ); 00452 00453 } else if (isBoxTGroup(exp, label, arg)) { 00454 const char* l1 = tree2str(label); 00455 const char* l2= evalLabel(l1, visited, localValEnv); 00456 return boxTGroup(tree(l2), eval(arg, visited, localValEnv) ); 00457 00458 } else if (isBoxHBargraph(exp, label, lo, hi)) { 00459 const char* l1 = tree2str(label); 00460 const char* l2= evalLabel(l1, visited, localValEnv); 00461 return boxHBargraph(tree(l2), 00462 tree(eval2double(lo, visited, localValEnv)), 00463 tree(eval2double(hi, visited, localValEnv))); 00464 00465 } else if (isBoxVBargraph(exp, label, lo, hi)) { 00466 const char* l1 = tree2str(label); 00467 const char* l2= evalLabel(l1, visited, localValEnv); 00468 return boxVBargraph(tree(l2), 00469 tree(eval2double(lo, visited, localValEnv)), 00470 tree(eval2double(hi, visited, localValEnv))); 00471 00472 // lambda calculus 00473 //---------------- 00474 00475 } else if (isBoxIdent(exp)) { 00476 return evalIdDef(exp, visited, localValEnv); 00477 00478 } else if (isBoxWithLocalDef(exp, body, ldef)) { 00479 return eval(body, visited, pushMultiClosureDefs(ldef, visited, localValEnv)); 00480 00481 } else if (isBoxAppl(exp, fun, arg)) { 00482 return applyList( eval(fun, visited, localValEnv), 00483 revEvalList(arg, visited, localValEnv) ); 00484 00485 } else if (isBoxAbstr(exp)) { 00486 // it is an abstraction : return a closure 00487 return closure(exp, nil, visited, localValEnv); 00488 00489 } else if (isBoxEnvironment(exp)) { 00490 // environment : return also a closure 00491 return closure(exp, nil, visited, localValEnv); 00492 00493 } else if (isClosure(exp, exp2, notused, visited2, lenv2)) { 00494 00495 if (isBoxAbstr(exp2)) { 00496 // a 'real' closure 00497 return closure(exp2, nil, setUnion(visited,visited2), lenv2); 00498 } else if (isBoxEnvironment(exp2)) { 00499 // a 'real' closure 00500 return closure(exp2, nil, setUnion(visited,visited2), lenv2); 00501 } else { 00502 // it was a suspended evaluation 00503 return eval(exp2, setUnion(visited,visited2), lenv2); 00504 } 00505 00506 // Algorithmic constructions 00507 //-------------------------- 00508 00509 } else if (isBoxIPar(exp, var, num, body)) { 00510 int n = eval2int(num, visited, localValEnv); 00511 return iteratePar(var, n, body, visited, localValEnv); 00512 00513 } else if (isBoxISeq(exp, var, num, body)) { 00514 int n = eval2int(num, visited, localValEnv); 00515 return iterateSeq(var, n, body, visited, localValEnv); 00516 00517 } else if (isBoxISum(exp, var, num, body)) { 00518 int n = eval2int(num, visited, localValEnv); 00519 return iterateSum(var, n, body, visited, localValEnv); 00520 00521 } else if (isBoxIProd(exp, var, num, body)) { 00522 int n = eval2int(num, visited, localValEnv); 00523 return iterateProd(var, n, body, visited, localValEnv); 00524 00525 } else if (isBoxSlot(exp)) { 00526 return exp; 00527 00528 } else if (isBoxSymbolic(exp)) { 00529 00530 return exp; 00531 00532 00533 // Pattern matching extension 00534 //--------------------------- 00535 00536 } else if (isBoxCase(exp, rules)) { 00537 return evalCase(rules, localValEnv); 00538 00539 } else if (isBoxPatternVar(exp, id)) { 00540 return exp; 00541 //return evalIdDef(id, visited, localValEnv); 00542 00543 } else if (isBoxPatternMatcher(exp)) { 00544 return exp; 00545 00546 } else { 00547 cerr << "ERROR : EVAL don't intercept : " << *exp << endl; 00548 assert(false); 00549 } 00550 } 00551 00552 /* Deconstruct a (BDA) op pattern (YO). */ 00553 00554 static inline bool isBoxPatternOp(Tree box, Node& n, Tree& t1, Tree& t2) 00555 { 00556 if ( isBoxPar(box, t1, t2) || 00557 isBoxSeq(box, t1, t2) || 00558 isBoxSplit(box, t1, t2) || 00559 isBoxMerge(box, t1, t2) || 00560 isBoxRec(box, t1, t2) ) 00561 { 00562 n = box->node(); 00563 return true; 00564 } else { 00565 return false; 00566 } 00567 } 00568 00569 00570 Tree NUMERICPROPERTY = tree(symbol("NUMERICPROPERTY")); 00571 00572 void setNumericProperty(Tree t, Tree num) 00573 { 00574 setProperty(t, NUMERICPROPERTY, num); 00575 } 00576 00577 bool getNumericProperty(Tree t, Tree& num) 00578 { 00579 return getProperty(t, NUMERICPROPERTY, num); 00580 } 00581 00588 /* uncomment for debugging output */ 00589 //#define DEBUG 00590 Tree simplifyPattern (Tree value) 00591 { 00592 Tree num; 00593 if (!getNumericProperty(value,num)) { 00594 if (!isBoxNumeric(value,num)) { 00595 num = value; 00596 } 00597 setNumericProperty(value,num); 00598 } 00599 return num; 00600 } 00601 00602 00603 static bool isBoxNumeric (Tree in, Tree& out) 00604 { 00605 int numInputs, numOutputs; 00606 double x; 00607 int i; 00608 Tree v; 00609 00610 if (isBoxInt(in, &i) || isBoxReal(in, &x)) { 00611 out = in; 00612 return true; 00613 } else { 00614 v = a2sb(in); 00615 if ( getBoxType(v, &numInputs, &numOutputs) && (numInputs == 0) && (numOutputs == 1) ) { 00616 // potential numerical expression 00617 Tree lsignals = boxPropagateSig(nil, v , makeSigInputList(numInputs) ); 00618 Tree res = simplify(hd(lsignals)); 00619 if (isSigReal(res, &x)) { 00620 out = boxReal(x); 00621 return true; 00622 } 00623 if (isSigInt(res, &i)) { 00624 out = boxInt(i); 00625 return true; 00626 } 00627 } 00628 return false; 00629 } 00630 } 00631 00632 static Tree patternSimplification (Tree pattern) 00633 { 00634 00635 Node n(0); 00636 Tree v, t1, t2; 00637 00638 if (isBoxNumeric(pattern, v)) { 00639 return v; 00640 } else if (isBoxPatternOp(pattern, n, t1, t2)) { 00641 return tree(n, patternSimplification(t1), patternSimplification(t2)); 00642 } else { 00643 return pattern; 00644 } 00645 } 00646 00647 00648 00662 static double eval2double (Tree exp, Tree visited, Tree localValEnv) 00663 { 00664 Tree diagram = a2sb(eval(exp, visited, localValEnv)); // pour getBoxType 00665 int numInputs, numOutputs; 00666 getBoxType(diagram, &numInputs, &numOutputs); 00667 if ( (numInputs > 0) || (numOutputs != 1) ) { 00668 evalerror (yyfilename, yylineno, "not a constant expression of type : (0->1)", exp); 00669 return 1; 00670 } else { 00671 Tree lsignals = boxPropagateSig(nil, diagram , makeSigInputList(numInputs) ); 00672 Tree val = simplify(hd(lsignals)); 00673 return tree2float(val); 00674 } 00675 } 00676 00677 00691 static int eval2int (Tree exp, Tree visited, Tree localValEnv) 00692 { 00693 Tree diagram = a2sb(eval(exp, visited, localValEnv)); // pour getBoxType() 00694 int numInputs, numOutputs; 00695 getBoxType(diagram, &numInputs, &numOutputs); 00696 if ( (numInputs > 0) || (numOutputs != 1) ) { 00697 evalerror (yyfilename, yylineno, "not a constant expression of type : (0->1)", exp); 00698 return 1; 00699 } else { 00700 Tree lsignals = boxPropagateSig(nil, diagram , makeSigInputList(numInputs) ); 00701 Tree val = simplify(hd(lsignals)); 00702 return tree2int(val); 00703 } 00704 } 00705 00706 static bool isDigitChar(char c) 00707 { 00708 return (c >= '0') & (c <= '9'); 00709 } 00710 00711 static bool isIdentChar(char c) 00712 { 00713 return ((c >= 'a') & (c <= 'z')) || ((c >= 'A') & (c <= 'Z')) || ((c >= '0') & (c <= '9')) || (c == '_'); 00714 } 00715 00716 const char* Formats [] = {"%d", "%1d", "%2d", "%3d", "%4d"}; 00717 00718 static char* writeIdentValue(char* dst, int format, const char* ident, Tree visited, Tree localValEnv) 00719 { 00720 int n = eval2int(boxIdent(ident), visited, localValEnv); 00721 int i = min(4,max(format,0)); 00722 00723 return dst + sprintf(dst, Formats[i], n); 00724 } 00725 00726 static const char * evalLabel (const char* label, Tree visited, Tree localValEnv) 00727 { 00728 char res[2000]; 00729 char ident[64]; 00730 00731 const char* src = &label[0]; 00732 char* dst = &res[0]; 00733 char* id = &ident[0]; 00734 00735 bool parametric = false; 00736 int state = 0; int format = 0; 00737 char c; 00738 00739 while ((c=*src++)) { 00740 if (state == 0) { 00741 // outside ident mode 00742 if (c == '%') { 00743 // look ahead for next char 00744 if (*src == '%') { 00745 *dst++ = *src++; // copy escape char and skip one char 00746 } else { 00747 state = 1; // prepare ident mode 00748 format = 0; 00749 parametric = true; 00750 id = &ident[0]; 00751 } 00752 } else { 00753 *dst++ = c; // copy char 00754 } 00755 } else if (state == 1) { 00756 // read the format 00757 if (isDigitChar(c)) { 00758 format = format*10 + (c-'0'); 00759 } else { 00760 state = 2; 00761 --src; // unread !!! 00762 } 00763 00764 } else { 00765 00766 // within ident mode 00767 if (isIdentChar(c)) { 00768 *id++ = c; 00769 } else { 00770 *id = 0; 00771 dst = writeIdentValue(dst, format, ident, visited, localValEnv); 00772 state = 0; 00773 src -= 1; 00774 } 00775 } 00776 } 00777 00778 if (state == 2) { 00779 *id = 0; 00780 dst = writeIdentValue(dst, format, ident, visited, localValEnv); 00781 } 00782 *dst = 0; 00783 return (parametric) ? strdup(res) : label; 00784 } 00785 00786 00787 00801 static Tree iteratePar (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00802 { 00803 assert (num>0); 00804 00805 Tree res = eval(body, visited, pushValueDef(id, tree(num-1), localValEnv)); 00806 for (int i = num-2; i >= 0; i--) { 00807 res = boxPar(eval(body, visited, pushValueDef(id, tree(i), localValEnv)), res); 00808 } 00809 00810 return res; 00811 } 00812 00813 00814 00827 static Tree iterateSeq (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00828 { 00829 assert (num>0); 00830 00831 Tree res = eval(body, visited, pushValueDef(id, tree(num-1), localValEnv)); 00832 for (int i = num-2; i >= 0; i--) { 00833 res = boxSeq(eval(body, visited, pushValueDef(id, tree(i), localValEnv)), res); 00834 } 00835 00836 return res; 00837 } 00838 00839 00840 00854 static Tree iterateSum (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00855 { 00856 assert (num>0); 00857 00858 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv)); 00859 00860 for (int i = 1; i < num; i++) { 00861 res = boxSeq(boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv))),boxPrim2(sigAdd)) ; 00862 } 00863 00864 return res; 00865 } 00866 00867 00868 00882 static Tree iterateProd (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00883 { 00884 assert (num>0); 00885 00886 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv)); 00887 00888 for (int i = 1; i < num; i++) { 00889 res = boxSeq(boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv))),boxPrim2(sigMul)) ; 00890 } 00891 00892 return res; 00893 } 00894 00903 #if 1 00904 static bool boxlistOutputs(Tree boxlist, int* outputs) 00905 { 00906 int ins, outs; 00907 00908 *outputs = 0; 00909 while (!isNil(boxlist)) 00910 { 00911 Tree b = a2sb(hd(boxlist)); // for getBoxType, suppose list of evaluated boxes 00912 if (getBoxType(b, &ins, &outs)) { 00913 *outputs += outs; 00914 } else { 00915 // arbitrary output arity set to 1 00916 // when can't be determined 00917 *outputs += 1; 00918 } 00919 boxlist = tl(boxlist); 00920 } 00921 return isNil(boxlist); 00922 } 00923 #else 00924 static bool boxlistOutputs(Tree boxlist, int* outputs) 00925 { 00926 int ins, outs; 00927 00928 *outputs = 0; 00929 while (!isNil(boxlist) && getBoxType(hd(boxlist), &ins, &outs)) { 00930 *outputs += outs; 00931 boxlist = tl(boxlist); 00932 } 00933 return isNil(boxlist); 00934 } 00935 #endif 00936 00940 static Tree nwires(int n) 00941 { 00942 Tree l = nil; 00943 while (n--) { l = cons(boxWire(), l); } 00944 return l; 00945 } 00946 00947 00959 static Tree applyList (Tree fun, Tree larg) 00960 { 00961 Tree abstr; 00962 Tree globalDefEnv; 00963 Tree visited; 00964 Tree localValEnv; 00965 Tree envList; 00966 Tree originalRules; 00967 Tree revParamList; 00968 00969 Tree id; 00970 Tree body; 00971 00972 Automaton* automat; 00973 int state; 00974 00975 prim2 p2; 00976 00977 //cerr << "applyList (" << *fun << ", " << *larg << ")" << endl; 00978 00979 if (isNil(larg)) return fun; 00980 00981 if (isBoxError(fun) || isBoxError(larg)) { 00982 return boxError(); 00983 } 00984 00985 if (isBoxPatternMatcher(fun, automat, state, envList, originalRules, revParamList)) { 00986 Tree result; 00987 int state2; 00988 vector<Tree> envVect; 00989 00990 list2vec(envList, envVect); 00991 //cerr << "applyList/apply_pattern_matcher(" << automat << "," << state << "," << *hd(larg) << ")" << endl; 00992 state2 = apply_pattern_matcher(automat, state, hd(larg), result, envVect); 00993 //cerr << "state2 = " << state2 << "; result = " << *result << endl; 00994 if (state2 >= 0 && isNil(result)) { 00995 // we need to continue the pattern matching 00996 return applyList( 00997 boxPatternMatcher(automat, state2, vec2list(envVect), originalRules, cons(hd(larg),revParamList)), 00998 tl(larg) ); 00999 } else if (state2 < 0) { 01000 cerr << "ERROR : pattern matching failed, no rule of " << boxpp(boxCase(originalRules)) 01001 << " matches argument list " << boxpp(reverse(cons(hd(larg), revParamList))) << endl; 01002 exit(1); 01003 } else { 01004 // Pattern Matching was succesful 01005 // the result is a closure that we need to evaluate. 01006 if (isClosure(result, body, globalDefEnv, visited, localValEnv)) { 01007 // why ??? return simplifyPattern(eval(body, nil, localValEnv)); 01008 //return eval(body, nil, localValEnv); 01009 return applyList(eval(body, nil, localValEnv), tl(larg)); 01010 } else { 01011 cerr << "wrong result from pattern matching (not a closure) : " << boxpp(result) << endl; 01012 return boxError(); 01013 } 01014 } 01015 } 01016 if (!isClosure(fun, abstr, globalDefEnv, visited, localValEnv)) { 01017 // principle : f(a,b,c,...) ==> (a,b,c,...):f 01018 int ins, outs; 01019 01020 // check arity of function 01021 Tree efun = a2sb(fun); 01022 //cerr << "TRACEPOINT 1 : " << boxpp(efun) << endl; 01023 if (!getBoxType(efun, &ins, &outs)) { // on laisse comme ca pour le moment 01024 // we can't determine the input arity of the expression 01025 // hope for the best 01026 return boxSeq(larg2par(larg), fun); 01027 } 01028 01029 // check arity of arg list 01030 if (!boxlistOutputs(larg,&outs)) { 01031 // we don't know yet the output arity of larg. Therefore we can't 01032 // do any arity checking nor add _ to reach the required number of arguments 01033 // cerr << "warning : can't infere the type of : " << boxpp(larg) << endl; 01034 return boxSeq(larg2par(larg), fun); 01035 } 01036 01037 if (outs > ins) { 01038 cerr << "too much arguments : " << outs << ", instead of : " << ins << endl; 01039 cerr << "when applying : " << boxpp(fun) << endl 01040 << " to : " << boxpp(larg) << endl; 01041 assert(false); 01042 } 01043 01044 if ( (outs == 1) 01045 && 01046 ( ( isBoxPrim2(fun, &p2) && (p2 != sigPrefix) ) 01047 || ( getUserData(fun) && ((xtended*)getUserData(fun))->isSpecialInfix() ) ) ) { 01048 // special case : /(3) ==> _,3 : / 01049 Tree larg2 = concat(nwires(ins-outs), larg); 01050 return boxSeq(larg2par(larg2), fun); 01051 01052 } else { 01053 01054 Tree larg2 = concat(larg, nwires(ins-outs)); 01055 return boxSeq(larg2par(larg2), fun); 01056 } 01057 } 01058 01059 if (isBoxEnvironment(abstr)) { 01060 evalerrorbox(yyfilename, -1, "an environment can't be used as a function", fun); 01061 exit(1); 01062 } 01063 01064 if (!isBoxAbstr(abstr, id, body)) { 01065 evalerror(yyfilename, -1, "(internal) not an abstraction inside closure", fun); 01066 exit(1); 01067 } 01068 01069 // try to synthetise a name from the function name and the argument name 01070 { 01071 Tree arg = eval(hd(larg), visited, localValEnv); 01072 Tree narg; if ( isBoxNumeric(arg,narg) ) { arg = narg; } 01073 Tree f = eval(body, visited, pushValueDef(id, arg, localValEnv)); 01074 01075 Tree fname; 01076 if (getDefNameProperty(fun, fname)) { 01077 stringstream s; s << tree2str(fname); if (!gSimpleNames) s << "(" << boxpp(arg) << ")"; 01078 setDefNameProperty(f, s.str()); 01079 } 01080 return applyList(f, tl(larg)); 01081 } 01082 } 01083 01084 01085 01097 static Tree revEvalList (Tree lexp, Tree visited, Tree localValEnv) 01098 { 01099 Tree result = nil; 01100 //Tree lexp_orig = lexp; 01101 //cerr << "ENTER revEvalList(" << *lexp_orig << ", env:" << *localValEnv << ")" << endl; 01102 while (!isNil(lexp)) { 01103 result = cons(eval(hd(lexp), visited, localValEnv), result); 01104 lexp = tl(lexp); 01105 } 01106 01107 //cerr << "EXIT revEvalList(" << *lexp_orig << ", env:" << *localValEnv << ") -> " << *result << endl; 01108 return result; 01109 } 01110 01111 01112 01119 static Tree larg2par (Tree larg) 01120 { 01121 if (isNil(larg)) { 01122 evalerror(yyfilename, -1, "empty list of arguments", larg); 01123 exit(1); 01124 } 01125 if (isNil(tl(larg))) { 01126 return hd(larg); 01127 } 01128 return boxPar(hd(larg), larg2par(tl(larg))); 01129 } 01130 01131 01132 01133 01144 static Tree evalIdDef(Tree id, Tree visited, Tree lenv) 01145 { 01146 Tree def, name; 01147 01148 // search the environment env for a definition of symbol id 01149 while (!isNil(lenv) && !getProperty(lenv, id, def)) { 01150 lenv = lenv->branch(0); 01151 } 01152 01153 // check that the definition exists 01154 if (isNil(lenv)) { 01155 cerr << "undefined symbol " << *id << endl; 01156 evalerror(getDefFileProp(id), getDefLineProp(id), "undefined symbol ", id); 01157 exit(1); 01158 } 01159 01160 //cerr << "Id definition is " << *def << endl; 01161 // check that it is not a recursive definition 01162 Tree p = cons(id,lenv); 01163 // set the definition name property 01164 if (!getDefNameProperty(def, name)) { 01165 // if the definition has no name use the identifier 01166 stringstream s; s << boxpp(id); 01167 //XXXXXX setDefNameProperty(def, s.str()); 01168 } 01169 01170 // return the evaluated definition 01171 return eval(def, addElement(p,visited), nil); 01172 } 01173 01174 01182 static Tree listn (int n, Tree e) 01183 { 01184 return (n<= 0) ? nil : cons(e, listn(n-1,e)); 01185 } 01186 01192 static Node PMPROPERTYNODE(symbol("PMPROPERTY")); 01193 01194 static void setPMProperty(Tree t, Tree env, Tree pm) 01195 { 01196 setProperty(t, tree(PMPROPERTYNODE, env), pm); 01197 } 01198 01199 static bool getPMProperty(Tree t, Tree env, Tree& pm) 01200 { 01201 return getProperty(t, tree(PMPROPERTYNODE, env), pm); 01202 } 01203 01213 static Tree evalCase(Tree rules, Tree env) 01214 { 01215 Tree pm; 01216 if (!getPMProperty(rules, env, pm)) { 01217 Automaton* a = make_pattern_matcher(evalRuleList(rules, env)); 01218 pm = boxPatternMatcher(a, 0, listn(len(rules), pushEnvBarrier(env)), rules, nil); 01219 setPMProperty(rules, env, pm); 01220 } 01221 return pm; 01222 } 01223 01224 01228 static Tree evalRuleList(Tree rules, Tree env) 01229 { 01230 //cerr << "evalRuleList "<< *rules << " in " << *env << endl; 01231 if (isNil(rules)) return nil; 01232 else return cons(evalRule(hd(rules), env), evalRuleList(tl(rules), env)); 01233 } 01234 01235 01239 static Tree evalRule(Tree rule, Tree env) 01240 { 01241 //cerr << "evalRule "<< *rule << " in " << *env << endl; 01242 return cons(evalPatternList(left(rule), env), right(rule)); 01243 } 01244 01245 01249 static Tree evalPatternList(Tree patterns, Tree env) 01250 { 01251 if (isNil(patterns)) { 01252 return nil; 01253 } else { 01254 return cons( evalPattern(hd(patterns), env), 01255 evalPatternList(tl(patterns), env) ); 01256 } 01257 } 01258 01259 01264 static Tree evalPattern(Tree pattern, Tree env) 01265 { 01266 Tree p = eval(pattern, nil, env); 01267 return patternSimplification(p); 01268 } 01269 01270 01271 static void list2vec(Tree l, vector<Tree>& v) 01272 { 01273 while (!isNil(l)) { 01274 v.push_back(hd(l)); 01275 l = tl(l); 01276 } 01277 } 01278 01279 01280 static Tree vec2list(const vector<Tree>& v) 01281 { 01282 Tree l = nil; 01283 int n = v.size(); 01284 while (n--) { l = cons(v[n],l); } 01285 return l; 01286 } 01287 01288 01289 01290 01292 // further simplification : replace bloc-diagrams that denote constant number by this number 01294 01295 static property<Tree> SimplifiedBoxProperty; 01296 static Tree numericBoxSimplification(Tree box); 01297 static Tree insideBoxSimplification (Tree box); 01298 01303 Tree boxSimplification (Tree box) 01304 { 01305 Tree simplified; 01306 01307 if (SimplifiedBoxProperty.get(box,simplified)) { 01308 01309 return simplified; 01310 01311 } else { 01312 01313 simplified = numericBoxSimplification(box); 01314 01315 // transferts name property if any 01316 Tree name; if (getDefNameProperty(box, name)) setDefNameProperty(simplified, name); 01317 01318 // attach simplified expression as a property of original box 01319 SimplifiedBoxProperty.set(box,simplified); 01320 01321 return simplified; 01322 } 01323 } 01324 01328 Tree numericBoxSimplification(Tree box) 01329 { 01330 int ins, outs; 01331 Tree result; 01332 int i; 01333 double x; 01334 01335 if ( ! getBoxType(box, &ins, &outs)) { 01336 cout << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", Can't compute the box type of : " << *box << endl; 01337 exit(1); 01338 } 01339 01340 if (ins==0 && outs==1) { 01341 // this box can potentially denote a number 01342 if (isBoxInt(box, &i) || isBoxReal(box, &x)) { 01343 result = box; 01344 } else { 01345 // propagate signals to discover if it simplifies to a number 01346 int i; 01347 double x; 01348 Tree lsignals = boxPropagateSig(nil, box , makeSigInputList(0)); 01349 Tree s = simplify(hd(lsignals)); 01350 01351 if (isSigReal(s, &x)) { 01352 result = boxReal(x); 01353 } else if (isSigInt(s, &i)) { 01354 result = boxInt(i); 01355 } else { 01356 result = insideBoxSimplification(box); 01357 } 01358 } 01359 } else { 01360 // this box can't denote a number 01361 result = insideBoxSimplification(box); 01362 } 01363 return result; 01364 } 01365 01369 Tree insideBoxSimplification (Tree box) 01370 { 01371 int i; 01372 double r; 01373 prim0 p0; 01374 prim1 p1; 01375 prim2 p2; 01376 prim3 p3; 01377 prim4 p4; 01378 prim5 p5; 01379 01380 Tree t1, t2, ff, label, cur, min, max, step, type, name, file, slot, body; 01381 01382 01383 xtended* xt = (xtended*)getUserData(box); 01384 01385 // Extended Primitives 01386 01387 if (xt) { 01388 return box; 01389 } 01390 01391 // Numbers and Constants 01392 01393 else if (isBoxInt(box, &i)) { 01394 return box; 01395 } 01396 else if (isBoxReal(box, &r)) { 01397 return box; 01398 } 01399 01400 else if (isBoxFConst(box, type, name, file)) { 01401 return box; 01402 } 01403 01404 else if (isBoxFVar(box, type, name, file)) { 01405 return box; 01406 } 01407 01408 // Wire and Cut 01409 01410 else if (isBoxCut(box)) { 01411 return box; 01412 } 01413 01414 else if (isBoxWire(box)) { 01415 return box; 01416 } 01417 01418 // Primitives 01419 01420 else if (isBoxPrim0(box, &p0)) { 01421 return box; 01422 } 01423 01424 else if (isBoxPrim1(box, &p1)) { 01425 return box; 01426 } 01427 01428 else if (isBoxPrim2(box, &p2)) { 01429 return box; 01430 } 01431 01432 else if (isBoxPrim3(box, &p3)) { 01433 return box; 01434 } 01435 01436 else if (isBoxPrim4(box, &p4)) { 01437 return box; 01438 } 01439 01440 else if (isBoxPrim5(box, &p5)) { 01441 return box; 01442 } 01443 01444 else if (isBoxFFun(box, ff)) { 01445 return box; 01446 } 01447 01448 // User Interface Widgets 01449 01450 else if (isBoxButton(box, label)) { 01451 return box; 01452 } 01453 01454 else if (isBoxCheckbox(box, label)) { 01455 return box; 01456 } 01457 01458 else if (isBoxVSlider(box, label, cur, min, max, step)) { 01459 return box; 01460 } 01461 01462 else if (isBoxHSlider(box, label, cur, min, max, step)) { 01463 return box; 01464 } 01465 01466 else if (isBoxNumEntry(box, label, cur, min, max, step)) { 01467 return box; 01468 } 01469 01470 else if (isBoxVBargraph(box, label, min, max)) { 01471 return box; 01472 } 01473 01474 else if (isBoxHBargraph(box, label, min, max)) { 01475 return box; 01476 } 01477 01478 // User Interface Groups 01479 01480 else if (isBoxVGroup(box, label, t1)) { 01481 return boxVGroup(label, boxSimplification(t1)); 01482 } 01483 01484 else if (isBoxHGroup(box, label, t1)) { 01485 return boxHGroup(label, boxSimplification(t1)); 01486 } 01487 01488 else if (isBoxTGroup(box, label, t1)) { 01489 return boxTGroup(label, boxSimplification(t1)); 01490 } 01491 01492 // Slots and Symbolic Boxes 01493 01494 else if (isBoxSlot(box)) { 01495 return box;; 01496 } 01497 01498 else if (isBoxSymbolic(box, slot, body)){ 01499 01500 Tree b = boxSimplification(body); 01501 return boxSymbolic(slot,b); 01502 } 01503 01504 // Block Diagram Composition Algebra 01505 01506 else if (isBoxSeq(box, t1, t2)) { 01507 Tree s1 = boxSimplification(t1); 01508 Tree s2 = boxSimplification(t2); 01509 return boxSeq(s1,s2); 01510 } 01511 01512 else if (isBoxPar(box, t1, t2)) { 01513 Tree s1 = boxSimplification(t1); 01514 Tree s2 = boxSimplification(t2); 01515 return boxPar(s1,s2); 01516 } 01517 01518 else if (isBoxSplit(box, t1, t2)) { 01519 Tree s1 = boxSimplification(t1); 01520 Tree s2 = boxSimplification(t2); 01521 return boxSplit(s1,s2); 01522 } 01523 01524 else if (isBoxMerge(box, t1, t2)) { 01525 Tree s1 = boxSimplification(t1); 01526 Tree s2 = boxSimplification(t2); 01527 return boxMerge(s1,s2); 01528 } 01529 else if (isBoxRec(box, t1, t2)) { 01530 Tree s1 = boxSimplification(t1); 01531 Tree s2 = boxSimplification(t2); 01532 return boxRec(s1,s2); 01533 } 01534 01535 cout << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", unrecognised box expression : " << *box << endl; 01536 exit(1); 01537 return 0; 01538 }
1.8.0