lac : 72eb5b12e039f43e3f5294a36c8f3688976e86ce

     1: /*
     2:    lac -- a lisp interpreter library
     3:    Copyright (C) 2010 Gianluca Guida
     4: 
     5:    This program is free software; you can redistribute it and/or modify
     6:    it under the terms of the GNU General Public License as published by
     7:    the Free Software Foundation; either version 2 of the License, or
     8:    (at your option) any later version.
     9: 
    10:    This program is distributed in the hope that it will be useful,
    11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
    12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13:    GNU General Public License for more details.
    14: 
    15:    You should have received a copy of the GNU General Public License along
    16:    with this program; if not, write to the Free Software Foundation, Inc.,
    17:    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    18: */
    19: 
    20: /* Mapping functions */
    21: #include "lac.h"
    22: #include <gc/gc.h>
    23: 
    24: #define ARGEVAL(_lr, _e) ((_e) == NULL ? _lr : eval((_lr), (_e)))
    25: #define is_cons(lr) (lreg_raw_type(lr) == LREG_CONS)
    26: 
    27: static lreg_t map_args(lreg_t lists)
    28: {
    29:   lreg_t args = lists;
    30:   lreg_t outargs = NIL, tail = NIL;
    31: 
    32:   for ( ; args != NIL ; args = cdr(args) )
    33:     {
    34:       if ( !is_cons(args) ||
    35: 	   !is_cons(car(args)) )
    36: 	{
    37: 	  if ( is_cons(args) && car(args) == NIL )
    38: 	      return NIL;
    39: 	  raise_exception("Syntax Error in mapcar", args);
    40: 	}
    41: 
    42:       if ( outargs == NIL ) {
    43:         outargs = tail = cons(cons(sym_quote, cons(cons(car(car(args)), NIL), NIL)), NIL);
    44:       } else {
    45: 	lreg_t tmp = cons(cons(sym_quote, cons(cons(car(car(args)), NIL), NIL)), NIL);
    46:         rplacd(tail, tmp);
    47:         tail = tmp;
    48:       }
    49: 
    50:       rplaca(args, cdr(car(args)));
    51:     }
    52: 
    53:   return outargs;
    54: }
    55: 
    56: 
    57: 
    58: LAC_API static lreg_t proc_mapcar(lreg_t args, lenv_t *argenv, lenv_t *env)
    59: {
    60:   _EXPECT_MIN_ARGS(args, 2);
    61:   lreg_t mapargs;
    62:   lreg_t fn, lists;
    63:   lreg_t outlist = NIL, tail = NIL;
    64:   lreg_t evd = argenv == NULL ? args : evargs(args, env);
    65:   fn = car(evd);
    66:   lists = cdr(evd);
    67: 
    68:   switch ( lreg_type(fn) )
    69:     {
    70:     case LREG_LAMBDA:
    71:     case LREG_MACRO:
    72:     case LREG_LLPROC:
    73:       break;
    74:     default:
    75:       _ERROR_AND_RET("Syntax error in mapcar");
    76:     }
    77: 
    78: 
    79:   for (;;)
    80:     {
    81:       lreg_t outelm;
    82:       mapargs = map_args(lists);
    83:       if ( mapargs == NIL )
    84:         break;
    85:       outelm = apply(fn, car(mapargs), env);
    86:       
    87:       if ( outlist == NIL ) {
    88:         outlist = tail = cons(outelm, NIL);
    89:       } else {
    90:         lreg_t tmp = cons(outelm, NIL);
    91:         rplacd(tail, tmp);
    92:         tail = tmp;
    93:       }
    94:     }
    95:   return outlist; 
    96: }
    97: 
    98: LAC_API static lreg_t proc_reduce(lreg_t args, lenv_t *argenv, lenv_t *env)
    99: {
   100:   _EXPECT_ARGS(args, 2);
   101:   lreg_t acc;
   102:   lreg_t fn = ARGEVAL(car(args), argenv);
   103:   lreg_t list = ARGEVAL(car(cdr(args)), argenv);
   104: 
   105:   if ( !is_cons(list) )
   106:       _ERROR_AND_RET("Syntax error in reduce\n");
   107: 
   108:   acc = car(list);
   109:   list = cdr(list);
   110: 
   111:   for ( ; list != NIL; list = cdr(list) )
   112: 	  acc = apply(fn, cons(acc, cons(car(list), NIL)), env);
   113: 
   114:   return acc;
   115: }
   116: 
   117: void map_init(lenv_t *env)
   118: {
   119: 
   120:   lac_extproc_register(env, "MAPCAR", proc_mapcar);
   121:   lac_extproc_register(env, "REDUCE", proc_reduce);
   122: }

Generated by git2html.