Differences From Artifact [56f0a662740b0906]:
- File        
polemy/eval.d
- 2010-11-26 05:29:24 - part of checkin [f8684f4d69] on branch trunk - changed the desugaring of >>@macro x=e from >>@macro x=e in x to >>@macro x=e in "(macro definition)" for convenience during REPL interaction (user: kinaba) [annotate]
 
 
To Artifact [1c0a1caee00496c7]:
- File        
polemy/eval.d
- 2010-11-26 06:46:09 - part of checkin [552d43f567] on branch trunk - one-by-one M&E memoizer (user: kinaba) [annotate]
 
 
     9      9   import polemy.failure;
    10     10   import polemy.ast;
    11     11   import polemy.parse;
    12     12   import polemy.value;
    13     13   import polemy.layer;
    14     14   import polemy.value;
    15     15   import polemy.valueconv;
           16  +import std.signals;
    16     17   
    17     18   /// Objects for maitaining global environment and evaluation of expression on it
    18     19   class Evaluator
    19     20   {
    20     21   public:
    21     22    /// Initialize evaluator with empty context
    22     23    this() { theContext = new Table; }
    23     24   
    24     25    /// Evaluate the AST
    25     26    Value evalAST(AST e)
    26     27    {
    27         -  return macroAndEval(e, ValueLayer, theContext, OverwriteCtx)[0];
           28  +  AST[void*] mandeCache;
           29  +  return macroAndEval(e, ValueLayer, theContext, OverwriteCtx, mandeCache)[0];
    28     30    }
    29     31   
    30     32    /// Evaluate the string
    31     33    Value evalString(S,T...)(S str, T fn_ln_cn)
    32     34    {
    33     35     return evalAST(parseString(str,fn_ln_cn));
    34     36    }
................................................................................
   152    154     }
   153    155    }
   154    156   
   155    157   private:
   156    158    // little little bit incremental macro defining version.
   157    159    // enables @macro foo(x)=... in ... foo ..., only at the top level of the
   158    160    // interpreter and functions. better than nothing :P
   159         - Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
          161  + Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overwriteCtx
          162  +  , ref AST[void*] mandeCache) // [TODO] avoid assuming non-moving GC
   160    163    {
   161    164     assert( !isASTLayer(lay) );
   162    165   
   163    166     AST decodeAST(Value v, LexPosition pos)
   164    167     {
   165    168      // [TODO] more informative error message
   166    169      return polemy2d!(AST)(v, pos);
   167    170     }
   168    171   
   169    172     if(auto e = cast(Let)e_)
   170    173     {
   171         -   AST   ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e.init.pos);
          174  +   void* key = cast(void*)e.init;
          175  +   AST ai;
          176  +   if(auto p = key in mandeCache)
          177  +    ai = *p;
          178  +   else {
          179  +    ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e.init.pos);
          180  +    mandeCache[key] = ai;
          181  +   }
   172    182      Value vi = eval(ai, lay, ctx);
   173    183   
   174    184      if( !overwriteCtx )
   175    185       ctx = new Table(ctx, Table.Kind.NotPropagateSet);
   176    186      string theLayer = e.layer.empty ? lay : e.layer;
   177    187      ctx.set(e.name, theLayer, vi);
   178    188   
   179         -   auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx );
          189  +   auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx, mandeCache );
   180    190      AST  a = new Let(e.pos, e.name, e.layer, ai, ave[1]);
   181    191      return tuple(ave[0], a);
   182    192     }
   183    193     else
   184    194     {
   185         -   AST   a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos);
   186         -   Value v = eval(a, lay, ctx);
          195  +   void* key = cast(void*)e_;
          196  +   AST a;
          197  +   if(auto p = key in mandeCache)
          198  +    a = *p;
          199  +   else {
          200  +    a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos);
          201  +    mandeCache[key] = a;
          202  +   }
          203  +   Value v = eval(a, lay, ctx, overwriteCtx);
   187    204      return tuple(v, a);
   188    205     }
   189    206    }
   190    207   
   191    208   private:
   192    209    string getNameIfPossible(AST e)
   193    210    {
................................................................................
   271    288       throw genex!RuntimeException("comparison with value and something other");
   272    289      }
   273    290      override hash_t toHash() {
   274    291       return (cast(hash_t)cast(void*)ast) + (cast(hash_t)cast(void*)defCtx);
   275    292      }
   276    293   
   277    294      AST macroCache;
          295  +   AST[void*] mandeCache;
   278    296      static class MemokeyType
   279    297      {
   280    298       void* a; Layer b; Tuple!(string,Layer,Value)[] c;
   281    299       hash_t toHash() {
   282    300        hash_t h = structuralHash(a) + structuralHash(b);
   283    301        foreach(e; c)
   284    302         h += structuralHash(e[0])+structuralHash(e[1])+structuralHash(e[2]);
................................................................................
   294    312      {
   295    313       if( isASTLayer(lay) )
   296    314        return eval(ast.funbody, lay, ctx);
   297    315   
   298    316       auto nonMemoizedRun = (){
   299    317        if( macroCache is null )
   300    318        {
   301         -      auto va = macroAndEval(e.funbody, lay, ctx);
          319  +      auto va = macroAndEval(e.funbody, lay, ctx, CascadeCtx, mandeCache);
   302    320         macroCache = va[1];
   303    321         return va[0];
   304    322        }
   305    323        else
   306    324         return eval(macroCache, lay, ctx);
   307    325       };
   308    326   
................................................................................
   466    484    assert_nothrow( e.evalString(`case 1 when 1: 2`) );
   467    485   
   468    486    // this is a shorthand for
   469    487    //   @macro x = fun(){} in @macro(x)
   470    488    // so it is ok to fail, but it is really incovenient on REPL
   471    489    assert_nothrow( e.evalString(`@macro x=fun(){}`) );
   472    490   }
   473         -
   474         -/*
   475         -unittest
   476         -{
   477         - assert_eq( evalString(`var fac = fun(x){
   478         -  if(x)
   479         -   { x*fac(x-1); }
   480         -  else
   481         -   { 1; };
   482         - };
   483         - fac(10);`).val, new IntValue(BigInt(10*9*8*5040)));
   484         - assert_eq( evalString(`var fib = fun(x){
   485         -  if(x<2)
   486         -   { 1; }
   487         -  else
   488         -   { fib(x-1) + fib(x-2); };
   489         - };
   490         - fib(5);`).val, new IntValue(BigInt(8)));
   491         -}
   492         -unittest
   493         -{
   494         - assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(BigInt(124)) );
   495         - // there was a bug that declaration in the first line of function definition
   496         - // cannot be recursive
   497         - assert_nothrow( evalString(`def foo() {
   498         -  def bar(y) { if(y<1) {0} else {bar(0)} };
   499         -  bar(1)
   500         -}; foo()`) );
   501         -}
   502         -*/