00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00045
00046 #include <assert.h>
00047 extern SourceReader gReader;
00048 extern int gMaxNameSize;
00049 extern bool gPatternEvalMode;
00050 extern bool gSimpleNames;
00051 extern bool gSimplifyDiagrams;
00052
00053
00054
00055
00056
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 pushMultiClosureDefs(Tree ldefs, Tree visited, Tree lenv);
00072 static Tree evalIdDef(Tree id, Tree visited, Tree env);
00073
00074
00075
00076 static Tree evalCase(Tree rules, Tree env);
00077 static Tree evalRuleList(Tree rules, Tree env);
00078 static Tree evalRule(Tree rule, Tree env);
00079 static Tree evalPatternList(Tree patterns, Tree env);
00080 static Tree evalPattern(Tree pattern, Tree env);
00081
00082 static Tree patternSimplification (Tree pattern);
00083 static bool isBoxNumeric (Tree in, Tree& out);
00084 static Tree replaceBoxNumeric (Tree exp);
00085
00086
00087 static Tree vec2list(const vector<Tree>& v);
00088 static void list2vec(Tree l, vector<Tree>& v);
00089 static Tree listn (int n, Tree e);
00090
00091
00092
00093
00094
00102 Tree evalprocess (Tree eqlist)
00103 {
00104 return a2sb(eval(boxIdent("process"), nil, pushMultiClosureDefs(eqlist, nil, nil)));
00105 }
00106
00107
00108
00109
00110 Tree evaldocexpr (Tree docexpr, Tree eqlist)
00111 {
00112 return a2sb(eval(docexpr, nil, pushMultiClosureDefs(eqlist, nil, nil)));
00113 }
00114
00115
00116
00117
00118
00119
00127 property<Tree> gSymbolicBoxProperty;
00128
00129 static Tree real_a2sb(Tree exp);
00130
00131 static Tree a2sb(Tree exp)
00132 {
00133 Tree result;
00134 Tree id;
00135
00136 if (gSymbolicBoxProperty.get(exp, result)) {
00137 return result;
00138 }
00139
00140 result = real_a2sb(exp);
00141 if (result != exp && getDefNameProperty(exp, id)) {
00142 setDefNameProperty(result, id);
00143 }
00144 gSymbolicBoxProperty.set(exp, result);
00145 return result;
00146 }
00147
00148 static int gBoxSlotNumber = 0;
00149
00150 static Tree real_a2sb(Tree exp)
00151 {
00152 Tree abstr, visited, unusedEnv, localValEnv, var, name, body;
00153
00154 if (isClosure(exp, abstr, unusedEnv, visited, localValEnv)) {
00155
00156 if (isBoxIdent(abstr)) {
00157
00158 Tree result = a2sb(eval(abstr, visited, localValEnv));
00159
00160
00161 if (getDefNameProperty(exp, name)) setDefNameProperty(result, name);
00162 return result;
00163
00164 } else if (isBoxAbstr(abstr, var, body)) {
00165
00166
00167
00168 Tree slot = boxSlot(++gBoxSlotNumber);
00169 stringstream s; s << boxpp(var);
00170 setDefNameProperty(slot, s.str() );
00171
00172
00173 Tree result = boxSymbolic(slot, a2sb(eval(body, visited, pushValueDef(var, slot, localValEnv))));
00174
00175
00176 if (getDefNameProperty(exp, name)) setDefNameProperty(result, name);
00177 return result;
00178
00179 } else if (isBoxEnvironment(abstr)) {
00180 return abstr;
00181
00182 } else {
00183 evalerror(yyfilename, -1, " a2sb : internal error : not an abstraction inside closure ", exp);
00184 exit(1);
00185 }
00186
00187 } else if (isBoxPatternMatcher(exp)) {
00188
00189
00190
00191 Tree slot = boxSlot(++gBoxSlotNumber);
00192 stringstream s; s << "PM" << gBoxSlotNumber;
00193 setDefNameProperty(slot, s.str() );
00194
00195
00196 Tree result = boxSymbolic(slot, a2sb(applyList(exp, cons(slot,nil))));
00197
00198
00199 if (getDefNameProperty(exp, name)) setDefNameProperty(result, name);
00200 return result;
00201
00202 } else {
00203
00204 unsigned int ar = exp->arity();
00205 tvec B(ar);
00206 bool modified = false;
00207 for (unsigned int i = 0; i < ar; i++) {
00208 Tree b = exp->branch(i);
00209 Tree m = a2sb(b);
00210 B[i] = m;
00211 if (b != m) modified=true;
00212 }
00213 Tree r = (modified) ? CTree::make(exp->node(), B) : exp;
00214 if (gSimplifyDiagrams) {
00215 return replaceBoxNumeric(r);
00216 } else {
00217 return r;
00218 }
00219
00220
00221
00222 }
00223 }
00224
00225 static bool autoName(Tree exp , Tree& id)
00226 {
00227 stringstream s; s << boxpp(exp);
00228 id = tree(s.str().c_str());
00229 return true;
00230 }
00231
00232 bool getArgName(Tree t, Tree& id)
00233 {
00234
00235 return autoName(t, id) ;
00236 }
00237
00238
00239
00249 static loopDetector LD(1024, 1);
00250
00251
00252 static Node EVALPROPERTY(symbol("EvalProperty"));
00253
00259 void setEvalProperty(Tree box, Tree env, Tree value)
00260 {
00261
00262 setProperty(box, tree(EVALPROPERTY,env), value);
00263 }
00264
00265
00273 bool getEvalProperty(Tree box, Tree env, Tree& value)
00274 {
00275 return getProperty(box, tree(EVALPROPERTY,env), value);
00276 }
00277
00278
00279 static Tree eval (Tree exp, Tree visited, Tree localValEnv)
00280 {
00281 Tree id;
00282 Tree result;
00283
00284 LD.detect(cons(exp,localValEnv));
00285
00286 if (!getEvalProperty(exp, localValEnv, result)) {
00287 result = realeval(exp, visited, localValEnv);
00288 setEvalProperty(exp, localValEnv, result);
00289
00290
00291
00292 if (getDefNameProperty(exp, id)) {
00293 setDefNameProperty(result, id);
00294 }
00295 }
00296 return result;
00297 }
00298
00309 static Tree realeval (Tree exp, Tree visited, Tree localValEnv)
00310 {
00311
00312 Tree fun;
00313 Tree arg;
00314 Tree var, num, body, ldef;
00315 Tree label;
00316 Tree cur, lo, hi, step;
00317 Tree e1, e2, exp2, notused, visited2, lenv2;
00318 Tree rules;
00319 Tree id;
00320
00321
00322
00323
00324 xtended* xt = (xtended*) getUserData(exp);
00325
00326
00327
00328
00329
00330 if ( xt ||
00331 isBoxInt(exp) || isBoxReal(exp) ||
00332 isBoxWire(exp) || isBoxCut(exp) ||
00333 isBoxPrim0(exp) || isBoxPrim1(exp) ||
00334 isBoxPrim2(exp) || isBoxPrim3(exp) ||
00335 isBoxPrim4(exp) || isBoxPrim5(exp) ||
00336 isBoxFFun(exp) || isBoxFConst(exp) || isBoxFVar(exp) ) {
00337 return exp;
00338
00339
00340
00341
00342 } else if ( isBoxSeq(exp, e1, e2) ) {
00343 return boxSeq(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));
00344
00345 } else if ( isBoxPar(exp, e1, e2) ) {
00346 return boxPar(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));
00347
00348 } else if ( isBoxRec(exp, e1, e2) ) {
00349 return boxRec(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));
00350
00351 } else if ( isBoxSplit(exp, e1, e2) ) {
00352 return boxSplit(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));
00353
00354 } else if ( isBoxMerge(exp, e1, e2) ) {
00355 return boxMerge(eval(e1, visited, localValEnv), eval(e2, visited, localValEnv));
00356
00357
00358
00359
00360 } else if (isBoxAccess(exp, body, var)) {
00361 Tree val = eval(body, visited, localValEnv);
00362 if (isClosure(val, exp2, notused, visited2, lenv2)) {
00363
00364 return eval(closure(var,notused,visited2,lenv2), visited, localValEnv);
00365 } else {
00366 evalerror(getDefFileProp(exp), getDefLineProp(exp), "No environment to access ", exp);
00367 exit(1);
00368 }
00369
00370 } else if (isBoxComponent(exp, label)) {
00371 string fname = tree2str(label);
00372 Tree eqlst = gReader.expandlist(gReader.getlist(fname));
00373 Tree res = closure(boxIdent("process"), nil, nil, pushMultiClosureDefs(eqlst, nil, nil));
00374 setDefNameProperty(res, label);
00375
00376 return res;
00377
00378 } else if (isBoxLibrary(exp, label)) {
00379 string fname = tree2str(label);
00380 Tree eqlst = gReader.expandlist(gReader.getlist(fname));
00381 Tree res = closure(boxEnvironment(), nil, nil, pushMultiClosureDefs(eqlst, nil, nil));
00382 setDefNameProperty(res, label);
00383
00384 return res;
00385
00386
00387
00388
00389
00390 } else if (isBoxButton(exp, label)) {
00391 const char* l1 = tree2str(label);
00392 const char* l2= evalLabel(l1, visited, localValEnv);
00393
00394 return ((l1 == l2) ? exp : boxButton(tree(l2)));
00395
00396 } else if (isBoxCheckbox(exp, label)) {
00397 const char* l1 = tree2str(label);
00398 const char* l2= evalLabel(l1, visited, localValEnv);
00399
00400 return ((l1 == l2) ? exp : boxCheckbox(tree(l2)));
00401
00402 } else if (isBoxVSlider(exp, label, cur, lo, hi, step)) {
00403 const char* l1 = tree2str(label);
00404 const char* l2= evalLabel(l1, visited, localValEnv);
00405 return ( boxVSlider(tree(l2),
00406 tree(eval2double(cur, visited, localValEnv)),
00407 tree(eval2double(lo, visited, localValEnv)),
00408 tree(eval2double(hi, visited, localValEnv)),
00409 tree(eval2double(step, visited, localValEnv))));
00410
00411 } else if (isBoxHSlider(exp, label, cur, lo, hi, step)) {
00412 const char* l1 = tree2str(label);
00413 const char* l2= evalLabel(l1, visited, localValEnv);
00414 return ( boxHSlider(tree(l2),
00415 tree(eval2double(cur, visited, localValEnv)),
00416 tree(eval2double(lo, visited, localValEnv)),
00417 tree(eval2double(hi, visited, localValEnv)),
00418 tree(eval2double(step, visited, localValEnv))));
00419
00420 } else if (isBoxNumEntry(exp, label, cur, lo, hi, step)) {
00421 const char* l1 = tree2str(label);
00422 const char* l2= evalLabel(l1, visited, localValEnv);
00423 return (boxNumEntry(tree(l2),
00424 tree(eval2double(cur, visited, localValEnv)),
00425 tree(eval2double(lo, visited, localValEnv)),
00426 tree(eval2double(hi, visited, localValEnv)),
00427 tree(eval2double(step, visited, localValEnv))));
00428
00429 } else if (isBoxVGroup(exp, label, arg)) {
00430 const char* l1 = tree2str(label);
00431 const char* l2= evalLabel(l1, visited, localValEnv);
00432 return boxVGroup(tree(l2), eval(arg, visited, localValEnv) );
00433
00434 } else if (isBoxHGroup(exp, label, arg)) {
00435 const char* l1 = tree2str(label);
00436 const char* l2= evalLabel(l1, visited, localValEnv);
00437 return boxHGroup(tree(l2), eval(arg, visited, localValEnv) );
00438
00439 } else if (isBoxTGroup(exp, label, arg)) {
00440 const char* l1 = tree2str(label);
00441 const char* l2= evalLabel(l1, visited, localValEnv);
00442 return boxTGroup(tree(l2), eval(arg, visited, localValEnv) );
00443
00444 } else if (isBoxHBargraph(exp, label, lo, hi)) {
00445 const char* l1 = tree2str(label);
00446 const char* l2= evalLabel(l1, visited, localValEnv);
00447 return boxHBargraph(tree(l2),
00448 tree(eval2double(lo, visited, localValEnv)),
00449 tree(eval2double(hi, visited, localValEnv)));
00450
00451 } else if (isBoxVBargraph(exp, label, lo, hi)) {
00452 const char* l1 = tree2str(label);
00453 const char* l2= evalLabel(l1, visited, localValEnv);
00454 return boxVBargraph(tree(l2),
00455 tree(eval2double(lo, visited, localValEnv)),
00456 tree(eval2double(hi, visited, localValEnv)));
00457
00458
00459
00460
00461 } else if (isBoxIdent(exp)) {
00462 return evalIdDef(exp, visited, localValEnv);
00463
00464 } else if (isBoxWithLocalDef(exp, body, ldef)) {
00465 return eval(body, visited, pushMultiClosureDefs(ldef, visited, localValEnv));
00466
00467 } else if (isBoxAppl(exp, fun, arg)) {
00468 return applyList( eval(fun, visited, localValEnv),
00469 revEvalList(arg, visited, localValEnv) );
00470
00471 } else if (isBoxAbstr(exp)) {
00472
00473 return closure(exp, nil, visited, localValEnv);
00474
00475 } else if (isBoxEnvironment(exp)) {
00476
00477 return closure(exp, nil, visited, localValEnv);
00478
00479 } else if (isClosure(exp, exp2, notused, visited2, lenv2)) {
00480
00481 if (isBoxAbstr(exp2)) {
00482
00483 return closure(exp2, nil, setUnion(visited,visited2), lenv2);
00484 } else if (isBoxEnvironment(exp2)) {
00485
00486 return closure(exp2, nil, setUnion(visited,visited2), lenv2);
00487 } else {
00488
00489 return eval(exp2, setUnion(visited,visited2), lenv2);
00490 }
00491
00492
00493
00494
00495 } else if (isBoxIPar(exp, var, num, body)) {
00496 int n = eval2int(num, visited, localValEnv);
00497 return iteratePar(var, n, body, visited, localValEnv);
00498
00499 } else if (isBoxISeq(exp, var, num, body)) {
00500 int n = eval2int(num, visited, localValEnv);
00501 return iterateSeq(var, n, body, visited, localValEnv);
00502
00503 } else if (isBoxISum(exp, var, num, body)) {
00504 int n = eval2int(num, visited, localValEnv);
00505 return iterateSum(var, n, body, visited, localValEnv);
00506
00507 } else if (isBoxIProd(exp, var, num, body)) {
00508 int n = eval2int(num, visited, localValEnv);
00509 return iterateProd(var, n, body, visited, localValEnv);
00510
00511 } else if (isBoxSlot(exp)) {
00512 return exp;
00513
00514 } else if (isBoxSymbolic(exp)) {
00515
00516 return exp;
00517
00518
00519
00520
00521
00522 } else if (isBoxCase(exp, rules)) {
00523 return evalCase(rules, localValEnv);
00524
00525 } else if (isBoxPatternVar(exp, id)) {
00526 return exp;
00527
00528
00529 } else if (isBoxPatternMatcher(exp)) {
00530 return exp;
00531
00532 } else {
00533 cerr << "ERROR : EVAL don't intercept : " << *exp << endl;
00534 assert(false);
00535 }
00536 }
00537
00538
00539
00540 static inline bool isBoxPatternOp(Tree box, Node& n, Tree& t1, Tree& t2)
00541 {
00542 if ( isBoxPar(box, t1, t2) ||
00543 isBoxSeq(box, t1, t2) ||
00544 isBoxSplit(box, t1, t2) ||
00545 isBoxMerge(box, t1, t2) ||
00546 isBoxRec(box, t1, t2) )
00547 {
00548 n = box->node();
00549 return true;
00550 } else {
00551 return false;
00552 }
00553 }
00554
00555
00556 Tree NUMERICPROPERTY = tree(symbol("NUMERICPROPERTY"));
00557
00558 void setNumericProperty(Tree t, Tree num)
00559 {
00560 setProperty(t, NUMERICPROPERTY, num);
00561 }
00562
00563 bool getNumericProperty(Tree t, Tree& num)
00564 {
00565 return getProperty(t, NUMERICPROPERTY, num);
00566 }
00567
00568
00569 static Tree replaceBoxNumeric (Tree exp)
00570 {
00571 int numInputs, numOutputs;
00572 double x;
00573 int i;
00574 Tree out;
00575
00576 if (isBoxInt(exp, &i) || isBoxReal(exp, &x)) {
00577 return exp;
00578 } else if (getNumericProperty(exp, out)) {
00579 return out;
00580 } else {
00581 if ( getBoxType(exp, &numInputs, &numOutputs) && (numInputs == 0) && (numOutputs == 1) ) {
00582
00583 Tree lsignals = boxPropagateSig(nil, exp , makeSigInputList(numInputs) );
00584 assert(isList(lsignals));
00585 Tree res = simplify(hd(lsignals));
00586 if (isSigReal(res, &x)) out = boxReal(x);
00587 else if (isSigInt(res, &i)) out = boxInt(i);
00588 else out = exp;
00589 } else {
00590 out = exp;
00591 }
00592 setNumericProperty(exp,out);
00593 return out;
00594 }
00595 }
00596
00603
00604
00605 Tree simplifyPattern (Tree value)
00606 {
00607 Tree num;
00608 if (!getNumericProperty(value,num)) {
00609 if (!isBoxNumeric(value,num)) {
00610 num = value;
00611 }
00612 setNumericProperty(value,num);
00613 }
00614 return num;
00615 }
00616
00617
00618 static bool isBoxNumeric (Tree in, Tree& out)
00619 {
00620 int numInputs, numOutputs;
00621 double x;
00622 int i;
00623 Tree v;
00624
00625 if (isBoxInt(in, &i) || isBoxReal(in, &x)) {
00626 out = in;
00627 return true;
00628 } else {
00629 v = a2sb(in);
00630 if ( getBoxType(v, &numInputs, &numOutputs) && (numInputs == 0) && (numOutputs == 1) ) {
00631
00632 Tree lsignals = boxPropagateSig(nil, v , makeSigInputList(numInputs) );
00633 Tree res = simplify(hd(lsignals));
00634 if (isSigReal(res, &x)) {
00635 out = boxReal(x);
00636 return true;
00637 }
00638 if (isSigInt(res, &i)) {
00639 out = boxInt(i);
00640 return true;
00641 }
00642 }
00643 return false;
00644 }
00645 }
00646
00647 static Tree patternSimplification (Tree pattern)
00648 {
00649
00650 Node n(0);
00651 Tree v, t1, t2;
00652
00653 if (isBoxNumeric(pattern, v)) {
00654 return v;
00655 } else if (isBoxPatternOp(pattern, n, t1, t2)) {
00656 return tree(n, patternSimplification(t1), patternSimplification(t2));
00657 } else {
00658 return pattern;
00659 }
00660 }
00661
00662
00663
00677 static double eval2double (Tree exp, Tree visited, Tree localValEnv)
00678 {
00679 Tree diagram = eval(exp, visited, localValEnv);
00680 int numInputs, numOutputs;
00681 getBoxType(diagram, &numInputs, &numOutputs);
00682 if ( (numInputs > 0) || (numOutputs != 1) ) {
00683 evalerror (yyfilename, yylineno, "not a constant expression of type : (0->1)", exp);
00684 return 1;
00685 } else {
00686 Tree lsignals = boxPropagateSig(nil, diagram , makeSigInputList(numInputs) );
00687 Tree val = simplify(hd(lsignals));
00688 return tree2float(val);
00689 }
00690 }
00691
00692
00706 static int eval2int (Tree exp, Tree visited, Tree localValEnv)
00707 {
00708 Tree diagram = eval(exp, visited, localValEnv);
00709 int numInputs, numOutputs;
00710 getBoxType(diagram, &numInputs, &numOutputs);
00711 if ( (numInputs > 0) || (numOutputs != 1) ) {
00712 evalerror (yyfilename, yylineno, "not a constant expression of type : (0->1)", exp);
00713 return 1;
00714 } else {
00715 Tree lsignals = boxPropagateSig(nil, diagram , makeSigInputList(numInputs) );
00716 Tree val = simplify(hd(lsignals));
00717 return tree2int(val);
00718 }
00719 }
00720
00721 static bool isDigitChar(char c)
00722 {
00723 return (c >= '0') & (c <= '9');
00724 }
00725
00726 static bool isIdentChar(char c)
00727 {
00728 return ((c >= 'a') & (c <= 'z')) || ((c >= 'A') & (c <= 'Z')) || ((c >= '0') & (c <= '9')) || (c == '_');
00729 }
00730
00731 const char* Formats [] = {"%d", "%1d", "%2d", "%3d", "%4d"};
00732
00733 static char* writeIdentValue(char* dst, int format, const char* ident, Tree visited, Tree localValEnv)
00734 {
00735 int n = eval2int(boxIdent(ident), visited, localValEnv);
00736 int i = min(4,max(format,0));
00737
00738 return dst + sprintf(dst, Formats[i], n);
00739 }
00740
00741 static const char * evalLabel (const char* label, Tree visited, Tree localValEnv)
00742 {
00743 char res[2000];
00744 char ident[64];
00745
00746 const char* src = &label[0];
00747 char* dst = &res[0];
00748 char* id = &ident[0];
00749
00750 bool parametric = false;
00751 int state = 0; int format = 0;
00752 char c;
00753
00754 while ((c=*src++)) {
00755 if (state == 0) {
00756
00757 if (c == '%') {
00758
00759 if (*src == '%') {
00760 *dst++ = *src++;
00761 } else {
00762 state = 1;
00763 format = 0;
00764 parametric = true;
00765 id = &ident[0];
00766 }
00767 } else {
00768 *dst++ = c;
00769 }
00770 } else if (state == 1) {
00771
00772 if (isDigitChar(c)) {
00773 format = format*10 + (c-'0');
00774 } else {
00775 state = 2;
00776 --src;
00777 }
00778
00779 } else {
00780
00781
00782 if (isIdentChar(c)) {
00783 *id++ = c;
00784 } else {
00785 *id = 0;
00786 dst = writeIdentValue(dst, format, ident, visited, localValEnv);
00787 state = 0;
00788 src -= 1;
00789 }
00790 }
00791 }
00792
00793 if (state == 2) {
00794 *id = 0;
00795 dst = writeIdentValue(dst, format, ident, visited, localValEnv);
00796 }
00797 *dst = 0;
00798 return (parametric) ? strdup(res) : label;
00799 }
00800
00801
00802
00816 static Tree iteratePar (Tree id, int num, Tree body, Tree visited, Tree localValEnv)
00817 {
00818 assert (num>0);
00819
00820 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv));
00821 for (int i = 1; i < num; i++) {
00822 res = boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv)));
00823 }
00824
00825 return res;
00826 }
00827
00828
00829
00842 static Tree iterateSeq (Tree id, int num, Tree body, Tree visited, Tree localValEnv)
00843 {
00844 assert (num>0);
00845
00846 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv));
00847
00848 for (int i = 1; i < num; i++) {
00849 res = boxSeq(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv)));
00850 }
00851
00852 return res;
00853 }
00854
00855
00856
00870 static Tree iterateSum (Tree id, int num, Tree body, Tree visited, Tree localValEnv)
00871 {
00872 assert (num>0);
00873
00874 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv));
00875
00876 for (int i = 1; i < num; i++) {
00877 res = boxSeq(boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv))),boxPrim2(sigAdd)) ;
00878 }
00879
00880 return res;
00881 }
00882
00883
00884
00898 static Tree iterateProd (Tree id, int num, Tree body, Tree visited, Tree localValEnv)
00899 {
00900 assert (num>0);
00901
00902 Tree res = eval(body, visited, pushValueDef(id, tree(0), localValEnv));
00903
00904 for (int i = 1; i < num; i++) {
00905 res = boxSeq(boxPar(res, eval(body, visited, pushValueDef(id, tree(i), localValEnv))),boxPrim2(sigMul)) ;
00906 }
00907
00908 return res;
00909 }
00910
00919 #if 1
00920 static bool boxlistOutputs(Tree boxlist, int* outputs)
00921 {
00922 int ins, outs;
00923
00924 *outputs = 0;
00925 while (!isNil(boxlist))
00926 {
00927 if (getBoxType(hd(boxlist), &ins, &outs)) {
00928 *outputs += outs;
00929 } else {
00930
00931
00932 *outputs += 1;
00933 }
00934 boxlist = tl(boxlist);
00935 }
00936 return isNil(boxlist);
00937 }
00938 #else
00939 static bool boxlistOutputs(Tree boxlist, int* outputs)
00940 {
00941 int ins, outs;
00942
00943 *outputs = 0;
00944 while (!isNil(boxlist) && getBoxType(hd(boxlist), &ins, &outs)) {
00945 *outputs += outs;
00946 boxlist = tl(boxlist);
00947 }
00948 return isNil(boxlist);
00949 }
00950 #endif
00951
00955 static Tree nwires(int n)
00956 {
00957 Tree l = nil;
00958 while (n--) { l = cons(boxWire(), l); }
00959 return l;
00960 }
00961
00962
00974 static Tree applyList (Tree fun, Tree larg)
00975 {
00976 Tree abstr;
00977 Tree globalDefEnv;
00978 Tree visited;
00979 Tree localValEnv;
00980 Tree envList;
00981 Tree originalRules;
00982 Tree revParamList;
00983
00984 Tree id;
00985 Tree body;
00986
00987 Automaton* automat;
00988 int state;
00989
00990 prim2 p2;
00991
00992 if (isNil(larg)) return fun;
00993
00994 if (isBoxError(fun) || isBoxError(larg)) {
00995 return boxError();
00996 }
00997
00998 if (isBoxPatternMatcher(fun, automat, state, envList, originalRules, revParamList)) {
00999 Tree result;
01000 int state2;
01001 vector<Tree> envVect;
01002
01003 list2vec(envList, envVect);
01004 state2 = apply_pattern_matcher(automat, state, hd(larg), result, envVect);
01005 if (state2 >= 0 && isNil(result)) {
01006
01007 return applyList(
01008 boxPatternMatcher(automat, state2, vec2list(envVect), originalRules, cons(hd(larg),revParamList)),
01009 tl(larg) );
01010 } else if (state2 < 0) {
01011 cerr << "ERROR : pattern matching failed, no rule of " << boxpp(boxCase(originalRules))
01012 << " matches argument list " << boxpp(reverse(cons(hd(larg), revParamList))) << endl;
01013 exit(1);
01014 } else {
01015
01016
01017 if (isClosure(result, body, globalDefEnv, visited, localValEnv)) {
01018
01019
01020 return applyList(eval(body, nil, localValEnv), tl(larg));
01021 } else {
01022 cerr << "wrong result from pattern matching (not a closure) : " << boxpp(result) << endl;
01023 return boxError();
01024 }
01025 }
01026 }
01027 if (!isClosure(fun, abstr, globalDefEnv, visited, localValEnv)) {
01028
01029 int ins, outs;
01030
01031
01032 if (!getBoxType(fun, &ins, &outs)) {
01033
01034
01035 return boxSeq(larg2par(larg), fun);
01036 }
01037
01038
01039 if (!boxlistOutputs(larg,&outs)) {
01040
01041
01042
01043 return boxSeq(larg2par(larg), fun);
01044 }
01045
01046 if (outs > ins) {
01047 cerr << "too much arguments : " << outs << ", instead of : " << ins << endl;
01048 cerr << "when applying : " << boxpp(fun) << endl
01049 << " to : " << boxpp(larg) << endl;
01050 assert(false);
01051 }
01052
01053 if ( (outs == 1) && isBoxPrim2(fun, &p2) && (p2 != sigPrefix)) {
01054
01055 Tree larg2 = concat(nwires(ins-outs), larg);
01056 return boxSeq(larg2par(larg2), fun);
01057 } else {
01058 Tree larg2 = concat(larg, nwires(ins-outs));
01059 return boxSeq(larg2par(larg2), fun);
01060 }
01061 }
01062
01063 if (isBoxEnvironment(abstr)) {
01064 evalerrorbox(yyfilename, -1, "an environment can't be used as a function", fun);
01065 exit(1);
01066 }
01067
01068 if (!isBoxAbstr(abstr, id, body)) {
01069 evalerror(yyfilename, -1, "(internal) not an abstraction inside closure", fun);
01070 exit(1);
01071 }
01072
01073
01074 {
01075 Tree arg = eval(hd(larg), visited, localValEnv);
01076 Tree narg; if ( isBoxNumeric(arg,narg) ) { arg = narg; }
01077 Tree f = eval(body, visited, pushValueDef(id, arg, localValEnv));
01078
01079 Tree fname;
01080 if (getDefNameProperty(fun, fname)) {
01081 stringstream s; s << tree2str(fname); if (!gSimpleNames) s << "(" << boxpp(arg) << ")";
01082 setDefNameProperty(f, s.str());
01083 }
01084 return applyList(f, tl(larg));
01085 }
01086 }
01087
01088
01089
01101 static Tree revEvalList (Tree lexp, Tree visited, Tree localValEnv)
01102 {
01103 Tree result = nil;
01104 while (!isNil(lexp)) {
01105 result = cons(eval(hd(lexp), visited, localValEnv), result);
01106 lexp = tl(lexp);
01107 }
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
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01151 static Tree pushNewLayer(Tree lenv)
01152 {
01153 return tree(unique("ENV_LAYER"), lenv);
01154 }
01155
01156
01164 static void addLayerDef(Tree id, Tree def, Tree lenv)
01165 {
01166
01167 Tree olddef;
01168 if (getProperty(lenv, id, olddef)) {
01169 if (def == olddef) {
01170 evalwarning(getDefFileProp(id), getDefLineProp(id), "equivalent re-definitions of", id);
01171 } else {
01172 fprintf(stderr, "%s:%d: ERROR: redefinition of symbols are not allowed : ", getDefFileProp(id), getDefLineProp(id));
01173 print(id,stderr);
01174 fprintf(stderr, " is already defined in file \"%s\" line %d \n", getDefFileProp(id), getDefLineProp(id));
01175 gErrorCount++;
01176 }
01177 }
01178 setProperty(lenv, id, def);
01179 }
01180
01181
01189 Tree pushValueDef(Tree id, Tree def, Tree lenv)
01190 {
01191 Tree lenv2 = pushNewLayer(lenv);
01192 addLayerDef(id, def, lenv2);
01193 return lenv2;
01194 }
01195
01196
01204 static Tree pushMultiClosureDefs(Tree ldefs, Tree visited, Tree lenv)
01205 {
01206 Tree lenv2 = pushNewLayer(lenv);
01207 while (!isNil(ldefs)) {
01208 Tree def = hd(ldefs);
01209 Tree id = hd(def);
01210 Tree rhs= tl(def);
01211 Tree cl = closure(tl(def),nil,visited,lenv2);
01212 stringstream s; s << boxpp(id);
01213 if (!isBoxCase(rhs)) setDefNameProperty(cl,s.str());
01214 addLayerDef( id, cl, lenv2 );
01215 ldefs = tl(ldefs);
01216 }
01217 return lenv2;
01218 }
01219
01220
01229 bool searchIdDef(Tree id, Tree& def, Tree lenv)
01230 {
01231
01232
01233 while (!isNil(lenv) && !getProperty(lenv, id, def)) {
01234 lenv = lenv->branch(0);
01235 }
01236 return !isNil(lenv);
01237 }
01238
01239
01240
01251 static Tree evalIdDef(Tree id, Tree visited, Tree lenv)
01252 {
01253 Tree def, name;
01254
01255
01256 while (!isNil(lenv) && !getProperty(lenv, id, def)) {
01257 lenv = lenv->branch(0);
01258 }
01259
01260
01261 if (isNil(lenv)) {
01262 if (gPatternEvalMode) return boxPatternVar(id);
01263 cerr << "undefined symbol " << *id << endl;
01264 evalerror(getDefFileProp(id), getDefLineProp(id), "undefined symbol ", id);
01265 exit(1);
01266
01267 }
01268
01269
01270 Tree p = cons(id,lenv);
01271
01272 if (!getDefNameProperty(def, name)) {
01273
01274 stringstream s; s << boxpp(id);
01275
01276 }
01277
01278
01279 return eval(def, addElement(p,visited), nil);
01280 }
01281
01282
01290 static Tree listn (int n, Tree e)
01291 {
01292 return (n<= 0) ? nil : cons(e, listn(n-1,e));
01293 }
01294
01300 static Node PMPROPERTYNODE(symbol("PMPROPERTY"));
01301
01302 static void setPMProperty(Tree t, Tree env, Tree pm)
01303 {
01304 setProperty(t, tree(PMPROPERTYNODE, env), pm);
01305 }
01306
01307 static bool getPMProperty(Tree t, Tree env, Tree& pm)
01308 {
01309 return getProperty(t, tree(PMPROPERTYNODE, env), pm);
01310 }
01311
01321 static Tree evalCase(Tree rules, Tree env)
01322 {
01323 Tree pm;
01324 if (!getPMProperty(rules, env, pm)) {
01325 Automaton* a = make_pattern_matcher(evalRuleList(rules, env));
01326 pm = boxPatternMatcher(a, 0, listn(len(rules), env), rules, nil);
01327 setPMProperty(rules, env, pm);
01328 }
01329 return pm;
01330 }
01331
01332
01336 static Tree evalRuleList(Tree rules, Tree env)
01337 {
01338 if (isNil(rules)) return nil;
01339 else return cons(evalRule(hd(rules), env), evalRuleList(tl(rules), env));
01340 }
01341
01342
01346 static Tree evalRule(Tree rule, Tree env)
01347 {
01348 return cons(evalPatternList(left(rule), env), right(rule));
01349 }
01350
01351
01355 static Tree evalPatternList(Tree patterns, Tree env)
01356 {
01357 if (isNil(patterns)) {
01358 return nil;
01359 } else {
01360 return cons( evalPattern(hd(patterns), env),
01361 evalPatternList(tl(patterns), env) );
01362 }
01363 }
01364
01365
01370 static Tree evalPattern(Tree pattern, Tree env)
01371 {
01372 bool saveMode = gPatternEvalMode;
01373 gPatternEvalMode = true;
01374 Tree p = eval(pattern, nil, env);
01375 gPatternEvalMode = saveMode;
01376 return patternSimplification(p);
01377 }
01378
01379
01380 static void list2vec(Tree l, vector<Tree>& v)
01381 {
01382 while (!isNil(l)) {
01383 v.push_back(hd(l));
01384 l = tl(l);
01385 }
01386 }
01387
01388
01389 static Tree vec2list(const vector<Tree>& v)
01390 {
01391 Tree l = nil;
01392 int n = v.size();
01393 while (n--) { l = cons(v[n],l); }
01394 return l;
01395 }