|
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, 1); 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 LD.detect(cons(exp,localValEnv)); 00283 00284 if (!getEvalProperty(exp, localValEnv, result)) { 00285 //cerr << "ENTER eval("<< *exp << ") with env " << *localValEnv << endl; 00286 result = realeval(exp, visited, localValEnv); 00287 setEvalProperty(exp, localValEnv, result); 00288 //cerr << "EXIT eval(" << *exp << ") IS " << *result << " with env " << *localValEnv << endl; 00289 if (getDefNameProperty(exp, id)) { 00290 setDefNameProperty(result, id); // propagate definition name property 00291 } 00292 } 00293 return result; 00294 } 00295 00306 static Tree realeval (Tree exp, Tree visited, Tree localValEnv) 00307 { 00308 //Tree def; 00309 Tree fun; 00310 Tree arg; 00311 Tree var, num, body, ldef; 00312 Tree label; 00313 Tree cur, lo, hi, step; 00314 Tree e1, e2, exp2, notused, visited2, lenv2; 00315 Tree rules; 00316 Tree id; 00317 00318 //cerr << "EVAL " << *exp << " (visited : " << *visited << ")" << endl; 00319 //cerr << "REALEVAL of " << *exp << endl; 00320 00321 xtended* xt = (xtended*) getUserData(exp); 00322 00323 00324 // constants 00325 //----------- 00326 00327 if ( xt || 00328 isBoxInt(exp) || isBoxReal(exp) || 00329 isBoxWire(exp) || isBoxCut(exp) || 00330 isBoxPrim0(exp) || isBoxPrim1(exp) || 00331 isBoxPrim2(exp) || isBoxPrim3(exp) || 00332 isBoxPrim4(exp) || isBoxPrim5(exp) || 00333 isBoxFFun(exp) || isBoxFConst(exp) || isBoxFVar(exp) ) { 00334 return exp; 00335 00336 // block-diagram constructors 00337 //--------------------------- 00338 00339 } else if ( isBoxSeq(exp, e1, e2) ) { 00340 return boxSeq(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00341 00342 } else if ( isBoxPar(exp, e1, e2) ) { 00343 return boxPar(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00344 00345 } else if ( isBoxRec(exp, e1, e2) ) { 00346 return boxRec(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00347 00348 } else if ( isBoxSplit(exp, e1, e2) ) { 00349 return boxSplit(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00350 00351 } else if ( isBoxMerge(exp, e1, e2) ) { 00352 return boxMerge(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv)); 00353 00354 // Modules 00355 //-------- 00356 00357 } else if (isBoxAccess(exp, body, var)) { 00358 Tree val = eval(body, visited, localValEnv); 00359 if (isClosure(val, exp2, notused, visited2, lenv2)) { 00360 // it is a closure, we have an environment to access 00361 return eval(closure(var,notused,visited2,lenv2), visited, localValEnv); 00362 } else { 00363 evalerror(getDefFileProp(exp), getDefLineProp(exp), "No environment to access ", exp); 00364 exit(1); 00365 } 00366 00368 00369 } else if (isBoxModifLocalDef(exp, body, ldef)) { 00370 Tree val = eval(body, visited, localValEnv); 00371 if (isClosure(val, exp2, notused, visited2, lenv2)) { 00372 // we rebuild the closure using a copy of the original environment 00373 // modified with some new definitions 00374 Tree lenv3 = copyEnvReplaceDefs(lenv2, ldef, visited2, localValEnv); 00375 return eval(closure(exp2,notused,visited2,lenv3), visited, localValEnv); 00376 } else { 00377 00378 evalerror(getDefFileProp(exp), getDefLineProp(exp), "not a closure ", val); 00379 evalerror(getDefFileProp(exp), getDefLineProp(exp), "No environment to access ", exp); 00380 exit(1); 00381 } 00382 00384 00385 } else if (isBoxComponent(exp, label)) { 00386 string fname = tree2str(label); 00387 Tree eqlst = gReader.expandlist(gReader.getlist(fname)); 00388 Tree res = closure(boxIdent("process"), nil, nil, pushMultiClosureDefs(eqlst, nil, nil)); 00389 setDefNameProperty(res, label); 00390 //cerr << "component is " << boxpp(res) << endl; 00391 return res; 00392 00393 } else if (isBoxLibrary(exp, label)) { 00394 string fname = tree2str(label); 00395 Tree eqlst = gReader.expandlist(gReader.getlist(fname)); 00396 Tree res = closure(boxEnvironment(), nil, nil, pushMultiClosureDefs(eqlst, nil, nil)); 00397 setDefNameProperty(res, label); 00398 //cerr << "component is " << boxpp(res) << endl; 00399 return res; 00400 00401 00402 // user interface elements 00403 //------------------------ 00404 00405 } else if (isBoxButton(exp, label)) { 00406 const char* l1 = tree2str(label); 00407 const char* l2= evalLabel(l1, visited, localValEnv); 00408 //cout << "button label : " << l1 << " become " << l2 << endl; 00409 return ((l1 == l2) ? exp : boxButton(tree(l2))); 00410 00411 } else if (isBoxCheckbox(exp, label)) { 00412 const char* l1 = tree2str(label); 00413 const char* l2= evalLabel(l1, visited, localValEnv); 00414 //cout << "check box label : " << l1 << " become " << l2 << endl; 00415 return ((l1 == l2) ? exp : boxCheckbox(tree(l2))); 00416 00417 } else if (isBoxVSlider(exp, label, cur, lo, hi, step)) { 00418 const char* l1 = tree2str(label); 00419 const char* l2= evalLabel(l1, visited, localValEnv); 00420 return ( boxVSlider(tree(l2), 00421 tree(eval2double(cur, visited, localValEnv)), 00422 tree(eval2double(lo, visited, localValEnv)), 00423 tree(eval2double(hi, visited, localValEnv)), 00424 tree(eval2double(step, visited, localValEnv)))); 00425 00426 } else if (isBoxHSlider(exp, label, cur, lo, hi, step)) { 00427 const char* l1 = tree2str(label); 00428 const char* l2= evalLabel(l1, visited, localValEnv); 00429 return ( boxHSlider(tree(l2), 00430 tree(eval2double(cur, visited, localValEnv)), 00431 tree(eval2double(lo, visited, localValEnv)), 00432 tree(eval2double(hi, visited, localValEnv)), 00433 tree(eval2double(step, visited, localValEnv)))); 00434 00435 } else if (isBoxNumEntry(exp, label, cur, lo, hi, step)) { 00436 const char* l1 = tree2str(label); 00437 const char* l2= evalLabel(l1, visited, localValEnv); 00438 return (boxNumEntry(tree(l2), 00439 tree(eval2double(cur, visited, localValEnv)), 00440 tree(eval2double(lo, visited, localValEnv)), 00441 tree(eval2double(hi, visited, localValEnv)), 00442 tree(eval2double(step, visited, localValEnv)))); 00443 00444 } else if (isBoxVGroup(exp, label, arg)) { 00445 const char* l1 = tree2str(label); 00446 const char* l2= evalLabel(l1, visited, localValEnv); 00447 return boxVGroup(tree(l2), eval(arg, visited, localValEnv) ); 00448 00449 } else if (isBoxHGroup(exp, label, arg)) { 00450 const char* l1 = tree2str(label); 00451 const char* l2= evalLabel(l1, visited, localValEnv); 00452 return boxHGroup(tree(l2), eval(arg, visited, localValEnv) ); 00453 00454 } else if (isBoxTGroup(exp, label, arg)) { 00455 const char* l1 = tree2str(label); 00456 const char* l2= evalLabel(l1, visited, localValEnv); 00457 return boxTGroup(tree(l2), eval(arg, visited, localValEnv) ); 00458 00459 } else if (isBoxHBargraph(exp, label, lo, hi)) { 00460 const char* l1 = tree2str(label); 00461 const char* l2= evalLabel(l1, visited, localValEnv); 00462 return boxHBargraph(tree(l2), 00463 tree(eval2double(lo, visited, localValEnv)), 00464 tree(eval2double(hi, visited, localValEnv))); 00465 00466 } else if (isBoxVBargraph(exp, label, lo, hi)) { 00467 const char* l1 = tree2str(label); 00468 const char* l2= evalLabel(l1, visited, localValEnv); 00469 return boxVBargraph(tree(l2), 00470 tree(eval2double(lo, visited, localValEnv)), 00471 tree(eval2double(hi, visited, localValEnv))); 00472 00473 // lambda calculus 00474 //---------------- 00475 00476 } else if (isBoxIdent(exp)) { 00477 return evalIdDef(exp, visited, localValEnv); 00478 00479 } else if (isBoxWithLocalDef(exp, body, ldef)) { 00480 return eval(body, visited, pushMultiClosureDefs(ldef, visited, localValEnv)); 00481 00482 } else if (isBoxAppl(exp, fun, arg)) { 00483 return applyList( eval(fun, visited, localValEnv), 00484 revEvalList(arg, visited, localValEnv) ); 00485 00486 } else if (isBoxAbstr(exp)) { 00487 // it is an abstraction : return a closure 00488 return closure(exp, nil, visited, localValEnv); 00489 00490 } else if (isBoxEnvironment(exp)) { 00491 // environment : return also a closure 00492 return closure(exp, nil, visited, localValEnv); 00493 00494 } else if (isClosure(exp, exp2, notused, visited2, lenv2)) { 00495 00496 if (isBoxAbstr(exp2)) { 00497 // a 'real' closure 00498 return closure(exp2, nil, setUnion(visited,visited2), lenv2); 00499 } else if (isBoxEnvironment(exp2)) { 00500 // a 'real' closure 00501 return closure(exp2, nil, setUnion(visited,visited2), lenv2); 00502 } else { 00503 // it was a suspended evaluation 00504 return eval(exp2, setUnion(visited,visited2), lenv2); 00505 } 00506 00507 // Algorithmic constructions 00508 //-------------------------- 00509 00510 } else if (isBoxIPar(exp, var, num, body)) { 00511 int n = eval2int(num, visited, localValEnv); 00512 return iteratePar(var, n, body, visited, localValEnv); 00513 00514 } else if (isBoxISeq(exp, var, num, body)) { 00515 int n = eval2int(num, visited, localValEnv); 00516 return iterateSeq(var, n, body, visited, localValEnv); 00517 00518 } else if (isBoxISum(exp, var, num, body)) { 00519 int n = eval2int(num, visited, localValEnv); 00520 return iterateSum(var, n, body, visited, localValEnv); 00521 00522 } else if (isBoxIProd(exp, var, num, body)) { 00523 int n = eval2int(num, visited, localValEnv); 00524 return iterateProd(var, n, body, visited, localValEnv); 00525 00526 } else if (isBoxSlot(exp)) { 00527 return exp; 00528 00529 } else if (isBoxSymbolic(exp)) { 00530 00531 return exp; 00532 00533 00534 // Pattern matching extension 00535 //--------------------------- 00536 00537 } else if (isBoxCase(exp, rules)) { 00538 return evalCase(rules, localValEnv); 00539 00540 } else if (isBoxPatternVar(exp, id)) { 00541 return exp; 00542 //return evalIdDef(id, visited, localValEnv); 00543 00544 } else if (isBoxPatternMatcher(exp)) { 00545 return exp; 00546 00547 } else { 00548 cerr << "ERROR : EVAL don't intercept : " << *exp << endl; 00549 assert(false); 00550 } 00551 } 00552 00553 /* Deconstruct a (BDA) op pattern (YO). */ 00554 00555 static inline bool isBoxPatternOp(Tree box, Node& n, Tree& t1, Tree& t2) 00556 { 00557 if ( isBoxPar(box, t1, t2) || 00558 isBoxSeq(box, t1, t2) || 00559 isBoxSplit(box, t1, t2) || 00560 isBoxMerge(box, t1, t2) || 00561 isBoxRec(box, t1, t2) ) 00562 { 00563 n = box->node(); 00564 return true; 00565 } else { 00566 return false; 00567 } 00568 } 00569 00570 00571 Tree NUMERICPROPERTY = tree(symbol("NUMERICPROPERTY")); 00572 00573 void setNumericProperty(Tree t, Tree num) 00574 { 00575 setProperty(t, NUMERICPROPERTY, num); 00576 } 00577 00578 bool getNumericProperty(Tree t, Tree& num) 00579 { 00580 return getProperty(t, NUMERICPROPERTY, num); 00581 } 00582 00589 /* uncomment for debugging output */ 00590 //#define DEBUG 00591 Tree simplifyPattern (Tree value) 00592 { 00593 Tree num; 00594 if (!getNumericProperty(value,num)) { 00595 if (!isBoxNumeric(value,num)) { 00596 num = value; 00597 } 00598 setNumericProperty(value,num); 00599 } 00600 return num; 00601 } 00602 00603 00604 static bool isBoxNumeric (Tree in, Tree& out) 00605 { 00606 int numInputs, numOutputs; 00607 double x; 00608 int i; 00609 Tree v; 00610 00611 if (isBoxInt(in, &i) || isBoxReal(in, &x)) { 00612 out = in; 00613 return true; 00614 } else { 00615 v = a2sb(in); 00616 if ( getBoxType(v, &numInputs, &numOutputs) && (numInputs == 0) && (numOutputs == 1) ) { 00617 // potential numerical expression 00618 Tree lsignals = boxPropagateSig(nil, v , makeSigInputList(numInputs) ); 00619 Tree res = simplify(hd(lsignals)); 00620 if (isSigReal(res, &x)) { 00621 out = boxReal(x); 00622 return true; 00623 } 00624 if (isSigInt(res, &i)) { 00625 out = boxInt(i); 00626 return true; 00627 } 00628 } 00629 return false; 00630 } 00631 } 00632 00633 static Tree patternSimplification (Tree pattern) 00634 { 00635 00636 Node n(0); 00637 Tree v, t1, t2; 00638 00639 if (isBoxNumeric(pattern, v)) { 00640 return v; 00641 } else if (isBoxPatternOp(pattern, n, t1, t2)) { 00642 return tree(n, patternSimplification(t1), patternSimplification(t2)); 00643 } else { 00644 return pattern; 00645 } 00646 } 00647 00648 00649 00663 static double eval2double (Tree exp, Tree visited, Tree localValEnv) 00664 { 00665 Tree diagram = a2sb(eval(exp, visited, localValEnv)); // pour getBoxType 00666 int numInputs, numOutputs; 00667 getBoxType(diagram, &numInputs, &numOutputs); 00668 if ( (numInputs > 0) || (numOutputs != 1) ) { 00669 evalerror (yyfilename, yylineno, "not a constant expression of type : (0->1)", exp); 00670 return 1; 00671 } else { 00672 Tree lsignals = boxPropagateSig(nil, diagram , makeSigInputList(numInputs) ); 00673 Tree val = simplify(hd(lsignals)); 00674 return tree2float(val); 00675 } 00676 } 00677 00678 00692 static int eval2int (Tree exp, Tree visited, Tree localValEnv) 00693 { 00694 Tree diagram = a2sb(eval(exp, visited, localValEnv)); // pour getBoxType() 00695 int numInputs, numOutputs; 00696 getBoxType(diagram, &numInputs, &numOutputs); 00697 if ( (numInputs > 0) || (numOutputs != 1) ) { 00698 evalerror (yyfilename, yylineno, "not a constant expression of type : (0->1)", exp); 00699 return 1; 00700 } else { 00701 Tree lsignals = boxPropagateSig(nil, diagram , makeSigInputList(numInputs) ); 00702 Tree val = simplify(hd(lsignals)); 00703 return tree2int(val); 00704 } 00705 } 00706 00707 static bool isDigitChar(char c) 00708 { 00709 return (c >= '0') & (c <= '9'); 00710 } 00711 00712 static bool isIdentChar(char c) 00713 { 00714 return ((c >= 'a') & (c <= 'z')) || ((c >= 'A') & (c <= 'Z')) || ((c >= '0') & (c <= '9')) || (c == '_'); 00715 } 00716 00717 const char* Formats [] = {"%d", "%1d", "%2d", "%3d", "%4d"}; 00718 00719 static char* writeIdentValue(char* dst, int format, const char* ident, Tree visited, Tree localValEnv) 00720 { 00721 int n = eval2int(boxIdent(ident), visited, localValEnv); 00722 int i = min(4,max(format,0)); 00723 00724 return dst + sprintf(dst, Formats[i], n); 00725 } 00726 00727 static const char * evalLabel (const char* label, Tree visited, Tree localValEnv) 00728 { 00729 char res[2000]; 00730 char ident[64]; 00731 00732 const char* src = &label[0]; 00733 char* dst = &res[0]; 00734 char* id = &ident[0]; 00735 00736 bool parametric = false; 00737 int state = 0; int format = 0; 00738 char c; 00739 00740 while ((c=*src++)) { 00741 if (state == 0) { 00742 // outside ident mode 00743 if (c == '%') { 00744 // look ahead for next char 00745 if (*src == '%') { 00746 *dst++ = *src++; // copy escape char and skip one char 00747 } else { 00748 state = 1; // prepare ident mode 00749 format = 0; 00750 parametric = true; 00751 id = &ident[0]; 00752 } 00753 } else { 00754 *dst++ = c; // copy char 00755 } 00756 } else if (state == 1) { 00757 // read the format 00758 if (isDigitChar(c)) { 00759 format = format*10 + (c-'0'); 00760 } else { 00761 state = 2; 00762 --src; // unread !!! 00763 } 00764 00765 } else { 00766 00767 // within ident mode 00768 if (isIdentChar(c)) { 00769 *id++ = c; 00770 } else { 00771 *id = 0; 00772 dst = writeIdentValue(dst, format, ident, visited, localValEnv); 00773 state = 0; 00774 src -= 1; 00775 } 00776 } 00777 } 00778 00779 if (state == 2) { 00780 *id = 0; 00781 dst = writeIdentValue(dst, format, ident, visited, localValEnv); 00782 } 00783 *dst = 0; 00784 return (parametric) ? strdup(res) : label; 00785 } 00786 00787 00788 00802 static Tree iteratePar (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00803 { 00804 assert (num>0); 00805 00806 Tree res = eval(body, visited, pushValueDef(id, tree(num-1), localValEnv)); 00807 for (int i = num-2; i >= 0; i--) { 00808 res = boxPar(eval(body, visited, pushValueDef(id, tree(i), localValEnv)), res); 00809 } 00810 00811 return res; 00812 } 00813 00814 00815 00828 static Tree iterateSeq (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00829 { 00830 assert (num>0); 00831 00832 Tree res = eval(body, visited, pushValueDef(id, tree(num-1), localValEnv)); 00833 for (int i = num-2; i >= 0; i--) { 00834 res = boxSeq(eval(body, visited, pushValueDef(id, tree(i), localValEnv)), res); 00835 } 00836 00837 return res; 00838 } 00839 00840 00841 00855 static Tree iterateSum (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00856 { 00857 assert (num>0); 00858 00859 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv)); 00860 00861 for (int i = 1; i < num; i++) { 00862 res = boxSeq(boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv))),boxPrim2(sigAdd)) ; 00863 } 00864 00865 return res; 00866 } 00867 00868 00869 00883 static Tree iterateProd (Tree id, int num, Tree body, Tree visited, Tree localValEnv) 00884 { 00885 assert (num>0); 00886 00887 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv)); 00888 00889 for (int i = 1; i < num; i++) { 00890 res = boxSeq(boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv))),boxPrim2(sigMul)) ; 00891 } 00892 00893 return res; 00894 } 00895 00904 #if 1 00905 static bool boxlistOutputs(Tree boxlist, int* outputs) 00906 { 00907 int ins, outs; 00908 00909 *outputs = 0; 00910 while (!isNil(boxlist)) 00911 { 00912 Tree b = a2sb(hd(boxlist)); // for getBoxType, suppose list of evaluated boxes 00913 if (getBoxType(b, &ins, &outs)) { 00914 *outputs += outs; 00915 } else { 00916 // arbitrary output arity set to 1 00917 // when can't be determined 00918 *outputs += 1; 00919 } 00920 boxlist = tl(boxlist); 00921 } 00922 return isNil(boxlist); 00923 } 00924 #else 00925 static bool boxlistOutputs(Tree boxlist, int* outputs) 00926 { 00927 int ins, outs; 00928 00929 *outputs = 0; 00930 while (!isNil(boxlist) && getBoxType(hd(boxlist), &ins, &outs)) { 00931 *outputs += outs; 00932 boxlist = tl(boxlist); 00933 } 00934 return isNil(boxlist); 00935 } 00936 #endif 00937 00941 static Tree nwires(int n) 00942 { 00943 Tree l = nil; 00944 while (n--) { l = cons(boxWire(), l); } 00945 return l; 00946 } 00947 00948 00960 static Tree applyList (Tree fun, Tree larg) 00961 { 00962 Tree abstr; 00963 Tree globalDefEnv; 00964 Tree visited; 00965 Tree localValEnv; 00966 Tree envList; 00967 Tree originalRules; 00968 Tree revParamList; 00969 00970 Tree id; 00971 Tree body; 00972 00973 Automaton* automat; 00974 int state; 00975 00976 prim2 p2; 00977 00978 //cerr << "applyList (" << *fun << ", " << *larg << ")" << endl; 00979 00980 if (isNil(larg)) return fun; 00981 00982 if (isBoxError(fun) || isBoxError(larg)) { 00983 return boxError(); 00984 } 00985 00986 if (isBoxPatternMatcher(fun, automat, state, envList, originalRules, revParamList)) { 00987 Tree result; 00988 int state2; 00989 vector<Tree> envVect; 00990 00991 list2vec(envList, envVect); 00992 //cerr << "applyList/apply_pattern_matcher(" << automat << "," << state << "," << *hd(larg) << ")" << endl; 00993 state2 = apply_pattern_matcher(automat, state, hd(larg), result, envVect); 00994 //cerr << "state2 = " << state2 << "; result = " << *result << endl; 00995 if (state2 >= 0 && isNil(result)) { 00996 // we need to continue the pattern matching 00997 return applyList( 00998 boxPatternMatcher(automat, state2, vec2list(envVect), originalRules, cons(hd(larg),revParamList)), 00999 tl(larg) ); 01000 } else if (state2 < 0) { 01001 cerr << "ERROR : pattern matching failed, no rule of " << boxpp(boxCase(originalRules)) 01002 << " matches argument list " << boxpp(reverse(cons(hd(larg), revParamList))) << endl; 01003 exit(1); 01004 } else { 01005 // Pattern Matching was succesful 01006 // the result is a closure that we need to evaluate. 01007 if (isClosure(result, body, globalDefEnv, visited, localValEnv)) { 01008 // why ??? return simplifyPattern(eval(body, nil, localValEnv)); 01009 //return eval(body, nil, localValEnv); 01010 return applyList(eval(body, nil, localValEnv), tl(larg)); 01011 } else { 01012 cerr << "wrong result from pattern matching (not a closure) : " << boxpp(result) << endl; 01013 return boxError(); 01014 } 01015 } 01016 } 01017 if (!isClosure(fun, abstr, globalDefEnv, visited, localValEnv)) { 01018 // principle : f(a,b,c,...) ==> (a,b,c,...):f 01019 int ins, outs; 01020 01021 // check arity of function 01022 Tree efun = a2sb(fun); 01023 //cerr << "TRACEPOINT 1 : " << boxpp(efun) << endl; 01024 if (!getBoxType(efun, &ins, &outs)) { // on laisse comme ca pour le moment 01025 // we can't determine the input arity of the expression 01026 // hope for the best 01027 return boxSeq(larg2par(larg), fun); 01028 } 01029 01030 // check arity of arg list 01031 if (!boxlistOutputs(larg,&outs)) { 01032 // we don't know yet the output arity of larg. Therefore we can't 01033 // do any arity checking nor add _ to reach the required number of arguments 01034 // cerr << "warning : can't infere the type of : " << boxpp(larg) << endl; 01035 return boxSeq(larg2par(larg), fun); 01036 } 01037 01038 if (outs > ins) { 01039 cerr << "too much arguments : " << outs << ", instead of : " << ins << endl; 01040 cerr << "when applying : " << boxpp(fun) << endl 01041 << " to : " << boxpp(larg) << endl; 01042 assert(false); 01043 } 01044 01045 if ( (outs == 1) 01046 && 01047 ( ( isBoxPrim2(fun, &p2) && (p2 != sigPrefix) ) 01048 || ( getUserData(fun) && ((xtended*)getUserData(fun))->isSpecialInfix() ) ) ) { 01049 // special case : /(3) ==> _,3 : / 01050 Tree larg2 = concat(nwires(ins-outs), larg); 01051 return boxSeq(larg2par(larg2), fun); 01052 01053 } else { 01054 01055 Tree larg2 = concat(larg, nwires(ins-outs)); 01056 return boxSeq(larg2par(larg2), fun); 01057 } 01058 } 01059 01060 if (isBoxEnvironment(abstr)) { 01061 evalerrorbox(yyfilename, -1, "an environment can't be used as a function", fun); 01062 exit(1); 01063 } 01064 01065 if (!isBoxAbstr(abstr, id, body)) { 01066 evalerror(yyfilename, -1, "(internal) not an abstraction inside closure", fun); 01067 exit(1); 01068 } 01069 01070 // try to synthetise a name from the function name and the argument name 01071 { 01072 Tree arg = eval(hd(larg), visited, localValEnv); 01073 Tree narg; if ( isBoxNumeric(arg,narg) ) { arg = narg; } 01074 Tree f = eval(body, visited, pushValueDef(id, arg, localValEnv)); 01075 01076 Tree fname; 01077 if (getDefNameProperty(fun, fname)) { 01078 stringstream s; s << tree2str(fname); if (!gSimpleNames) s << "(" << boxpp(arg) << ")"; 01079 setDefNameProperty(f, s.str()); 01080 } 01081 return applyList(f, tl(larg)); 01082 } 01083 } 01084 01085 01086 01098 static Tree revEvalList (Tree lexp, Tree visited, Tree localValEnv) 01099 { 01100 Tree result = nil; 01101 //Tree lexp_orig = lexp; 01102 //cerr << "ENTER revEvalList(" << *lexp_orig << ", env:" << *localValEnv << ")" << endl; 01103 while (!isNil(lexp)) { 01104 result = cons(eval(hd(lexp), visited, localValEnv), result); 01105 lexp = tl(lexp); 01106 } 01107 01108 //cerr << "EXIT revEvalList(" << *lexp_orig << ", env:" << *localValEnv << ") -> " << *result << endl; 01109 return result; 01110 } 01111 01112 01113 01120 static Tree larg2par (Tree larg) 01121 { 01122 if (isNil(larg)) { 01123 evalerror(yyfilename, -1, "empty list of arguments", larg); 01124 exit(1); 01125 } 01126 if (isNil(tl(larg))) { 01127 return hd(larg); 01128 } 01129 return boxPar(hd(larg), larg2par(tl(larg))); 01130 } 01131 01132 01133 01134 01145 static Tree evalIdDef(Tree id, Tree visited, Tree lenv) 01146 { 01147 Tree def, name; 01148 01149 // search the environment env for a definition of symbol id 01150 while (!isNil(lenv) && !getProperty(lenv, id, def)) { 01151 lenv = lenv->branch(0); 01152 } 01153 01154 // check that the definition exists 01155 if (isNil(lenv)) { 01156 cerr << "undefined symbol " << *id << endl; 01157 evalerror(getDefFileProp(id), getDefLineProp(id), "undefined symbol ", id); 01158 exit(1); 01159 } 01160 01161 //cerr << "Id definition is " << *def << endl; 01162 // check that it is not a recursive definition 01163 Tree p = cons(id,lenv); 01164 // set the definition name property 01165 if (!getDefNameProperty(def, name)) { 01166 // if the definition has no name use the identifier 01167 stringstream s; s << boxpp(id); 01168 //XXXXXX setDefNameProperty(def, s.str()); 01169 } 01170 01171 // return the evaluated definition 01172 return eval(def, addElement(p,visited), nil); 01173 } 01174 01175 01183 static Tree listn (int n, Tree e) 01184 { 01185 return (n<= 0) ? nil : cons(e, listn(n-1,e)); 01186 } 01187 01193 static Node PMPROPERTYNODE(symbol("PMPROPERTY")); 01194 01195 static void setPMProperty(Tree t, Tree env, Tree pm) 01196 { 01197 setProperty(t, tree(PMPROPERTYNODE, env), pm); 01198 } 01199 01200 static bool getPMProperty(Tree t, Tree env, Tree& pm) 01201 { 01202 return getProperty(t, tree(PMPROPERTYNODE, env), pm); 01203 } 01204 01214 static Tree evalCase(Tree rules, Tree env) 01215 { 01216 Tree pm; 01217 if (!getPMProperty(rules, env, pm)) { 01218 Automaton* a = make_pattern_matcher(evalRuleList(rules, env)); 01219 pm = boxPatternMatcher(a, 0, listn(len(rules), pushEnvBarrier(env)), rules, nil); 01220 setPMProperty(rules, env, pm); 01221 } 01222 return pm; 01223 } 01224 01225 01229 static Tree evalRuleList(Tree rules, Tree env) 01230 { 01231 //cerr << "evalRuleList "<< *rules << " in " << *env << endl; 01232 if (isNil(rules)) return nil; 01233 else return cons(evalRule(hd(rules), env), evalRuleList(tl(rules), env)); 01234 } 01235 01236 01240 static Tree evalRule(Tree rule, Tree env) 01241 { 01242 //cerr << "evalRule "<< *rule << " in " << *env << endl; 01243 return cons(evalPatternList(left(rule), env), right(rule)); 01244 } 01245 01246 01250 static Tree evalPatternList(Tree patterns, Tree env) 01251 { 01252 if (isNil(patterns)) { 01253 return nil; 01254 } else { 01255 return cons( evalPattern(hd(patterns), env), 01256 evalPatternList(tl(patterns), env) ); 01257 } 01258 } 01259 01260 01265 static Tree evalPattern(Tree pattern, Tree env) 01266 { 01267 Tree p = eval(pattern, nil, env); 01268 return patternSimplification(p); 01269 } 01270 01271 01272 static void list2vec(Tree l, vector<Tree>& v) 01273 { 01274 while (!isNil(l)) { 01275 v.push_back(hd(l)); 01276 l = tl(l); 01277 } 01278 } 01279 01280 01281 static Tree vec2list(const vector<Tree>& v) 01282 { 01283 Tree l = nil; 01284 int n = v.size(); 01285 while (n--) { l = cons(v[n],l); } 01286 return l; 01287 } 01288 01289 01290 01291 01293 // further simplification : replace bloc-diagrams that denote constant number by this number 01295 01296 static property<Tree> SimplifiedBoxProperty; 01297 static Tree numericBoxSimplification(Tree box); 01298 static Tree insideBoxSimplification (Tree box); 01299 01304 Tree boxSimplification (Tree box) 01305 { 01306 Tree simplified; 01307 01308 if (SimplifiedBoxProperty.get(box,simplified)) { 01309 01310 return simplified; 01311 01312 } else { 01313 01314 simplified = numericBoxSimplification(box); 01315 01316 // transferts name property if any 01317 Tree name; if (getDefNameProperty(box, name)) setDefNameProperty(simplified, name); 01318 01319 // attach simplified expression as a property of original box 01320 SimplifiedBoxProperty.set(box,simplified); 01321 01322 return simplified; 01323 } 01324 } 01325 01329 Tree numericBoxSimplification(Tree box) 01330 { 01331 int ins, outs; 01332 Tree result; 01333 int i; 01334 double x; 01335 01336 if ( ! getBoxType(box, &ins, &outs)) { 01337 cout << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", Can't compute the box type of : " << *box << endl; 01338 exit(1); 01339 } 01340 01341 if (ins==0 && outs==1) { 01342 // this box can potentially denote a number 01343 if (isBoxInt(box, &i) || isBoxReal(box, &x)) { 01344 result = box; 01345 } else { 01346 // propagate signals to discover if it simplifies to a number 01347 int i; 01348 double x; 01349 Tree lsignals = boxPropagateSig(nil, box , makeSigInputList(0)); 01350 Tree s = simplify(hd(lsignals)); 01351 01352 if (isSigReal(s, &x)) { 01353 result = boxReal(x); 01354 } else if (isSigInt(s, &i)) { 01355 result = boxInt(i); 01356 } else { 01357 result = insideBoxSimplification(box); 01358 } 01359 } 01360 } else { 01361 // this box can't denote a number 01362 result = insideBoxSimplification(box); 01363 } 01364 return result; 01365 } 01366 01370 Tree insideBoxSimplification (Tree box) 01371 { 01372 int i; 01373 double r; 01374 prim0 p0; 01375 prim1 p1; 01376 prim2 p2; 01377 prim3 p3; 01378 prim4 p4; 01379 prim5 p5; 01380 01381 Tree t1, t2, ff, label, cur, min, max, step, type, name, file, slot, body; 01382 01383 01384 xtended* xt = (xtended*)getUserData(box); 01385 01386 // Extended Primitives 01387 01388 if (xt) { 01389 return box; 01390 } 01391 01392 // Numbers and Constants 01393 01394 else if (isBoxInt(box, &i)) { 01395 return box; 01396 } 01397 else if (isBoxReal(box, &r)) { 01398 return box; 01399 } 01400 01401 else if (isBoxFConst(box, type, name, file)) { 01402 return box; 01403 } 01404 01405 else if (isBoxFVar(box, type, name, file)) { 01406 return box; 01407 } 01408 01409 // Wire and Cut 01410 01411 else if (isBoxCut(box)) { 01412 return box; 01413 } 01414 01415 else if (isBoxWire(box)) { 01416 return box; 01417 } 01418 01419 // Primitives 01420 01421 else if (isBoxPrim0(box, &p0)) { 01422 return box; 01423 } 01424 01425 else if (isBoxPrim1(box, &p1)) { 01426 return box; 01427 } 01428 01429 else if (isBoxPrim2(box, &p2)) { 01430 return box; 01431 } 01432 01433 else if (isBoxPrim3(box, &p3)) { 01434 return box; 01435 } 01436 01437 else if (isBoxPrim4(box, &p4)) { 01438 return box; 01439 } 01440 01441 else if (isBoxPrim5(box, &p5)) { 01442 return box; 01443 } 01444 01445 else if (isBoxFFun(box, ff)) { 01446 return box; 01447 } 01448 01449 // User Interface Widgets 01450 01451 else if (isBoxButton(box, label)) { 01452 return box; 01453 } 01454 01455 else if (isBoxCheckbox(box, label)) { 01456 return box; 01457 } 01458 01459 else if (isBoxVSlider(box, label, cur, min, max, step)) { 01460 return box; 01461 } 01462 01463 else if (isBoxHSlider(box, label, cur, min, max, step)) { 01464 return box; 01465 } 01466 01467 else if (isBoxNumEntry(box, label, cur, min, max, step)) { 01468 return box; 01469 } 01470 01471 else if (isBoxVBargraph(box, label, min, max)) { 01472 return box; 01473 } 01474 01475 else if (isBoxHBargraph(box, label, min, max)) { 01476 return box; 01477 } 01478 01479 // User Interface Groups 01480 01481 else if (isBoxVGroup(box, label, t1)) { 01482 return boxVGroup(label, boxSimplification(t1)); 01483 } 01484 01485 else if (isBoxHGroup(box, label, t1)) { 01486 return boxHGroup(label, boxSimplification(t1)); 01487 } 01488 01489 else if (isBoxTGroup(box, label, t1)) { 01490 return boxTGroup(label, boxSimplification(t1)); 01491 } 01492 01493 // Slots and Symbolic Boxes 01494 01495 else if (isBoxSlot(box)) { 01496 return box;; 01497 } 01498 01499 else if (isBoxSymbolic(box, slot, body)){ 01500 01501 Tree b = boxSimplification(body); 01502 return boxSymbolic(slot,b); 01503 } 01504 01505 // Block Diagram Composition Algebra 01506 01507 else if (isBoxSeq(box, t1, t2)) { 01508 Tree s1 = boxSimplification(t1); 01509 Tree s2 = boxSimplification(t2); 01510 return boxSeq(s1,s2); 01511 } 01512 01513 else if (isBoxPar(box, t1, t2)) { 01514 Tree s1 = boxSimplification(t1); 01515 Tree s2 = boxSimplification(t2); 01516 return boxPar(s1,s2); 01517 } 01518 01519 else if (isBoxSplit(box, t1, t2)) { 01520 Tree s1 = boxSimplification(t1); 01521 Tree s2 = boxSimplification(t2); 01522 return boxSplit(s1,s2); 01523 } 01524 01525 else if (isBoxMerge(box, t1, t2)) { 01526 Tree s1 = boxSimplification(t1); 01527 Tree s2 = boxSimplification(t2); 01528 return boxMerge(s1,s2); 01529 } 01530 else if (isBoxRec(box, t1, t2)) { 01531 Tree s1 = boxSimplification(t1); 01532 Tree s2 = boxSimplification(t2); 01533 return boxRec(s1,s2); 01534 } 01535 01536 cout << "ERROR in file " << __FILE__ << ':' << __LINE__ << ", unrecognised box expression : " << *box << endl; 01537 exit(1); 01538 return 0; 01539 }
1.7.5.1