Differences From Artifact [b119954d6ce43301]:
- File        
polemy/eval.d
- 2010-11-23 07:42:13 - part of checkin [6ac127ddd0] on branch trunk - new evaluator (user: kinaba) [annotate]
 
To Artifact [5a9949a1eb8839b1]:
- File        
polemy/eval.d
- 2010-11-23 09:36:27 - part of checkin [b97bd4f713] on branch trunk - automatic AST to table encoder (user: kinaba) [annotate]
 
    8  import polemy._common;                                                                 8  import polemy._common;
    9  import polemy.failure;                                                                 9  import polemy.failure;
   10  import polemy.ast;                                                                    10  import polemy.ast;
   11  import polemy.parse;                                                                  11  import polemy.parse;
   12  import polemy.value;                                                                  12  import polemy.value;
   13  import polemy.layer;                                                                  13  import polemy.layer;
   14                                                                                        14  
                                                                                        >    15  /// Objects for maitaining global environment and evaluation of expression on it
   15  class Evaluator                                                                       16  class Evaluator
   16  {                                                                                     17  {
   17  public:                                                                               18  public:
                                                                                        >    19          /// Initialize evaluator with empty context
   18          this() { theContext = new Table; }                                            20          this() { theContext = new Table; }
   19                                                                                        21  
                                                                                        >    22          /// Evaluate the AST
   20          Value evalAST(AST e)                                                          23          Value evalAST(AST e)
   21          {                                                                             24          {
   22                  return eval(e, ValueLayer, theContext, OverwriteCtx);                 25                  return eval(e, ValueLayer, theContext, OverwriteCtx);
   23          }                                                                             26          }
   24                                                                                        27  
                                                                                        >    28          /// Evaluate the string
   25          Value evalString(S,T...)(S str, T fn_ln_cn)                                   29          Value evalString(S,T...)(S str, T fn_ln_cn)
   26          {                                                                             30          {
   27                  return evalAST(parseString(str,fn_ln_cn));                            31                  return evalAST(parseString(str,fn_ln_cn));
   28          }                                                                             32          }
   29                                                                                        33  
                                                                                        >    34          /// Evaluate the file
   30          Value evalFile(S,T...)(S filename, T ln_cn)                                   35          Value evalFile(S,T...)(S filename, T ln_cn)
   31          {                                                                             36          {
   32                  return evalAST(parseFile(filename,ln_cn));                            37                  return evalAST(parseFile(filename,ln_cn));
   33          }                                                                             38          }
   34                                                                                        39  
                                                                                        >    40          /// Get the global context
   35          Table globalContext()                                                         41          Table globalContext()
   36          {                                                                             42          {
   37                  return theContext;                                                    43                  return theContext;
   38          }                                                                             44          }
   39                                                                                        45  
   40  private:                                                                              46  private:
   41          Table theContext;                                                             47          Table theContext;
   42                                                                                        48  
   43  private:                                                                         <
   44          enum : bool { CascadeCtx=false, OverwriteCtx=true };                          49          enum : bool { CascadeCtx=false, OverwriteCtx=true };
   45                                                                                   <
   46          Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )       50          Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
   47          {                                                                             51          {
   48                  // dynamic-overload-resolution-pattern: modify here                   52                  // dynamic-overload-resolution-pattern: modify here
   49                  enum funName = "eval";                                                53                  enum funName = "eval";
   50                  alias TypeTuple!(e,lay,ctx,overwriteCtx) params;                      54                  alias TypeTuple!(e,lay,ctx,overwriteCtx) params;
   51                                                                                        55  
   52                  // dynamic-overload-resolution-pattern: dispatch                      56                  // dynamic-overload-resolution-pattern: dispatch
................................................................................................................................................................................
   57                          static if( is(T == typeof(params[0])) ) {} else if( auto      61                          static if( is(T == typeof(params[0])) ) {} else if( auto
   58                                  return __traits(getOverloads, this, funName)[i](      62                                  return __traits(getOverloads, this, funName)[i](
   59                                                                                        63  
   60                  // dynamic-overload-resolution-pattern: default behavior              64                  // dynamic-overload-resolution-pattern: default behavior
   61                  assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not       65                  assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 
   62          }                                                                             66          }
   63                                                                                        67  
   64  private:                                                                         <
   65          Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )       68          Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
   66          {                                                                             69          {
   67                  Value v = new StrValue(e.data);                                  |    70                  if( isMacroishLayer(lay) )
   68                  if( lay==RawMacroLayer || lay==MacroLayer )                      |    71                          return ast2table(e, (AST e){return eval(e,lay,ctx);});
   69                  {                                                                <
   70                          auto ast = new Table;                                    <
   71                          ast.set("pos",  ValueLayer, fromPos(e.pos));             <
   72                          ast.set("is",   ValueLayer, new StrValue("str"));        <
   73                          ast.set("data", ValueLayer, v);                          <
   74                          return ast;                                              <
   75                  }                                                                <
   76                  if( lay==ValueLayer )                                                 72                  if( lay==ValueLayer )
   77                          return v;                                                |    73                          return new StrValue(e.data);
   78                  return lift(v, lay, ctx, e.pos);                                 |    74                  return lift(new StrValue(e.data), lay, ctx, e.pos);
   79          }                                                                             75          }
   80                                                                                        76  
   81          Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )       77          Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
   82          {                                                                             78          {
   83                  Value v = new IntValue(e.data);                                  |    79                  if( isMacroishLayer(lay) )
   84                  if( lay==RawMacroLayer || lay==MacroLayer )                      |    80                          return ast2table(e, (AST e){return eval(e,lay,ctx);});
   85                  {                                                                <
   86                          auto ast = new Table;                                    <
   87                          ast.set("pos",  ValueLayer, fromPos(e.pos));             <
   88                          ast.set("is",   ValueLayer, new StrValue("int"));        <
   89                          ast.set("data", ValueLayer, v);                          <
   90                          return ast;                                              <
   91                  }                                                                <
   92                  if( lay==ValueLayer )                                                 81                  if( lay==ValueLayer )
   93                          return v;                                                |    82                          return new IntValue(e.data);
   94                  return lift(v, lay, ctx, e.pos);                                 |    83                  return lift(new IntValue(e.data), lay, ctx, e.pos);
   95          }                                                                             84          }
   96                                                                                        85  
   97          Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )       86          Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
   98          {                                                                             87          {
   99                  if( lay==RawMacroLayer || lay==MacroLayer )                      |    88                  if( isMacroishLayer(lay) )
  100                  {                                                                <
  101                          if( ctx.has(e.name,MacroLayer) )                              89                          if( ctx.has(e.name,MacroLayer) )
  102                                  return ctx.get(e.name, MacroLayer, e.pos);            90                                  return ctx.get(e.name, MacroLayer, e.pos);
  103                          auto ast = new Table;                                    |    91                          else
  104                          ast.set("pos",  ValueLayer, fromPos(e.pos));             |    92                                  return ast2table(e, (AST e){return eval(e,lay,ct
  105                          ast.set("is",   ValueLayer, new StrValue("var"));        <
  106                          ast.set("name", ValueLayer, new StrValue(e.name));       <
  107                          return ast;                                              <
  108                  }                                                                <
  109                  if( lay==ValueLayer || ctx.has(e.name, lay) )                         93                  if( lay==ValueLayer || ctx.has(e.name, lay) )
  110                          return ctx.get(e.name, lay, e.pos);                           94                          return ctx.get(e.name, lay, e.pos);
  111                  return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos)      95                  return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos)
  112          }                                                                             96          }
  113                                                                                        97  
  114          Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )       98          Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
  115          {                                                                             99          {
  116                  Value f = eval( e.fun, lay, ctx );                                   100                  Value f = eval( e.fun, lay, ctx );
  117                  if( lay==RawMacroLayer || lay==MacroLayer )                      |   101                  if( isMacroishLayer(lay) )
  118                  {                                                                <
  119                          if( auto ff = cast(FunValue)f )                              102                          if( auto ff = cast(FunValue)f )
  120                                  return invokeFunction(ff, e.args, MacroLayer, ct     103                                  return invokeFunction(ff, e.args, MacroLayer, ct
  121                          Table ast = new Table;                                   <
  122                          ast.set("pos",  ValueLayer, fromPos(e.pos));             <
  123                          ast.set("is",   ValueLayer, new StrValue("app"));        <
  124                          ast.set("fun",  ValueLayer, f);                          <
  125                          Table args = new Table;                                  <
  126                          foreach_reverse(a; e.args)                               <
  127                                  args = makeCons(eval(a, lay, ctx), args);        <
  128                          ast.set("args", ValueLayer, args);                       <
  129                          return ast;                                              <
  130                  }                                                                <
  131                  else                                                             |   104                          else
  132                  {                                                                <
                                                                                        >   105                                  return ast2table(e, (AST e){return eval(e,lay,ct
  133                          return invokeFunction(f, e.args, lay, ctx, e.pos);       |   106                  return invokeFunction(f, e.args, lay, ctx, e.pos);
  134                  }                                                                <
  135          }                                                                            107          }
  136                                                                                       108  
  137          Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )      109          Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
  138          {                                                                            110          {
  139                  if( lay==RawMacroLayer || lay==MacroLayer )                      |   111                  if( isMacroishLayer(lay) )
  140                  {                                                                |   112                          return ast2table(e, (AST e){return eval(e,lay,ctx);});
  141                          Table t = new Table;                                     <
  142                          t.set("pos",     ValueLayer, fromPos(e.pos));            <
  143                          t.set("is",      ValueLayer, new StrValue("fun"));       <
  144                          t.set("funbody", ValueLayer, eval(e.funbody,lay,ctx));   <
  145                          Table params = new Table;                                <
  146                          foreach_reverse(p; e.params)                             <
  147                          {                                                        <
  148                                  Table lays = new Table;                          <
  149                                  foreach_reverse(l; p.layers)                     <
  150                                          lays = makeCons(new StrValue(l), lays);  <
  151                                  Table kv = new Table;                            <
  152                                  kv.set("name", ValueLayer, new StrValue(p.name)) <
  153                                  kv.set("layers", ValueLayer, lays);              <
  154                                  Table cons = new Table;                          <
  155                                  params = makeCons(kv, params);                   <
  156                          }                                                        <
  157                          t.set("params", ValueLayer, params);                     <
  158                          return t;                                                <
  159                  }                                                                <
  160                  else                                                                 113                  else
  161                  {                                                                <
  162                          return createNewFunction(e, ctx);                            114                          return createNewFunction(e, ctx);
  163                  }                                                                <
  164          }                                                                            115          }
  165                                                                                       116  
  166          Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )      117          Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
  167          {                                                                            118          {
  168                  if( lay == RawMacroLayer )                                       |   119                  if( isNoLayerChangeLayer(lay) )
  169                  {                                                                |   120                          return ast2table(e, (AST e){return eval(e,lay,ctx);});
  170                          Value r = eval(e.expr, lay, ctx);                        <
  171                          auto ast = new Table; // todo: pos                       <
  172                          ast.set("pos",   ValueLayer, fromPos(e.pos));            <
  173                          ast.set("is",    ValueLayer, new StrValue("lay"));       <
  174                          ast.set("layer", ValueLayer, new StrValue(e.layer));     <
  175                          ast.set("expr",  ValueLayer, r);                         <
  176                          return ast;                                              <
  177                  }                                                                <
  178                  else                                                                 121                  else
  179                          return eval(e.expr, e.layer, ctx);                           122                          return eval(e.expr, e.layer, ctx);
  180          }                                                                            123          }
  181                                                                                       124  
  182          Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )      125          Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
  183          {                                                                            126          {
  184                  // todo @macro let                                                   127                  // todo @macro let
  185                  if( lay==RawMacroLayer || lay==MacroLayer )                      |   128                  if( isMacroishLayer(lay) )
  186                  {                                                                |   129                          return ast2table(e, (AST e){return eval(e,lay,ctx);});
  187                          auto ast = new Table; // todo: pos                       <
  188                          ast.set("pos",   ValueLayer, fromPos(e.pos));            <
  189                          ast.set("is",    ValueLayer, new StrValue("let"));       <
  190                          ast.set("name",  ValueLayer, new StrValue(e.name));      <
  191                          ast.set("layer", ValueLayer, new StrValue(e.layer));     <
  192                          ast.set("init",  ValueLayer, eval(e.init, lay, ctx));    <
  193                          ast.set("expr",  ValueLayer, eval(e.expr, lay, ctx));    <
  194                          return ast;                                              <
  195                  }                                                                <
  196                  else                                                                 130                  else
  197                  {                                                                    131                  {
  198                          if( !overwriteCtx )                                          132                          if( !overwriteCtx )
  199                                  ctx = new Table(ctx, Table.Kind.NotPropagateSet)     133                                  ctx = new Table(ctx, Table.Kind.NotPropagateSet)
  200                          Value ri = eval(e.init, lay, ctx);                           134                          Value ri = eval(e.init, lay, ctx);
  201                          string theLayer = e.layer.empty ? (lay==RawMacroLayer ?  |   135                          string theLayer = e.layer.empty ? lay : e.layer; // neut
  202                          ctx.set(e.name, theLayer, ri);                               136                          ctx.set(e.name, theLayer, ri);
  203                          return eval(e.expr, lay, ctx, OverwriteCtx);                 137                          return eval(e.expr, lay, ctx, OverwriteCtx);
  204                  }                                                                    138                  }
  205          }                                                                            139          }
  206                                                                                       140  
  207  private:                                                                             141  private:
  208          Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi     142          Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi
................................................................................................................................................................................
  212                          Table newCtx = new Table(f.definitionContext(), Table.Ki     146                          Table newCtx = new Table(f.definitionContext(), Table.Ki
  213                          foreach(i,p; f.params())                                     147                          foreach(i,p; f.params())
  214                                  if( p.layers.empty )                                 148                                  if( p.layers.empty )
  215                                          newCtx.set(p.name, (lay==RawMacroLayer ?     149                                          newCtx.set(p.name, (lay==RawMacroLayer ?
  216                                  else                                                 150                                  else
  217                                          foreach(argLay; p.layers)                    151                                          foreach(argLay; p.layers)
  218                                                  newCtx.set(p.name, argLay, eval(     152                                                  newCtx.set(p.name, argLay, eval(
  219                          return f.invoke(pos, lay, newCtx);                       |   153                          return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, n
  220                  }                                                                    154                  }
  221                  throw genex!RuntimeException(pos, text("tried to call non-functi     155                  throw genex!RuntimeException(pos, text("tried to call non-functi
  222          }                                                                            156          }
  223                                                                                       157  
  224          Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null)              158          Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null)
  225          {                                                                            159          {
                                                                                        >   160                  assert( !isMacroishLayer(lay), "lift to the @macro layer should 
                                                                                        >   161  
  226                  // functions are automatically lifterd                               162                  // functions are automatically lifterd
  227                  if( cast(FunValue) v )                                               163                  if( cast(FunValue) v )
  228                          return v;                                                    164                          return v;
  229                                                                                       165  
  230                  // similar to invoke Function, but with only one argument bound      166                  // similar to invoke Function, but with only one argument bound 
  231                  if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos))            167                  if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos))
  232                  {                                                                    168                  {
................................................................................................................................................................................
  233                          Table newCtx = new Table(f.definitionContext(), Table.Ki     169                          Table newCtx = new Table(f.definitionContext(), Table.Ki
  234                          auto ps = f.params();                                        170                          auto ps = f.params();
  235                          if( ps.length != 1 )                                         171                          if( ps.length != 1 )
  236                                  throw genex!RuntimeException(pos, "lift function     172                                  throw genex!RuntimeException(pos, "lift function
  237                          if( ps[0].layers.length==0 || ps[0].layers.length==1 &&      173                          if( ps[0].layers.length==0 || ps[0].layers.length==1 && 
  238                          {                                                            174                          {
  239                                  newCtx.set(ps[0].name, ValueLayer, v);               175                                  newCtx.set(ps[0].name, ValueLayer, v);
  240                                  return f.invoke(pos, ValueLayer, newCtx);        |   176                                  return f.invoke(ValueLayer, newCtx, pos);
  241                          }                                                            177                          }
  242                          else                                                         178                          else
  243                                  throw genex!RuntimeException(pos, "lift function     179                                  throw genex!RuntimeException(pos, "lift function
  244                  }                                                                    180                  }
  245                  throw genex!RuntimeException(pos, "tried to call non-function");     181                  throw genex!RuntimeException(pos, "tried to call non-function");
  246          }                                                                            182          }
  247                                                                                       183  
................................................................................................................................................................................
  273                                          if(auto i = this.ast.opCmp(rhs.ast))         209                                          if(auto i = this.ast.opCmp(rhs.ast))
  274                                                  return i;                            210                                                  return i;
  275                                          return this.defCtx.opCmp(rhs.defCtx);        211                                          return this.defCtx.opCmp(rhs.defCtx);
  276                                  }                                                    212                                  }
  277                                  assert(false, sprintf!"Cannot compare %s with %s     213                                  assert(false, sprintf!"Cannot compare %s with %s
  278                          }                                                            214                          }
  279                                                                                       215  
  280                          override Value invoke(LexPosition pos, Layer lay, Table  |   216                          override Value invoke(Layer lay, Table ctx, LexPosition 
  281                          {                                                            217                          {
  282                                  if( lay == MacroLayer )                              218                                  if( lay == MacroLayer )
  283                                          return eval(ast.funbody, lay, ctx);          219                                          return eval(ast.funbody, lay, ctx);
                                                                                        >   220                                  if( afterMacroAST is null )
  284                                  auto macroed = tableToAST(ValueLayer, eval(e.fun |   221                                          afterMacroAST = tableToAST(ValueLayer, e
  285                                  return eval(macroed, lay, ctx);                  |   222                                  return eval(afterMacroAST, lay, ctx);
  286                          }                                                            223                          }
                                                                                        >   224  
                                                                                        >   225                          AST afterMacroAST;
  287                  }                                                                    226                  }
  288                  return new UserDefinedFunValue(e,ctx);                               227                  return new UserDefinedFunValue(e,ctx);
  289          }                                                                            228          }
  290                                                                                       229  
  291  public:                                                                              230  public:
  292          /// TODO: move up                                                        |   231          /// Add primitive function to the global context
  293          /// TDOO: to other layers?                                               <
  294          void addPrimitive(R,T...)(string name, Layer lay, R delegate (T) dg)     |   232          void addPrimitive(R,T...)(string name, Layer defLay, R delegate (T) dg)
  295          {                                                                            233          {
  296                  class NativeFunValue : FunValue                                      234                  class NativeFunValue : FunValue
  297                  {                                                                    235                  {
  298                          Parameter[] params_data;                                 <
  299                          override string toString() { return sprintf!"(native:%x) <
  300                          override const(Parameter[]) params() { return params_dat     236                          override const(Parameter[]) params() { return params_dat
  301                          override Table definitionContext() { return new Table; } |   237                          override Table definitionContext()   { return theContext
                                                                                        >   238  
                                                                                        >   239                          override string toString() { return sprintf!"(native:%x)
                                                                                        >   240                          override int opCmp(Object rhs) {
                                                                                        >   241                                  if(auto r = cast(NativeFunValue)rhs) return type
                                                                                        >   242                                  if(auto r = cast(Value)rhs)          return type
                                                                                        >   243                                  throw genex!RuntimeException(LexPosition.dummy, 
                                                                                        >   244                          }
                                                                                        >   245                          mixin SimpleToHash;
                                                                                        >   246  
                                                                                        >   247                          R delegate(T) dg;
                                                                                        >   248                          Parameter[] params_data;
                                                                                        >   249  
                                                                                        >   250                          this(R delegate(T) dg)
                                                                                        >   251                          {
  302                          this(){                                                  |   252                                  this.dg = dg;
  303                                  foreach(i, Ti; T)                                    253                                  foreach(i, Ti; T)
  304                                          params_data ~= new Parameter(text(i), []     254                                          params_data ~= new Parameter(text(i), []
  305                          }                                                            255                          }
                                                                                        >   256  
  306                          override Value invoke(LexPosition pos, Layer lay, Table  |   257                          override Value invoke(Layer lay, Table ctx, LexPosition 
  307                          {                                                            258                          {
  308                                  if( lay != ValueLayer )                          |   259                                  if( lay != defLay )
  309                                          throw genex!RuntimeException(pos, "only  |   260                                          throw genex!RuntimeException(pos, text("
  310                                  T typed_args;                                        261                                  T typed_args;
  311                                  foreach(i, Ti; T) {                                  262                                  foreach(i, Ti; T) {
  312                                          typed_args[i] = cast(Ti) ctx.get(text(i) |   263                                          typed_args[i] = cast(Ti) ctx.get(text(i)
  313                                          if( typed_args[i] is null )                  264                                          if( typed_args[i] is null )
  314                                                  throw genex!RuntimeException(pos |   265                                                  throw genex!RuntimeException(pos
  315                                  }                                                    266                                  }
  316                                  try {                                                267                                  try {
  317                                          return dg(typed_args);                       268                                          return dg(typed_args);
  318                                  } catch( RuntimeException e ) {                      269                                  } catch( RuntimeException e ) {
  319                                          throw e.pos is null ? new RuntimeExcepti     270                                          throw e.pos is null ? new RuntimeExcepti
  320                                  }                                                    271                                  }
  321                          }                                                            272                          }
  322                  }                                                                    273                  }
  323                  theContext.set(name, lay, new NativeFunValue);                   |   274                  theContext.set(name, defLay, new NativeFunValue(dg));
  324          }                                                                            275          }
  325  }                                                                                    276  }
  326                                                                                       277  
  327  version(unittest) import polemy.runtime;                                             278  version(unittest) import polemy.runtime;
  328  unittest                                                                             279  unittest
  329  {                                                                                    280  {
  330          auto e = new Evaluator;                                                      281          auto e = new Evaluator;