The Pico Evaluator

(contents of the file Eval.pco)
general info

{ eval(Exp):
    error('evaluator not initialized');
        
  init_eval(Dct):
    { DCT: Dct;

      eval_variable(Exp):
        { nam: Exp[VAR_NAM_idx];
          get(nam, DCT) };

      call_function(Exp, Dct):
        { dct: DCT;
          DCT:= Dct;
          val: eval(Exp);
          DCT:= dct;
          val };

      bind_variable(Exp, Var, Dct):
        { nam: Var[VAR_NAM_idx];
          val: eval(Exp);
          add(nam, val, Dct) };

      bind_application(Exp, Apl, Dct):
        { nam: Apl[APL_NAM_idx];
          arg: Apl[APL_ARG_idx]; 
          fun: FUN(nam, arg, Exp, DCT);
          add(nam, fun, Dct) };

      bind_error(Tab, Err, Dct):
        error('illegal parameter');
   
     bind_case: case(VAR_tag => bind_variable,
                      APL_tag => bind_application,
                         else => bind_error);
  
      call_table(TbA, TbP, Dct):
        { tbA: TbA[TAB_TAB_idx];
          tbP: TbP[TAB_TAB_idx];
          siz: size(tbA);
          if(siz = size(tbP),
             for(k: 1, k:= k+1, not(k > siz),
                 { arg: tbA[k];
                   par: tbP[k];
                   tag: par[TAG_idx];
                   cas: bind_case(tag);
                   Dct:= cas(arg, par, Dct) }),
             error('Illegal argument count'));
          Dct };

      call_variable(Tab, Var, Dct):
        { nam: Var[VAR_NAM_idx];
          tab: Tab[TAB_TAB_idx];
          siz: size(tab);
          exp: if(siz > 0,
                  { idx: 0;
                    arg[siz]: eval(tab[idx:= idx+1]);
                    TAB(arg) },
                  Empty);
          add(nam, exp, Dct) };
   
      call_error(Tab, Apl, Dct):
        error('illegal parameter');
   
      call_case: case(TAB_tag => call_table,
                      VAR_tag => call_variable,
                         else => call_error);
  
      eval_call(Fun, Tab):
        { par: Fun[FUN_PAR_idx];
          exp: Fun[FUN_EXP_idx];
          dct: Fun[FUN_DCT_idx];
          tag: par[TAG_idx];
          cas: call_case(tag);
          dct:= cas(Tab, par, dct);
          call_function(exp, dct) };

      eval_application(Exp):
        { nam: Exp[APL_NAM_idx];
          arg: Exp[APL_ARG_idx];
          exp: get(nam, DCT);
          if(exp[TAG_idx] = FUN_tag,
             if(arg[TAG_idx] = TAB_tag,
                eval_call(exp, arg),
                { val: eval(arg);
                  if(val[TAG_idx] = TAB_tag,
                     eval_call(exp, val),
                     error('illegal argument')) }),
             if(exp[TAG_idx] = NAT_tag,
                { nat: exp[NAT_NAT_idx]; 
                  nat@arg },
                error('(native) function required'))) };

      eval_tabulation(Exp):
        { nam: Exp[TBL_NAM_idx];
          exp: get(nam, DCT);
          if(exp[TAG_idx] = TAB_tag,
             { idx: Exp[TBL_IDX_idx];
               val: eval(idx);
               if(val[TAG_idx] = NBR_tag,
                  { nbr: val[NBR_VAL_idx];
                    if(nbr > 0, 
                       { tab: exp[TAB_TAB_idx];
                         if(nbr > size(tab),
                            error('index beyond size'),
                            tab[nbr]) },
                       error('non-positive index')) },
                  error('invalid index')) },
             error('table required')) };

      define_variable(Var, Exp):
        { nam: Var[VAR_NAM_idx];
          val: eval(Exp);
          DCT:= add(nam, val, DCT);
          val };
    
      define_application(Apl, Exp):
        { nam: Apl[APL_NAM_idx];
          arg: Apl[APL_ARG_idx];
          DCT:= add(nam, Void, DCT);
          fun: FUN(nam, arg, Exp, DCT);
          set(nam, fun, DCT);
          fun };
    
      define_tabulation(Tbl, Exp):
        { nam: Tbl[TBL_NAM_idx];
          idx: Tbl[TBL_IDX_idx];
          val: eval(idx);
          if(val[TAG_idx] = NBR_tag,
             { nbr: val[NBR_VAL_idx];
               if(nbr < 0,
                  error('negative size'),
                  { exp: if(nbr > 0,
                            { tab[nbr]: eval(Exp);
                              TAB(tab) },
                            Empty );
                    DCT:= add(nam, exp, DCT);
                    exp }) },
             error('invalid size')) }; 
   
      define_error(Inv, Exp):
         error('invocation required');
  
      define_case: case(VAR_tag => define_variable,
                        APL_tag => define_application,
                        TBL_tag => define_tabulation,
                           else => define_error);
  
      eval_definition(Exp):
        { inv: Exp[DEF_INV_idx];
          exp: Exp[DEF_EXP_idx];
          tag: inv[TAG_idx];
          cas: define_case(tag);
          cas(inv, exp) };

      assign_variable(Var, Exp):
        { nam: Var[VAR_NAM_idx];
          val: eval(Exp);
          set(nam, val, DCT);
          val };
    
      assign_application(Apl, Exp):
        { nam: Apl[APL_NAM_idx];
          arg: Apl[APL_ARG_idx];
          fun: FUN(nam, arg, Exp, DCT);
          set(nam, fun, DCT);
          fun };
    
      assign_tabulation(Tbl, Exp):
        { nam: Tbl[TBL_NAM_idx];
          exp: get(nam, DCT);
          if(exp[TAG_idx] = TAB_tag,
             { idx: Tbl[TBL_IDX_idx];
               val: eval(idx);
               if(val[TAG_idx] = NBR_tag,
                  { nbr: val[NBR_VAL_idx];
                    if(nbr > 0, 
                       { tab: exp[TAB_TAB_idx];
                         if(nbr > size(tab),
                            error('index beyond size'),
                            { tab[nbr]:= eval(Exp);
                              exp }) },
                       error('non-positive index')) },
                  error('invalid index')) },
             error('table required')) };
   
      assign_error(Inv, Exp):
         error('invocation required');
  
      assign_case: case(VAR_tag => assign_variable,
                        APL_tag => assign_application,
                        TBL_tag => assign_tabulation,
                           else => assign_error);
  
      eval_assignment(Exp):
        { inv: Exp[SET_INV_idx];
          exp: Exp[SET_EXP_idx];
          tag: inv[TAG_idx];
          cas: assign_case(tag);
          cas(inv, exp) };
    
      eval_identity(Exp):
        Exp;
    
      eval_case: case(VAR_tag => eval_variable,
                      APL_tag => eval_application,
                      TBL_tag => eval_tabulation,
                      DEF_tag => eval_definition,
                      SET_tag => eval_assignment,
                         else => eval_identity);
  
      init_eval(Dct):=
        { DCT:= Dct;
          void };

     eval(Exp):=
        { tag: Exp[TAG_idx];
          cas: eval_case(tag);
          cas(Exp) };
  
      void };

  display('evaluator installed', eoln) }

Back to the metacircular evaluator

This page was made (with lots of hard work!) by Wolfgang De Meuter