Blame doc/minilisp/minilisp.cpp

Packit df99a1
/* -*- C++ -*-
Packit df99a1
// -------------------------------------------------------------------
Packit df99a1
// MiniLisp - Very small lisp interpreter to demonstrate MiniExp.
Packit df99a1
// Copyright (c) 2005  Leon Bottou
Packit df99a1
//
Packit df99a1
// This software is subject to, and may be distributed under, the
Packit df99a1
// GNU General Public License, either Version 2 of the license,
Packit df99a1
// or (at your option) any later version. The license should have
Packit df99a1
// accompanied the software or you may obtain a copy of the license
Packit df99a1
// from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//
Packit df99a1
// This program is distributed in the hope that it will be useful,
Packit df99a1
// but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
// GNU General Public License for more details.
Packit df99a1
// -------------------------------------------------------------------
Packit df99a1
*/
Packit df99a1
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <stdio.h>
Packit df99a1
#include <string.h>
Packit df99a1
#include <signal.h>
Packit df99a1
#include <ctype.h>
Packit df99a1
#include <math.h>
Packit df99a1
Packit df99a1
#include "miniexp.h"
Packit df99a1
Packit df99a1
#define CAT(a,b) __CAT(a,b)
Packit df99a1
#define __CAT(a,b) a ## b
Packit df99a1
Packit df99a1
miniexp_t s_quote = miniexp_symbol("quote");
Packit df99a1
miniexp_t s_true = miniexp_symbol("t");
Packit df99a1
Packit df99a1
/* ------------ error */
Packit df99a1
Packit df99a1
#ifdef __GNUC__
Packit df99a1
void error(const char *msg, miniexp_t v=0) __attribute__ ((noreturn));
Packit df99a1
#else
Packit df99a1
void error(const char *msg, miniexp_t v=0);
Packit df99a1
#endif
Packit df99a1
Packit df99a1
void
Packit df99a1
error(const char *msg, miniexp_t v)
Packit df99a1
{
Packit df99a1
  if (msg)
Packit df99a1
    printf("ERROR: %s", msg);
Packit df99a1
  else
Packit df99a1
    printf("BREAK");
Packit df99a1
  if (v)
Packit df99a1
    {
Packit df99a1
      printf(": ");
Packit df99a1
      miniexp_prin(v);
Packit df99a1
    }
Packit df99a1
  printf("\n");
Packit df99a1
  throw 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/* ------------ environment */
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
lookup(miniexp_t var, miniexp_t env)
Packit df99a1
{
Packit df99a1
  while (miniexp_consp(env))
Packit df99a1
    {
Packit df99a1
      miniexp_t a = miniexp_car(env);
Packit df99a1
      if (miniexp_car(a) == var)
Packit df99a1
	return a;
Packit df99a1
      env = miniexp_cdr(env);
Packit df99a1
    }
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
minivar_t globalenv;
Packit df99a1
Packit df99a1
void
Packit df99a1
defvar(miniexp_t s, miniexp_t w = 0)
Packit df99a1
{
Packit df99a1
  minivar_t v;
Packit df99a1
  if (! globalenv)
Packit df99a1
    {
Packit df99a1
      minivar_t a = miniexp_cons(s_true, s_true);
Packit df99a1
      globalenv = miniexp_cons(a, 0);
Packit df99a1
    }
Packit df99a1
  if (! miniexp_symbolp(s))
Packit df99a1
    error("defvar: not a symbol", s);
Packit df99a1
  miniexp_t a = lookup(s, globalenv);
Packit df99a1
  if (a && w)
Packit df99a1
    {
Packit df99a1
      printf("WARNING: redefining '%s\n", miniexp_to_name(s));
Packit df99a1
      miniexp_rplacd(a, w);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      v = miniexp_cons(s, w);
Packit df99a1
      v = miniexp_cons(v, miniexp_cdr(globalenv));
Packit df99a1
      miniexp_rplacd(globalenv, v);
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
/* ------------ evaluate */
Packit df99a1
Packit df99a1
static bool break_request = false;
Packit df99a1
Packit df99a1
struct callable_t : public miniobj_t
Packit df99a1
{
Packit df99a1
  MINIOBJ_DECLARE(callable_t,miniobj_t,"callable");
Packit df99a1
  virtual miniexp_t call(miniexp_t args, miniexp_t env,
Packit df99a1
			 bool apply=false) = 0;
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(callable_t,miniobj_t,"callable");
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
evaluate(miniexp_t expr, miniexp_t env)
Packit df99a1
{
Packit df99a1
  if (miniexp_symbolp(expr))
Packit df99a1
    {
Packit df99a1
      miniexp_t a = lookup(expr,env);
Packit df99a1
      if (! a)
Packit df99a1
	error ("eval: undefined variable", expr);
Packit df99a1
      return miniexp_cdr(a);
Packit df99a1
    }
Packit df99a1
  else if (miniexp_consp(expr))
Packit df99a1
    {
Packit df99a1
      miniexp_t s = miniexp_car(expr);
Packit df99a1
      minivar_t xs = evaluate(s, env);
Packit df99a1
      miniobj_t *obj = miniexp_to_obj(xs);
Packit df99a1
      if (break_request)
Packit df99a1
	error(0);
Packit df99a1
      if (obj && obj->isa(callable_t::classname))
Packit df99a1
	return ((callable_t*)obj)->call(miniexp_cdr(expr), env);
Packit df99a1
      error("apply: cannot apply this object", xs);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    return expr;
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
evaluate_progn(miniexp_t exprs, miniexp_t env)
Packit df99a1
{
Packit df99a1
  minivar_t v;
Packit df99a1
  while (miniexp_consp(exprs))
Packit df99a1
    {
Packit df99a1
      v = evaluate(miniexp_car(exprs),env);
Packit df99a1
      exprs = miniexp_cdr(exprs);
Packit df99a1
    }
Packit df99a1
  if (exprs)
Packit df99a1
    v = evaluate(exprs,env);
Packit df99a1
  return v;
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
evaluate_list(miniexp_t l, miniexp_t env)
Packit df99a1
{
Packit df99a1
  minivar_t v;
Packit df99a1
  minivar_t ll = 0;
Packit df99a1
  miniexp_t lp = ll;
Packit df99a1
  if (miniexp_consp(l))
Packit df99a1
    {
Packit df99a1
      v = evaluate(miniexp_car(l), env);
Packit df99a1
      lp = ll = miniexp_cons(v, 0);
Packit df99a1
      l = miniexp_cdr(l);
Packit df99a1
    }
Packit df99a1
  while (miniexp_consp(l))
Packit df99a1
    {
Packit df99a1
      v = evaluate(miniexp_car(l), env);
Packit df99a1
      miniexp_rplacd(lp, miniexp_cons(v, 0));
Packit df99a1
      lp = miniexp_cdr(lp);
Packit df99a1
      l = miniexp_cdr(l);
Packit df99a1
    }
Packit df99a1
  if (l)
Packit df99a1
    {
Packit df99a1
      v = evaluate(l, env);
Packit df99a1
      if (lp)
Packit df99a1
	miniexp_rplacd(lp, v);
Packit df99a1
      else
Packit df99a1
	ll = v;
Packit df99a1
    }
Packit df99a1
  return ll;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
/* ------------ special forms */
Packit df99a1
Packit df99a1
class specialform_t : public callable_t
Packit df99a1
{
Packit df99a1
  typedef miniexp_t (*fptr_t)(miniexp_t, miniexp_t);
Packit df99a1
  fptr_t fptr;
Packit df99a1
public:
Packit df99a1
  specialform_t(const char *name, fptr_t fptr);
Packit df99a1
  MINIOBJ_DECLARE(specialform_t,callable_t,"specialform");
Packit df99a1
  virtual miniexp_t call(miniexp_t args, miniexp_t env, bool);
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(specialform_t,callable_t,"specialform");
Packit df99a1
Packit df99a1
specialform_t::specialform_t(const char *name, fptr_t fptr)
Packit df99a1
  : fptr(fptr)
Packit df99a1
{
Packit df99a1
  miniexp_t s = miniexp_symbol(name);
Packit df99a1
  minivar_t v = miniexp_object(this);
Packit df99a1
  defvar(s, v);
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
specialform_t::call(miniexp_t args, miniexp_t env, bool)
Packit df99a1
{
Packit df99a1
  return (*fptr)(args, env);
Packit df99a1
}
Packit df99a1
Packit df99a1
#define DEFSPECIAL(s, n) \
Packit df99a1
miniexp_t CAT(f_,n)(miniexp_t, miniexp_t);\
Packit df99a1
specialform_t *CAT(p_,n) = new specialform_t(s, CAT(f_,n));\
Packit df99a1
miniexp_t CAT(f_,n)(miniexp_t expr, miniexp_t env)
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
/* ------------ primitives */
Packit df99a1
Packit df99a1
class primitive_t : public callable_t
Packit df99a1
{
Packit df99a1
  typedef miniexp_t (*fptr_t)(int, miniexp_t*, miniexp_t);
Packit df99a1
  fptr_t fptr;
Packit df99a1
  const int args;
Packit df99a1
  const int optargs;
Packit df99a1
public:
Packit df99a1
  primitive_t(const char *name, fptr_t fptr, int a, int o);
Packit df99a1
  MINIOBJ_DECLARE(primitive_t,callable_t,"primitive");
Packit df99a1
  virtual miniexp_t call(miniexp_t args, miniexp_t env, bool);
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(primitive_t,callable_t,"primitive");
Packit df99a1
Packit df99a1
primitive_t::primitive_t(const char *n, fptr_t f, int a, int o)
Packit df99a1
  : fptr(f), args(a), optargs(o)
Packit df99a1
{
Packit df99a1
  miniexp_t s = miniexp_symbol(n);
Packit df99a1
  minivar_t v = miniexp_object(this);
Packit df99a1
  defvar(s, v);
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
primitive_t::call(miniexp_t args, miniexp_t env, bool apply)
Packit df99a1
{
Packit df99a1
  int argc = miniexp_length(args);
Packit df99a1
  if (argc < this->args)
Packit df99a1
    error("apply(primitive): not enough arguments");
Packit df99a1
  if (argc > this->args + this->optargs)
Packit df99a1
    error("apply(primitive): too many arguments");
Packit df99a1
  minivar_t xargs = apply ? args : evaluate_list(args, env);
Packit df99a1
  miniexp_t *argv = new miniexp_t[argc];
Packit df99a1
  miniexp_t a = xargs;
Packit df99a1
  argc = 0;
Packit df99a1
  while (miniexp_consp(a))
Packit df99a1
    {
Packit df99a1
      argv[argc++] = miniexp_car(a);
Packit df99a1
      a = miniexp_cdr(a);
Packit df99a1
    }
Packit df99a1
  minivar_t v;
Packit df99a1
  try
Packit df99a1
    { v = (*fptr)(argc, argv, env); }
Packit df99a1
  catch(...)
Packit df99a1
    { delete [] argv; throw; }
Packit df99a1
  delete [] argv;
Packit df99a1
  return v;
Packit df99a1
}
Packit df99a1
Packit df99a1
#define DEFUN(s, n,a,o) \
Packit df99a1
miniexp_t CAT(f_,n)(int argc, miniexp_t *argv, miniexp_t env);\
Packit df99a1
primitive_t *CAT(p_,n) = new primitive_t(s, CAT(f_,n), a, o);\
Packit df99a1
miniexp_t CAT(f_,n)(int argc, miniexp_t *argv, miniexp_t env)
Packit df99a1
Packit df99a1
Packit df99a1
/* ------- functions */
Packit df99a1
Packit df99a1
class function_t : public callable_t
Packit df99a1
{
Packit df99a1
protected:
Packit df99a1
  miniexp_t args;
Packit df99a1
  miniexp_t body;
Packit df99a1
  miniexp_t env;
Packit df99a1
  static void check_args(miniexp_t a);
Packit df99a1
  static void match_args(miniexp_t a, miniexp_t v, miniexp_t &env;;
Packit df99a1
public:
Packit df99a1
  function_t(miniexp_t, miniexp_t, miniexp_t);
Packit df99a1
  MINIOBJ_DECLARE(function_t,callable_t,"function");
Packit df99a1
  virtual miniexp_t call(miniexp_t args, miniexp_t env, bool);
Packit df99a1
  virtual void mark(minilisp_mark_t action);
Packit df99a1
  virtual miniexp_t funcdef(miniexp_t name=0);
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(function_t,callable_t,"function");
Packit df99a1
Packit df99a1
void
Packit df99a1
function_t::check_args(miniexp_t a)
Packit df99a1
{
Packit df99a1
 again:
Packit df99a1
  if (miniexp_symbolp(a) || !a)
Packit df99a1
    return;
Packit df99a1
  if (miniexp_listp(a))
Packit df99a1
    {
Packit df99a1
      check_args(miniexp_car(a));
Packit df99a1
      a = miniexp_cdr(a);
Packit df99a1
      goto again;
Packit df99a1
    }
Packit df99a1
  error("lambda: illegal formal arguments");
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
function_t::match_args(miniexp_t a, miniexp_t v, miniexp_t &env)
Packit df99a1
{
Packit df99a1
 again:
Packit df99a1
  if (miniexp_symbolp(a))
Packit df99a1
    {
Packit df99a1
      minivar_t x = miniexp_cons(a,v);
Packit df99a1
      env = miniexp_cons(x, env);
Packit df99a1
      return;
Packit df99a1
    }
Packit df99a1
  if (miniexp_consp(a))
Packit df99a1
    {
Packit df99a1
      if (! miniexp_consp(v))
Packit df99a1
	error("apply: not enough arguments", a);
Packit df99a1
      match_args(miniexp_car(a), miniexp_car(v), env);
Packit df99a1
      a = miniexp_cdr(a);
Packit df99a1
      v = miniexp_cdr(v);
Packit df99a1
      goto again;
Packit df99a1
    }
Packit df99a1
  if (v)
Packit df99a1
    error("apply: too many arguments", v);
Packit df99a1
}
Packit df99a1
Packit df99a1
function_t::function_t(miniexp_t a, miniexp_t b, miniexp_t e)
Packit df99a1
  : args(a), body(b), env(e)
Packit df99a1
{
Packit df99a1
  check_args(a);
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
function_t::call(miniexp_t args, miniexp_t env, bool apply)
Packit df99a1
{
Packit df99a1
  minivar_t xargs = apply ? args : evaluate_list(args, env);
Packit df99a1
  minivar_t nenv = this->env;
Packit df99a1
  match_args(this->args, xargs, nenv);
Packit df99a1
  return evaluate_progn(body, nenv);
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
function_t::mark(minilisp_mark_t action)
Packit df99a1
{
Packit df99a1
  action(&args);
Packit df99a1
  action(&body);
Packit df99a1
  action(&env;;
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
function_t::funcdef(miniexp_t name)
Packit df99a1
{
Packit df99a1
  if (name)
Packit df99a1
    {
Packit df99a1
      miniexp_t d = miniexp_symbol("defun");
Packit df99a1
      miniexp_t a = miniexp_cons(name, args);
Packit df99a1
      return miniexp_cons(d, miniexp_cons(a, body));
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      miniexp_t d = miniexp_symbol("lambda");
Packit df99a1
      return miniexp_cons(d,miniexp_cons(args,body));
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
/* ------- macros */
Packit df99a1
Packit df99a1
class macrofunction_t : public function_t
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  macrofunction_t(miniexp_t a, miniexp_t b, miniexp_t e);
Packit df99a1
  MINIOBJ_DECLARE(macrofunction_t,function_t,"macrofunction");
Packit df99a1
  virtual miniexp_t call(miniexp_t args, miniexp_t env, bool);
Packit df99a1
  virtual miniexp_t funcdef(miniexp_t name=0);
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(macrofunction_t,function_t,"macrofunction");
Packit df99a1
Packit df99a1
macrofunction_t::macrofunction_t(miniexp_t a, miniexp_t b, miniexp_t e)
Packit df99a1
  : function_t(a,b,e)
Packit df99a1
{
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
macrofunction_t::call(miniexp_t args, miniexp_t env, bool)
Packit df99a1
{
Packit df99a1
  minivar_t nenv = this->env;
Packit df99a1
  match_args(this->args, args, nenv);
Packit df99a1
  minivar_t e = evaluate_progn(body, nenv);
Packit df99a1
  return evaluate(e, env);
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
macrofunction_t::funcdef(miniexp_t name)
Packit df99a1
{
Packit df99a1
  if (name)
Packit df99a1
    {
Packit df99a1
      miniexp_t d = miniexp_symbol("defmacro");
Packit df99a1
      miniexp_t a = miniexp_cons(name, args);
Packit df99a1
      return miniexp_cons(d, miniexp_cons(a, body));
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      miniexp_t d = miniexp_symbol("mlambda");
Packit df99a1
      return miniexp_cons(d, miniexp_cons(args, body));
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
/* ------------ define special forms */
Packit df99a1
Packit df99a1
DEFSPECIAL("progn",progn)
Packit df99a1
{
Packit df99a1
  return evaluate_progn(expr, env);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("list",list)
Packit df99a1
{
Packit df99a1
  return evaluate_list(expr, env);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("if",if)
Packit df99a1
{
Packit df99a1
  if (evaluate(miniexp_car(expr), env))
Packit df99a1
    return evaluate(miniexp_cadr(expr), env);
Packit df99a1
  return evaluate_progn(miniexp_cddr(expr), env);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("setq",setq)
Packit df99a1
{
Packit df99a1
  if (miniexp_cddr(expr) || !miniexp_consp(miniexp_cdr(expr)))
Packit df99a1
    error("setq: syntax error");
Packit df99a1
  miniexp_t a = lookup(miniexp_car(expr),env);
Packit df99a1
  if (! a)
Packit df99a1
    error ("setq: undefined variable", miniexp_car(expr));
Packit df99a1
  minivar_t v = evaluate(miniexp_cadr(expr), env);
Packit df99a1
  miniexp_rplacd(a,v);
Packit df99a1
  return v;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("defvar",defvar)
Packit df99a1
{
Packit df99a1
  if (miniexp_cddr(expr))
Packit df99a1
    error("defvar: syntax error");
Packit df99a1
  minivar_t v = evaluate(miniexp_cadr(expr), env);
Packit df99a1
  defvar(miniexp_car(expr), v);
Packit df99a1
  return miniexp_car(expr);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("let",let)
Packit df99a1
{
Packit df99a1
  miniexp_t v = miniexp_car(expr);
Packit df99a1
  minivar_t nenv = env;
Packit df99a1
  minivar_t p, w;
Packit df99a1
  while (miniexp_consp(v))
Packit df99a1
    {
Packit df99a1
      miniexp_t a = miniexp_car(v);
Packit df99a1
      v = miniexp_cdr(v);
Packit df99a1
      if (! (miniexp_consp(a) &&
Packit df99a1
	     miniexp_symbolp(miniexp_car(a)) &&
Packit df99a1
	     !miniexp_cddr(a)))
Packit df99a1
	error("let: syntax error");
Packit df99a1
      w = evaluate(miniexp_cadr(a), env);
Packit df99a1
      p = miniexp_cons(miniexp_car(a), w);
Packit df99a1
      nenv = miniexp_cons(p, nenv);
Packit df99a1
    }
Packit df99a1
  return evaluate_progn(miniexp_cdr(expr), nenv);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("letrec",letrec)
Packit df99a1
{
Packit df99a1
  miniexp_t v = miniexp_car(expr);
Packit df99a1
  minivar_t nenv = env;
Packit df99a1
  minivar_t p, w;
Packit df99a1
  while (miniexp_consp(v))
Packit df99a1
    {
Packit df99a1
      miniexp_t a = miniexp_car(v);
Packit df99a1
      v = miniexp_cdr(v);
Packit df99a1
      if (! (miniexp_consp(a) &&
Packit df99a1
	     miniexp_symbolp(miniexp_car(a)) &&
Packit df99a1
	     !miniexp_cddr(a)))
Packit df99a1
	error("let: syntax error");
Packit df99a1
      minivar_t p = miniexp_cons(miniexp_car(a), 0);
Packit df99a1
      nenv = miniexp_cons(p, nenv);
Packit df99a1
    }
Packit df99a1
  v = miniexp_car(expr);
Packit df99a1
  while (miniexp_consp(v))
Packit df99a1
    {
Packit df99a1
      miniexp_t a = miniexp_car(v);
Packit df99a1
      v = miniexp_cdr(v);
Packit df99a1
      w = evaluate(miniexp_cadr(a), nenv);
Packit df99a1
      p = lookup(miniexp_car(a), nenv);
Packit df99a1
      miniexp_rplacd(p,w);
Packit df99a1
    }
Packit df99a1
  return evaluate_progn(miniexp_cdr(expr), nenv);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("lambda",lambda)
Packit df99a1
{
Packit df99a1
  miniexp_t args = miniexp_car(expr);
Packit df99a1
  miniexp_t body = miniexp_cdr(expr);
Packit df99a1
  function_t *f = new function_t(args, body, env);
Packit df99a1
  return miniexp_object(f);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("mlambda",mlambda)
Packit df99a1
{
Packit df99a1
  miniexp_t args = miniexp_car(expr);
Packit df99a1
  miniexp_t body = miniexp_cdr(expr);
Packit df99a1
  function_t *f = new macrofunction_t(args, body, env);
Packit df99a1
  return miniexp_object(f);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("quote",quote)
Packit df99a1
{
Packit df99a1
  if (miniexp_cdr(expr))
Packit df99a1
    error("quote: syntax error");
Packit df99a1
  return miniexp_car(expr);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFSPECIAL("while",while)
Packit df99a1
{
Packit df99a1
  if (! miniexp_consp(expr))
Packit df99a1
    error("while: syntax error");
Packit df99a1
  minivar_t v;
Packit df99a1
  while (evaluate(miniexp_car(expr), env))
Packit df99a1
    v = evaluate_progn(miniexp_cdr(expr), env);
Packit df99a1
  return v;
Packit df99a1
}
Packit df99a1
Packit df99a1
/* ------------ define primitive */
Packit df99a1
Packit df99a1
DEFUN("nullp",nullp,1,0) {
Packit df99a1
  return (!argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("listp",listp,1,0) {
Packit df99a1
  return miniexp_listp(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("consp",consp,1,0) {
Packit df99a1
  return miniexp_consp(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("numberp",numberp,1,0) {
Packit df99a1
  return miniexp_numberp(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("doublep",doublep,1,0) {
Packit df99a1
  return miniexp_doublep(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("objectp",objectp,1,0) {
Packit df99a1
  return miniexp_objectp(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("symbolp",symbolp,1,0) {
Packit df99a1
  return miniexp_symbolp(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("stringp",stringp,1,0) {
Packit df99a1
  return miniexp_stringp(argv[0]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("classof",classof,1,0) {
Packit df99a1
  return miniexp_classof(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("car",car,1,0) {
Packit df99a1
  return miniexp_car(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("cdr",cdr,1,0) {
Packit df99a1
  return miniexp_cdr(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("caar",caar,1,0) {
Packit df99a1
  return miniexp_caar(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("cadr",cadr,1,0) {
Packit df99a1
  return miniexp_cadr(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("cdar",cdar,1,0) {
Packit df99a1
  return miniexp_cdar(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("cddr",cddr,1,0) {
Packit df99a1
  return miniexp_cddr(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("length",length,1,0) {
Packit df99a1
  return miniexp_number(miniexp_length(argv[0]));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("reverse",reverse,1,0) {
Packit df99a1
  return miniexp_reverse(argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("cons",cons,2,0) {
Packit df99a1
  return miniexp_cons(argv[0],argv[1]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("nth",nth,2,0) {
Packit df99a1
  if (! miniexp_numberp(argv[0]))
Packit df99a1
    error("nth: integer number expected");
Packit df99a1
  return miniexp_nth(miniexp_to_int(argv[0]), argv[1]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("rplaca",rplaca,2,0) {
Packit df99a1
  return miniexp_rplaca(argv[0],argv[1]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("rplacd",rplacd,2,0) {
Packit df99a1
  return miniexp_rplacd(argv[0],argv[1]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("abs",abs,1,0) {
Packit df99a1
  return miniexp_double(fabs(miniexp_to_double(argv[0])));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("+",plus,0,9999) {
Packit df99a1
  double s = 0;
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      if (!miniexp_doublep(argv[i]))
Packit df99a1
	error("+: number expected");
Packit df99a1
      s += miniexp_to_double(argv[i]);
Packit df99a1
    }
Packit df99a1
  return miniexp_double(s);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("*",times,0,9999) {
Packit df99a1
  double s = 1;
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      if (!miniexp_doublep(argv[i]))
Packit df99a1
	error("*: number expected");
Packit df99a1
      s *= miniexp_to_double(argv[i]);
Packit df99a1
    }
Packit df99a1
  return miniexp_double(s);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("-",minus,1,9999) {
Packit df99a1
  if (! miniexp_doublep(argv[0]))
Packit df99a1
    error("-: number expected");
Packit df99a1
  int i = 0;
Packit df99a1
  double s = 0;
Packit df99a1
  if (argc>1 && miniexp_doublep(argv[0]))
Packit df99a1
    s = miniexp_to_double(argv[i++]);
Packit df99a1
  while (i
Packit df99a1
    s -= miniexp_to_double(argv[i++]);
Packit df99a1
  if (i < argc)
Packit df99a1
    error("-: number expected", argv[i]);
Packit df99a1
  return miniexp_double(s);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("/",div,1,9999) {
Packit df99a1
  if (! miniexp_doublep(argv[0]))
Packit df99a1
    error("/: number expected");
Packit df99a1
  int i = 0;
Packit df99a1
  double s = 1;
Packit df99a1
  if (argc>1 && miniexp_doublep(argv[0]))
Packit df99a1
    s = miniexp_to_double(argv[i++]);
Packit df99a1
  while (i
Packit df99a1
    s /= miniexp_to_double(argv[i++]);
Packit df99a1
  if (i < argc)
Packit df99a1
    if (miniexp_doublep(argv[i]))
Packit df99a1
      error("/: division by zero", argv[i]);
Packit df99a1
    else
Packit df99a1
      error("/: number expected", argv[i]);
Packit df99a1
  return miniexp_double(s);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("==",equalequal,2,0) {
Packit df99a1
  return (argv[0]==argv[1]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
static bool
Packit df99a1
equal(miniexp_t a, miniexp_t b)
Packit df99a1
{
Packit df99a1
  if (a == b)
Packit df99a1
    return true;
Packit df99a1
  else if (miniexp_consp(a) && miniexp_consp(b))
Packit df99a1
    return equal(miniexp_car(a),miniexp_car(b))
Packit df99a1
      &&   equal(miniexp_cdr(a),miniexp_cdr(b));
Packit df99a1
  else if (miniexp_stringp(a) && miniexp_stringp(b))
Packit df99a1
    return !strcmp(miniexp_to_str(a), miniexp_to_str(b));
Packit df99a1
  else if (miniexp_doublep(a) && miniexp_doublep(b))
Packit df99a1
    return miniexp_to_double(a) == miniexp_to_double(b);
Packit df99a1
  return false;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("=",equal,2,0) {
Packit df99a1
  return equal(argv[0],argv[1]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("<>",notequal,2,0) {
Packit df99a1
  return !equal(argv[0],argv[1]) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
static int
Packit df99a1
compare(miniexp_t a, miniexp_t b)
Packit df99a1
{
Packit df99a1
  if (miniexp_doublep(a) && miniexp_doublep(b))
Packit df99a1
    {
Packit df99a1
      double na = miniexp_to_double(a);
Packit df99a1
      double nb = miniexp_to_double(b);
Packit df99a1
      if (na < nb)
Packit df99a1
	return -1;
Packit df99a1
      else if (na > nb)
Packit df99a1
	return 1;
Packit df99a1
      return 0;
Packit df99a1
    }
Packit df99a1
  else if (miniexp_stringp(a) && miniexp_stringp(b))
Packit df99a1
    {
Packit df99a1
      const char *sa = miniexp_to_str(a);
Packit df99a1
      const char *sb = miniexp_to_str(b);
Packit df99a1
      return strcmp(sa, sb);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    error("compare: cannot rank these arguments");
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("<=",cmple,2,0) {
Packit df99a1
  return (compare(argv[0],argv[1])<=0) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("<",cmplt,2,0) {
Packit df99a1
  return (compare(argv[0],argv[1])<0) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN(">=",cmpge,2,0) {
Packit df99a1
  return (compare(argv[0],argv[1])>=0) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN(">",cmpgt,2,0) {
Packit df99a1
  return (compare(argv[0],argv[1])>0) ? s_true : 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("floor",floor,1,0) {
Packit df99a1
  if (! miniexp_doublep(argv[0]))
Packit df99a1
    error("-: number expected");
Packit df99a1
  return miniexp_double(floor(miniexp_to_double(argv[0])));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("ceil",ceil,1,0) {
Packit df99a1
  if (! miniexp_doublep(argv[0]))
Packit df99a1
    error("-: number expected");
Packit df99a1
  return miniexp_double(ceil(miniexp_to_double(argv[0])));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("strlen",strlen,1,1) {
Packit df99a1
  if (! miniexp_stringp(argv[0]))
Packit df99a1
    error("strlen: string expected", argv[0]);
Packit df99a1
  const char *s = miniexp_to_str(argv[0]);
Packit df99a1
  return miniexp_number(strlen(s));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("substr",substr,2,1) {
Packit df99a1
  if (! miniexp_stringp(argv[0]))
Packit df99a1
    error("substr: string expected", argv[0]);
Packit df99a1
  const char *s = miniexp_to_str(argv[0]);
Packit df99a1
  int l = strlen(s);
Packit df99a1
  if (! miniexp_numberp(argv[1]))
Packit df99a1
    error("substr: integer number expected", argv[1]);
Packit df99a1
  int f = miniexp_to_double(argv[1]);
Packit df99a1
  f = (l < f) ? l : (f < 0) ? l : f;
Packit df99a1
  s += f;
Packit df99a1
  l -= f;
Packit df99a1
  if (argc>2)
Packit df99a1
    {
Packit df99a1
      if (! miniexp_numberp(argv[2]))
Packit df99a1
	error("substr: integer number expected", argv[2]);
Packit df99a1
      f = miniexp_to_double(argv[2]);
Packit df99a1
      l = (f > l) ? l : (f < 0) ? 0 : f;
Packit df99a1
    }
Packit df99a1
  return miniexp_substring(s,l);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("concat",concat,0,9999) {
Packit df99a1
  minivar_t l = 0;
Packit df99a1
  for (int i=0; i
Packit df99a1
    if (miniexp_stringp(argv[i]))
Packit df99a1
      l = miniexp_cons(argv[i],l);
Packit df99a1
    else
Packit df99a1
      error("concat: string expected", argv[i]);
Packit df99a1
  l = miniexp_reverse(l);
Packit df99a1
  return miniexp_concat(l);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("prin",prin,1,9999) {
Packit df99a1
  minivar_t v;
Packit df99a1
  v = miniexp_prin(argv[0]);
Packit df99a1
  for (int i=1; i
Packit df99a1
    {
Packit df99a1
      minilisp_puts(" ");
Packit df99a1
      v = miniexp_prin(argv[i]);
Packit df99a1
    }
Packit df99a1
  return v;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("print",print,1,9999) {
Packit df99a1
  minivar_t v;
Packit df99a1
  v = miniexp_prin(argv[0]);
Packit df99a1
  for (int i=1; i
Packit df99a1
    {
Packit df99a1
      minilisp_puts(" ");
Packit df99a1
      v = miniexp_prin(argv[i]);
Packit df99a1
    }
Packit df99a1
  minilisp_puts("\n");
Packit df99a1
  return v;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("pprint",pprint,1,1) {
Packit df99a1
  int w = 72;
Packit df99a1
  if (argc>1)
Packit df99a1
    {
Packit df99a1
      if (! miniexp_numberp(argv[1]))
Packit df99a1
	error("pprint: second argument must be number");
Packit df99a1
      w = miniexp_to_int(argv[1]);
Packit df99a1
    }
Packit df99a1
  return miniexp_pprint(argv[0], w);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("pname",pname,1,1) {
Packit df99a1
  int w = 0;
Packit df99a1
  if (argc > 1)
Packit df99a1
    {
Packit df99a1
      if (! miniexp_numberp(argv[1]))
Packit df99a1
	error("pprint: second argument must be number");
Packit df99a1
      w = miniexp_to_int(argv[1]);
Packit df99a1
    }
Packit df99a1
  return miniexp_pname(argv[0],w);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("gc",gc,0,0) {
Packit df99a1
  minilisp_gc();
Packit df99a1
  minilisp_info();
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("info",info,0,0) {
Packit df99a1
  minilisp_info();
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("funcdef",funcdef,1,1) {
Packit df99a1
  if (! miniexp_isa(argv[0], function_t::classname))
Packit df99a1
    error("funcdef: expecting function", argv[0]);
Packit df99a1
  if (argc>1 && ! miniexp_symbolp(argv[1]))
Packit df99a1
    error("funcdef: expecting symbol", argv[1]);
Packit df99a1
  function_t *f = (function_t*)miniexp_to_obj(argv[0]);
Packit df99a1
  return f->funcdef(argc>1 ? argv[1] : 0);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("vardef",vardef,1,0) {
Packit df99a1
  miniexp_t a = lookup(argv[0],globalenv);
Packit df99a1
  if (! a)
Packit df99a1
    error("vardef: undefined global variable");
Packit df99a1
  return miniexp_cdr(a);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("eval",eval,1,0) {
Packit df99a1
  return evaluate(argv[0],env);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("apply",apply,2,0) {
Packit df99a1
  miniobj_t *obj = miniexp_to_obj(argv[0]);
Packit df99a1
  if (obj && obj->isa(callable_t::classname))
Packit df99a1
    return ((callable_t*)obj)->call(argv[1], env, true);
Packit df99a1
  error("apply: cannot apply this object", argv[0]);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("error",error,1,1) {
Packit df99a1
  if (!miniexp_stringp(argv[0]))
Packit df99a1
    error("error: string expected", argv[0]);
Packit df99a1
  error(miniexp_to_str(argv[0]), (argc>1) ? argv[1] : 0);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("display",display,0,9999) {
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      minivar_t v = argv[i];
Packit df99a1
      if (! miniexp_stringp(v)) 
Packit df99a1
        v = miniexp_pname(v, 0);
Packit df99a1
      minilisp_puts(miniexp_to_str(v));
Packit df99a1
    }
Packit df99a1
  return 0;
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("string->symbol",string2symbol,1,0) {
Packit df99a1
  if (! miniexp_stringp(argv[0]))
Packit df99a1
    error("string->symbol: string expected",argv[0]);
Packit df99a1
  return miniexp_symbol(miniexp_to_str(argv[0]));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("symbol->string",symbol2string,1,0) {
Packit df99a1
  if (! miniexp_symbolp(argv[0]))
Packit df99a1
    error("symbol->string: symbol expected",argv[0]);
Packit df99a1
  return miniexp_string(miniexp_to_name(argv[0]));
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("printflags",printflags,1,0) {
Packit df99a1
  if (! miniexp_numberp(argv[0]))
Packit df99a1
    error("printflags: integer number expected");
Packit df99a1
  minilisp_print_7bits = miniexp_to_int(argv[0]);
Packit df99a1
  return argv[0];
Packit df99a1
}
Packit df99a1
Packit df99a1
/* ------------ special */
Packit df99a1
Packit df99a1
#if defined(_WIN32) || defined(__WIN64)
Packit df99a1
# include <process.h>
Packit df99a1
Packit df99a1
class thread_t : public miniobj_t
Packit df99a1
{
Packit df99a1
  MINIOBJ_DECLARE(thread_t, miniobj_t, "thread");
Packit df99a1
private:
Packit df99a1
  uintptr_t thr;
Packit df99a1
  miniexp_t exp, env, res, run;
Packit df99a1
  static void start(void *arg) {
Packit df99a1
    thread_t *pth = (thread_t*) arg;
Packit df99a1
    try { 
Packit df99a1
      pth->res = evaluate(pth->exp, pth->env); 
Packit df99a1
      pth->run = miniexp_symbol("finished");
Packit df99a1
    } catch(...) { 
Packit df99a1
      pth->run = miniexp_symbol("error");
Packit df99a1
    } }
Packit df99a1
public:
Packit df99a1
  thread_t(miniexp_t exp, miniexp_t env) : exp(exp), env(env), res(0), run(0) { 
Packit df99a1
    thr = _beginthread(thread_t::start, 0, (void*)this); }
Packit df99a1
  void mark(minilisp_mark_t action) {
Packit df99a1
    action(&exp); action(&env), action(&res;; }
Packit df99a1
  miniexp_t join() {
Packit df99a1
    return (run) ? res : miniexp_dummy; }
Packit df99a1
  miniexp_t status() { return run; }
Packit df99a1
  ~thread_t() { if (!run) abort(); join(); }
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(thread_t, miniobj_t, "thread");
Packit df99a1
Packit df99a1
DEFUN("thread",threadstart,1,0) {
Packit df99a1
  return miniexp_object(new thread_t(argv[0],env));
Packit df99a1
}
Packit df99a1
DEFUN("threadp", threadtest,1,0) {
Packit df99a1
  if (! miniexp_isa(argv[0], thread_t::classname)) return 0;
Packit df99a1
  miniexp_t run = ((thread_t*)miniexp_to_obj(argv[0]))->status();
Packit df99a1
  return (run) ? run : miniexp_symbol("running");
Packit df99a1
}
Packit df99a1
DEFUN("join",threadjoin,1,0) {
Packit df99a1
  if (! miniexp_isa(argv[0], thread_t::classname))
Packit df99a1
    error("join: thread expected");
Packit df99a1
  return ((thread_t*)miniexp_to_obj(argv[0]))->join();
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#ifdef HAVE_PTHREAD
Packit df99a1
# include <pthread.h>
Packit df99a1
Packit df99a1
class thread_t : public miniobj_t
Packit df99a1
{
Packit df99a1
  MINIOBJ_DECLARE(thread_t, miniobj_t, "thread");
Packit df99a1
private:
Packit df99a1
  pthread_t thr;
Packit df99a1
  miniexp_t exp, env, res, run;
Packit df99a1
  bool joined;
Packit df99a1
  static void* start(void *arg) {
Packit df99a1
    thread_t *pth = (thread_t*) arg;
Packit df99a1
    try { 
Packit df99a1
      pth->res = evaluate(pth->exp, pth->env); 
Packit df99a1
      pth->run = miniexp_symbol("finished");
Packit df99a1
      return 0; } 
Packit df99a1
    catch(...) { 
Packit df99a1
      pth->run = miniexp_symbol("error");
Packit df99a1
      return (void*)1; } }
Packit df99a1
public:
Packit df99a1
  thread_t(miniexp_t exp, miniexp_t env) 
Packit df99a1
    : exp(exp), env(env), res(0), run(0), joined(false) { 
Packit df99a1
    pthread_create(&this->thr, 0, thread_t::start, (void*)this); }
Packit df99a1
  void mark(minilisp_mark_t action) {
Packit df99a1
    action(&exp); action(&env), action(&res;; }
Packit df99a1
  miniexp_t join() {
Packit df99a1
    if (! joined) pthread_join(thr, 0); joined=true;
Packit df99a1
    return (run) ? res : miniexp_dummy; }
Packit df99a1
  miniexp_t status() { return run; }
Packit df99a1
  ~thread_t() { if (!run) abort(); join(); }
Packit df99a1
};
Packit df99a1
Packit df99a1
MINIOBJ_IMPLEMENT(thread_t, miniobj_t, "thread");
Packit df99a1
Packit df99a1
DEFUN("thread",threadstart,1,0) {
Packit df99a1
  return miniexp_object(new thread_t(argv[0],env));
Packit df99a1
}
Packit df99a1
DEFUN("threadp", threadtest,1,0) {
Packit df99a1
  if (! miniexp_isa(argv[0], thread_t::classname)) return 0;
Packit df99a1
  miniexp_t run = ((thread_t*)miniexp_to_obj(argv[0]))->status();
Packit df99a1
  return (run) ? run : miniexp_symbol("running");
Packit df99a1
}
Packit df99a1
DEFUN("join",threadjoin,1,0) {
Packit df99a1
  if (! miniexp_isa(argv[0], thread_t::classname))
Packit df99a1
    error("join: thread expected");
Packit df99a1
  return ((thread_t*)miniexp_to_obj(argv[0]))->join();
Packit df99a1
}
Packit df99a1
Packit df99a1
#endif
Packit df99a1
Packit df99a1
Packit df99a1
/* ------------ toplevel */
Packit df99a1
Packit df99a1
void
Packit df99a1
toplevel(FILE *inp, FILE *out, bool print)
Packit df99a1
{
Packit df99a1
  miniexp_io_t saved_io = miniexp_io;
Packit df99a1
  minilisp_set_output(out);
Packit df99a1
  minilisp_set_input(inp);
Packit df99a1
  for(;;)
Packit df99a1
    {
Packit df99a1
      minivar_t s = miniexp_read();
Packit df99a1
      if (s == miniexp_dummy)
Packit df99a1
	{
Packit df99a1
          if (feof(inp)) break;
Packit df99a1
          printf("ERROR: while parsing\n");
Packit df99a1
	  break;
Packit df99a1
	}
Packit df99a1
      try
Packit df99a1
	{
Packit df99a1
	  break_request = false;
Packit df99a1
	  minivar_t v = evaluate(s, globalenv);
Packit df99a1
	  if (print)
Packit df99a1
	    {
Packit df99a1
	      printf("= ");
Packit df99a1
	      miniexp_print(v);
Packit df99a1
	    }
Packit df99a1
	}
Packit df99a1
      catch(...)
Packit df99a1
	{
Packit df99a1
	}
Packit df99a1
    }
Packit df99a1
  miniexp_io = saved_io;
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
parse_comment(void)
Packit df99a1
{
Packit df99a1
  int c = minilisp_getc();
Packit df99a1
  while (c != EOF && c != '\n')
Packit df99a1
    c = minilisp_getc();
Packit df99a1
  return miniexp_nil;
Packit df99a1
}
Packit df99a1
Packit df99a1
miniexp_t
Packit df99a1
parse_quote(void)
Packit df99a1
{
Packit df99a1
  minivar_t l = miniexp_read();
Packit df99a1
  if (l == miniexp_dummy)
Packit df99a1
    return miniexp_dummy;
Packit df99a1
  l = miniexp_cons(s_quote, miniexp_cons(l, miniexp_nil));
Packit df99a1
  return miniexp_cons(l,miniexp_nil);
Packit df99a1
}
Packit df99a1
Packit df99a1
static void
Packit df99a1
sighandler(int signo)
Packit df99a1
{
Packit df99a1
  break_request = true;
Packit df99a1
  signal(signo, sighandler);
Packit df99a1
}
Packit df99a1
Packit df99a1
DEFUN("load",xload,1,0) {
Packit df99a1
  if (! miniexp_stringp(argv[0]))
Packit df99a1
    error("load: string expected");
Packit df99a1
  FILE *f = fopen(miniexp_to_str(argv[0]), "r");
Packit df99a1
  if (! f)
Packit df99a1
    error("load: cannot open file");
Packit df99a1
  toplevel(f, stdout, false);
Packit df99a1
  fclose(f);
Packit df99a1
  return miniexp_nil;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
/* ------------ toplevel */
Packit df99a1
Packit df99a1
int
Packit df99a1
main()
Packit df99a1
{
Packit df99a1
#ifdef DEBUG
Packit df99a1
  minilisp_debug(1);
Packit df99a1
#endif
Packit df99a1
  minilisp_macrochar_parser[(int)';'] = parse_comment;
Packit df99a1
  minilisp_macrochar_parser[(int)'\''] = parse_quote;
Packit df99a1
  FILE *f = fopen("minilisp.in","r");
Packit df99a1
  if (f) {
Packit df99a1
    toplevel(f, stdout, false);
Packit df99a1
    fclose(f);
Packit df99a1
  } else
Packit df99a1
    printf("WARNING: cannot find 'minilisp.in'\n");
Packit df99a1
  signal(SIGINT, sighandler);
Packit df99a1
  while (! feof(stdin))
Packit df99a1
    toplevel(stdin, stdout, true);
Packit df99a1
  break_request = true;
Packit df99a1
  minilisp_finish();
Packit df99a1
  return 0;
Packit df99a1
}