美文网首页
https://github.com/janet-lang/ja

https://github.com/janet-lang/ja

作者: onedam | 来源:发表于2020-05-13 14:16 被阅读0次
/* lysp.c -- LYSP: commemorating 50 Years of Symbolic Processing
**         (no relation to the long-deceased dialect from IBM)
**
** Copyright (c) 2008 Ian Piumarta
** All Rights Reserved
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the 'Software'),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, provided that the above copyright notice(s) and this
** permission notice appear in all copies of the Software.  Inclusion of the
** the above copyright notice(s) and this permission notice in supporting
** documentation would be appreciated but is not required.
**
** THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.
**
** Last edited: 2012-01-12 15:44:18 by piumarta on vps2.piumarta.com
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include <sys/errno.h>
#include <assert.h>

#ifndef BDWGC
# error you did neither -DBDWGC=0 nor -DBDWGC=1 in the compilation command
#endif

#if BDWGC
# include <gc/gc.h>
# define GC_PROTECT(X)
# define GC_UNPROTECT(X)
#else
# include "gc.h"
#endif
#define balloc  GC_malloc_atomic
#define malloc  GC_malloc

static void fatal(const char *fmt, ...)
{
  va_list ap;
  va_start(ap, fmt);
  fprintf(stderr, "\nError: ");
  vfprintf(stderr, fmt, ap);
  fprintf(stderr, "\n");
  va_end(ap);
  exit(1);
}

typedef enum { None, Number, String, Symbol, Cons, Subr, Fsubr, Expr, Fexpr, Psubr } Tag;

struct _Cell;
typedef struct _Cell Cell;

typedef Cell *(*Subr_t)(Cell *args, Cell *env);

Cell *apply(Cell *fn, Cell *args, Cell *env);

struct _Cell
{
  Tag        mTag;
  union {
    long     mNumber;
    const char  *mString;
    const char  *mSymbol;
    struct {
      Cell  *a;
      Cell  *d;
    }        mCons;
    Subr_t   mSubr;
    struct {
      Cell  *expr;
      Cell  *env;
    }        mExpr;
  };
};

Cell *mkNumber(long n)      { Cell *self= balloc(sizeof(Cell));  self->mTag= Number;  self->mNumber= n;             return self; }
Cell *mkString(const char *s)   { Cell *self= balloc(sizeof(Cell));  self->mTag= String;  self->mString= s;             return self; }
Cell *mkSymbol(const char *s)   { Cell *self= balloc(sizeof(Cell));  self->mTag= Symbol;  self->mString= s;             return self; }
Cell *cons(Cell *a, Cell *d)    { Cell *self= malloc(sizeof(Cell));  self->mTag= Cons;    self->mCons.a= a;     self->mCons.d= d;   return self; }
Cell *mkSubr(Subr_t fn)     { Cell *self= balloc(sizeof(Cell));  self->mTag= Subr;    self->mSubr= fn;              return self; }
Cell *mkFsubr(Subr_t fn)    { Cell *self= balloc(sizeof(Cell));  self->mTag= Fsubr;   self->mSubr= fn;              return self; }
Cell *mkExpr(Cell *x, Cell *e)  { Cell *self= malloc(sizeof(Cell));  self->mTag= Expr;    self->mExpr.expr= x;  self->mExpr.env= e; return self; }
Cell *mkFexpr(Cell *x, Cell *e) { Cell *self= malloc(sizeof(Cell));  self->mTag= Fexpr;   self->mExpr.expr= x;  self->mExpr.env= e; return self; }
Cell *mkPsubr(Subr_t fn)    { Cell *self= balloc(sizeof(Cell));  self->mTag= Psubr;   self->mSubr= fn;              return self; }

int nilP(Cell *self)        { return !self; }
int numberP(Cell *self)     { return self && self->mTag == Number; }
int stringP(Cell *self)     { return self && self->mTag == String; }
int symbolP(Cell *self)     { return self && self->mTag == Symbol; }
int consP(Cell *self)       { return self && self->mTag == Cons; }
int subrP(Cell *self)       { return self && self->mTag == Subr; }
int fsubrP(Cell *self)      { return self && self->mTag == Fsubr; }
int exprP(Cell *self)       { return self && self->mTag == Expr; }
int fexprP(Cell *self)      { return self && self->mTag == Fexpr; }
int psubrP(Cell *self)      { return self && self->mTag == Psubr; }

#ifndef NDEBUG
# define require(X) assert(X)
#else
# define require(X) if (!(X)) return 0
#endif

long        number(Cell *self)      { require(numberP(self));  return self->mNumber; }
const char *string(Cell *self)      { require(stringP(self));  return self->mString; }
const char *symbol(Cell *self)      { require(symbolP(self));  return self->mSymbol; }
Subr_t      subr(Cell *self)        { require(subrP(self));    return self->mSubr; }
Subr_t      fsubr(Cell *self)       { require(fsubrP(self));   return self->mSubr; }
Cell       *expr(Cell *self)        { require(exprP(self));    return self->mExpr.expr; }
Cell       *exprenv(Cell *self)     { require(exprP(self));    return self->mExpr.env; }
Cell       *fexpr(Cell *self)       { require(fexprP(self));   return self->mExpr.expr; }
Cell       *fexprenv(Cell *self)    { require(fexprP(self));   return self->mExpr.env; }
Subr_t      psubr(Cell *self)       { require(psubrP(self));   return self->mSubr; }

Cell *car(Cell *self)           { require(!self || consP(self));  return self ? self->mCons.a    : 0; }
Cell *cdr(Cell *self)           { require(!self || consP(self));  return self ? self->mCons.d    : 0; }
Cell *rplaca(Cell *self, Cell *c)   { require(!self || consP(self));  return self ? self->mCons.a= c : c; }
Cell *rplacd(Cell *self, Cell *c)   { require(!self || consP(self));  return self ? self->mCons.d= c : c; }

#undef require

Cell *caar  (Cell *self)        { return car(car(self)); }
Cell *cadr  (Cell *self)        { return car(cdr(self)); }
Cell *cdar  (Cell *self)        { return cdr(car(self)); }
Cell *caddr (Cell *self)        { return car(cdr(cdr(self))); }
Cell *cadar (Cell *self)        { return car(cdr(car(self))); }

Cell *interns= 0;

Cell *intern(const char *s)
{
  Cell *cell= 0;
  for (cell= interns;  cell;  cell= cdr(cell))
    if (!strcmp(symbol(car(cell)), s))
      return car(cell);
  cell= mkSymbol(strdup(s));
  GC_PROTECT(cell);
  interns= cons(cell, interns);
  GC_UNPROTECT(cell);
  return car(interns);
}

Cell *assq(Cell *key, Cell *list)
{
  for (; list;  list= cdr(list))
    if (key == caar(list)) return car(list);
  return 0;
}

Cell *print(Cell *self, FILE *stream)
{
  if (!self) fprintf(stream, "nil");
  else
    switch (self->mTag) {
    case Number:    fprintf(stream, "%ld",        number(self));                    break;
    case String:    fprintf(stream, "\"%s\"",     string(self));                    break;
    case Symbol:    fprintf(stream, "%s",         symbol(self));                    break;
    case Subr:      fprintf(stream, "subr<%p>",   subr(self));                  break;
    case Fsubr:     fprintf(stream, "fsubr<%p>",  fsubr(self));                 break;
    case Expr:      fprintf(stream, "(lambda ");  print(expr(self), stream);  fprintf(stream, ")"); break;
    case Fexpr:     fprintf(stream, "(flambda "); print(fexpr(self), stream); fprintf(stream, ")"); break;
    case Psubr:     fprintf(stream, "psubr<%p>",  psubr(self));         break;
    case Cons: {
      fprintf(stream, "(");
      while (self && consP(self)) {
    print(car(self), stream);
    if ((self= cdr(self))) fputc(' ', stream);
      }
      if (self) {
    fprintf(stream, ". ");
    print(self, stream);
      }
      fprintf(stream, ")");
      break;
    }
    default:
      fprintf(stream, "?%p", self);
      break;
    }
  return self;
}

Cell *println(Cell *self, FILE *stream)
{
  print(self, stream);
  fprintf(stream, "\n");
  return self;
}

Cell *_S_t   = 0;
Cell *_S_quote   = 0;
Cell *_S_qquote  = 0;
Cell *_S_uquote  = 0;
Cell *_S_uquotes = 0;
Cell *syntaxTable= 0;
Cell *globals= 0;

typedef Cell *(*Reader)(int, FILE *);

Cell *readFile(FILE *in);
Cell *readAlpha(int c, FILE *in);
Cell *readSign(int c, FILE *in);

Reader readers[256];

#define CEOF    ((Cell *)-1)

Cell *readIllegal(int c, FILE *in)
{
  fprintf(stderr, "ignoring illegal character ");
  fprintf(stderr, (isprint(c) ? "%c" : "0x%02x"), c);
  fprintf(stderr, "\n");
  return 0;
}

Cell *readBlank(int c, FILE *in)
{
  return 0;
}

Cell *readDigit(int c, FILE *in)
{
  char buf[1024];
  int index= 0;
  char *endptr;
  long number= 0;
  buf[index++]= c;
  if ('0' == c) {
    if (strchr("xX", (c= getc(in))))    buf[index++]= c;
    else                ungetc(c, in);
  }
  while ((c= getc(in)) > 0 && (readDigit == readers[c] || readAlpha == readers[c])) buf[index++]= c;
  ungetc(c, in);
  buf[index]= '\0';
  errno= 0;
  number= strtol(buf, &endptr, 0);
  if ((ERANGE == errno) || (errno && !number)) perror(buf);
  if (*endptr != '\0') fprintf(stderr, "%s: invalid digits in number\n", buf);
  return mkNumber(number);
}

Cell *readAlpha(int c, FILE *in)
{
  char buf[1024];
  int index= 0;
  buf[index++]= c;
  while ((c= getc(in)) > 0 && (readAlpha == readers[c] || readDigit == readers[c] || readSign == readers[c])) buf[index++]= c;
  ungetc(c, in);
  buf[index]= '\0';
  return intern(buf);
}

Cell *readSign(int c, FILE *in)
{
  int d= getc(in);
  ungetc(d, in);
  return (d > 0 && readers[d] == readDigit) ? readDigit(c, in) : readAlpha(c, in);
}

Cell *readString(int d, FILE *in)
{
  char buf[1024];
  int index= 0;
  int c;
  while ((c= getc(in)) > 0 && c != d) if ('\\' == (buf[index++]= c)) buf[index++]= getc(in);
  if (c != d) fatal("EOF in string");
  buf[index]= '\0';
  return mkString(strdup(buf));
}

Cell *readQuote(int c, FILE *in)
{
  Cell *cell= readFile(in);
  if (CEOF == cell) fatal("EOF in quoted literal");
  GC_PROTECT(cell);
  cell= cons(cell, 0);
  cell= cons(_S_quote, cell);
  GC_UNPROTECT(cell);
  return cell;
}

Cell *readQquote(int c, FILE *in)
{
  Cell *cell= readFile(in);
  if (CEOF == cell) fatal("EOF in quasiquoted literal");
  GC_PROTECT(cell);
  cell= cons(cell, 0);
  cell= cons(_S_qquote, cell);
  GC_UNPROTECT(cell);
  return cell;
}

Cell *readUquote(int c, FILE *in)
{
  int splice= 0;
  if ('@' == (c= getc(in))) splice= 1;
  else ungetc(c, in);
  Cell *cell= readFile(in);
  if (CEOF == cell) fatal("EOF in quasiquoted literal");
  GC_PROTECT(cell);
  cell= cons(cell, 0);
  cell= cons((splice ? _S_uquotes : _S_uquote), cell);
  GC_UNPROTECT(cell);
  return cell;
}

Cell *readList(int d, FILE *in)
{
  Cell *head, *tail, *cell= 0;
  tail= head= cons(0, 0);
  GC_PROTECT(head);
  GC_PROTECT(cell);
  switch (d) {
  case '(': d= ')'; break;
  case '[': d= ']'; break;
  case '{': d= '}'; break;
  }
  int c;
  for (;;) {
    while (isspace((c= getc(in))));
    if (c == d) break;
    if (c == ')' || c == ']' || c == '}') fatal("mismatched parentheses");
    if (c == '.')
      rplacd(tail, readFile(in));
    else {
      ungetc(c, in);
      cell= readFile(in);
      if (feof(in)) fatal("EOF in list");
      tail= rplacd(tail, cons(cell, 0));
    }
  }
  head= cdr(head);
  if (head && symbolP(car(head))) {
    Cell *syntax= assq(car(head), cdr(syntaxTable));
    if (syntax) head= apply(cdr(syntax), cdr(head), globals);
    if (!head) {
      GC_UNPROTECT(head);
      return 0;
    }
  }
  GC_UNPROTECT(head);
  return head ? head : (Cell *)-1;
}

Cell *readSemi(int c, FILE *in)
{
  while ((c= getc(in)) && (c != '\n') && (c != '\r'));
  return 0;
}

Cell *readFile(FILE *in)
{
  int c;
  Cell *cell;
  do {
    while (isspace(c= getc(in)));
    if (c < 0) return (Cell *)-1;
    cell= readers[c](c, in);
  } while (!cell);
  if (cell == (Cell *)-1) cell= 0;
  return cell;
}

static void initReaders(Reader r, const char *chars)
{
  while (*chars) readers[(int)*chars++]= r;
}

Cell *undefined(Cell *sym)
{
  fprintf(stderr, "undefined: %s\n", symbol(sym));
  return 0;
}

Cell *eval(Cell *expr, Cell *env);

Cell *evargs(Cell *self, Cell *env)
{
  if (self) {
    Cell *head, *tail;
    head= eval(car(self), env);
    GC_PROTECT(head);
    tail= evargs(cdr(self), env);
    GC_PROTECT(tail);
    head= cons(head, tail);
    GC_UNPROTECT(head);
    return head;
  }
  return 0;
}

Cell *evbind(Cell *expr, Cell *args, Cell *env)
{
  Cell *cell= 0;
  GC_PROTECT(env);
  GC_PROTECT(cell);
  if (consP(expr))
    for (;  expr;  expr= cdr(expr), args= cdr(args)) {
      cell= cons(car(expr), car(args));
      env= cons(cell, env);
    }
  else {
    cell= cons(expr, args);
    env= cons(cell, env);
  }
  GC_UNPROTECT(env);
  return env;
}

Cell *evlist(Cell *expr, Cell *env)
{
  Cell *result= 0;
  GC_PROTECT(expr);
  GC_PROTECT(env);
  GC_PROTECT(result);
  for (;  expr;  expr= cdr(expr)) result= eval(car(expr), env);
  GC_UNPROTECT(expr);
  return result;
}

typedef void (*apply_t)(void);
typedef union { char *argp; } *arglist_t;

long primcall(apply_t fn, arglist_t args, int size)
{
  void *ret= __builtin_apply(fn, args, size);
  __builtin_return(ret);
}

void *cellToPrim(Cell *cell)
{
  switch (cell->mTag) {
  case Cons:  case Expr:  case Fexpr:   return (void *)cell;
  default:              return (void *)cell->mCons.a;
  }
}

Cell *apply(Cell *fn, Cell *args, Cell *env)
{
  GC_PROTECT(fn);
  GC_PROTECT(args);
  GC_PROTECT(env);
  if (fn)
    switch (fn->mTag) {
    case Subr:  return subr(fn)(evargs(args, env), env);
    case Fsubr: return fsubr(fn)(args, env);
    case Expr:  {
      Cell *eva= evargs(args, env);
      GC_PROTECT(eva);
      eva= evlist(cdr(expr(fn)), evbind(car(expr(fn)), eva, exprenv(fn)));
      GC_UNPROTECT(fn);
      return eva;
    }
    case Fexpr: {
      Cell *eva= cons(env, 0);
      GC_PROTECT(eva);
      eva= cons(args, eva);
      eva= evlist(cdr(fexpr(fn)), evbind(car(fexpr(fn)), eva, fexprenv(fn)));
      GC_UNPROTECT(fn);
      return eva;
    }
    case Psubr: {
      void *argv[32];   /* fixme: count the args, then alloca() */
      int i;
      for (i= 1;  args;  args= cdr(args), ++i) argv[i]= cellToPrim(eval(car(args), env));
      argv[0]= &argv[1];
      return mkNumber(primcall((apply_t)psubr(fn), (void*)argv, sizeof(void *) * i));
    }
    default:    break;
    }
  fprintf(stderr, "cannot apply: ");
  println(fn, stderr);
  return 0;
}

Cell *eval(Cell *expr, Cell *env)
{
  if (!expr) return 0;
  switch (expr->mTag) {
  case Number:  case String:  case Subr:  case Fsubr:  case Expr: {
    return expr;
  }
  case Symbol: {
    Cell *cell= assq(expr, env);
    if (!cell) return undefined(expr);
    return cdr(cell);
  }
  case Cons: {
    Cell *cell;
    GC_PROTECT(expr);
    GC_PROTECT(env);
    cell= eval(car(expr), env);
    GC_PROTECT(cell);
    cell= apply(cell, cdr(expr), env);
    GC_UNPROTECT(expr);
    return cell;
  }
  default:
    fatal("unknown tag");
  }
  return 0;
}

Cell *defineFsubr(Cell *args, Cell *env)
{
  Cell *cell= 0;
  GC_PROTECT(args);
  GC_PROTECT(env);
  if (args) {
    cell= cons(car(args), 0);
    GC_PROTECT(cell);
    rplacd(globals, cons(cell, cdr(globals)));
    cell= rplacd(cell, eval(cadr(args), env));
  }
  GC_UNPROTECT(args);
  return cell;
}

Cell *setqFsubr(Cell *args, Cell *env)
{
  Cell *key, *value= 0;
  GC_PROTECT(args);
  GC_PROTECT(env);
  key= car(args);
  if (symbolP(key)) {
    Cell *cell;
    value= eval(cadr(args), env);
    GC_PROTECT(value);
    cell= assq(key, env);
    if (!cell) {
      GC_UNPROTECT(args);
      return undefined(key);
    }
    rplacd(cell, value);
  }
  GC_UNPROTECT(args);
  return value;
}

Cell *lambdaFsubr(Cell *args, Cell *env)
{
  return mkExpr(args, env);
}

Cell *flambdaFsubr(Cell *args, Cell *env)
{
  return mkFexpr(args, env);
}

Cell *letFsubr(Cell *args, Cell *env)
{
  Cell *cell, *tmp= 0;
  GC_PROTECT(args);
  GC_PROTECT(env);
  GC_PROTECT(tmp);
  for (cell= car(args);  cell;  cell= cdr(cell)) {
    tmp= eval(cadar(cell), env);
    tmp= cons(caar(cell), tmp);
    env= cons(tmp, env);
  }
  GC_UNPROTECT(args);
  return evlist(cdr(args), env);
}

Cell *orFsubr(Cell *args, Cell *env)
{
  Cell *value;
  GC_PROTECT(args);
  GC_PROTECT(env);
  for (value= 0;  args && !value;  args= cdr(args))
    value= eval(car(args), env);
  GC_UNPROTECT(args);
  return value;
}

Cell *andFsubr(Cell *args, Cell *env)
{
  Cell *value;
  GC_PROTECT(args);
  GC_PROTECT(env);
  for (value= _S_t;  args && value;  args= cdr(args))
    value= eval(car(args), env);
  GC_UNPROTECT(args);
  return value;
}

Cell *ifFsubr(Cell *args, Cell *env)
{
  Cell *cell;
  GC_PROTECT(args);
  GC_PROTECT(env);
  cell= (eval(car(args), env) ? eval(cadr (args), env) : eval(caddr(args), env));
  GC_UNPROTECT(args);
  return cell;
}

Cell *whileFsubr(Cell *args, Cell *env)
{
  Cell *result= 0;
  GC_PROTECT(args);
  GC_PROTECT(env);
  GC_PROTECT(result);
  while (eval(car(args), env)) result= evlist(cdr(args), env);
  GC_UNPROTECT(args);
  return result;
}

Cell *mapArgs(Cell *args)
{
  Cell *arg, *tail;
  if (!args) return 0;
  arg= caar(args);
  GC_PROTECT(args);
  GC_PROTECT(arg);
  rplaca(args, cdar(args));
  tail= mapArgs(cdr(args));
  arg= cons(arg, tail);
  GC_UNPROTECT(args);
  return arg;
}

Cell *mapSubr(Cell *args, Cell *env)
{
  Cell *fn= car(args), *head, *tail, *cell= 0;
  GC_PROTECT(args);
  GC_PROTECT(env);
  GC_PROTECT(cell);
  tail= head= cons(0, 0);
  args= cdr(args);
  while (car(args)) {
    cell= mapArgs(args);
    cell= apply(fn, cell, env);
    tail= rplacd(tail, cons(cell, 0));
  }
  GC_UNPROTECT(args);
  return cdr(head);
}

Cell *evalSubr(Cell *args, Cell *env)
{
  Cell *evalArg= car(args);
  Cell *evalEnv= cadr(args);
  GC_PROTECT(args);
  GC_PROTECT(env);
  evalArg= eval(evalArg, evalEnv ? evalEnv : env);
  GC_UNPROTECT(args);
  return evalArg;
}

Cell *applySubr(Cell *args, Cell *env)  { return apply(car(args), cdr(args), env); }
Cell *consSubr(Cell *args, Cell *env)   { return cons(car(args), cadr(args)); }
Cell *rplacaSubr(Cell *args, Cell *env) { return rplaca(car(args), cadr(args)); }
Cell *rplacdSubr(Cell *args, Cell *env) { return rplacd(car(args), cadr(args)); }
Cell *carSubr(Cell *args, Cell *env)    { return caar(args); }
Cell *cdrSubr(Cell *args, Cell *env)    { return cdar(args); }
Cell *assqSubr(Cell *args, Cell *env)   { return assq(car(args), cadr(args)); }

Cell *printlnSubr(Cell *args, Cell *env)
{
  for (;  args;  args= cdr(args)) {
    print(car(args), stdout);
    if (cdr(args)) putchar(' ');
  }
  putchar('\n');
  return 0;
}

#define arithmetic(name, id, op)            \
Cell *name##Subr(Cell *args, Cell *env)         \
{                           \
  if (cdr(args)) {                  \
    long n= number(car(args));              \
    for (args= cdr(args);  args;  args= cdr(args))  \
      n op##= number(car(args));            \
    return mkNumber(n);                 \
  }                         \
  return mkNumber(id op number(car(args)));     \
}

arithmetic(add,     0, +)
arithmetic(subtract,    0, -)
arithmetic(multiply,    1, *)
arithmetic(divide,  1, /)
arithmetic(modulus, 1, %)

#undef arithmetic

#define relation(name, op)                  \
Cell *name##Subr(Cell *args, Cell *env)             \
{                               \
  Cell *numbers;                        \
  for (numbers= args;  cdr(numbers);  numbers= cdr(numbers))    \
    if (!(number(car(numbers)) op number(cadr(numbers))))   \
      return 0;                         \
  return args;                          \
}

relation(less,      < )
relation(lessEqual, <=)
relation(equal,     ==)
relation(notEqual,  !=)
relation(greaterEqual,  >=)
relation(greater,   > )

#undef relation

int numbersP2(Cell *args)   { return numberP(car(args)) && numberP(cadr(args)); }
int numbersP3(Cell *args)   { return numberP(car(args)) && numberP(cadr(args)) && numberP(caddr(args)); }

Cell *primToStringSubr(Cell *args)  { return numberP(car(args)) ? mkString(strdup((char *)number(car(args)))) : 0; }

typedef void *ptr;

#define access(type)                                                                                \
  Cell *type##PeekSubr(Cell *args, Cell *env)   { return numbersP2(args) ? mkNumber((long)((type *)number(car(args)))[number(cadr(args))]) : 0; }               \
  Cell *type##PokeSubr(Cell *args, Cell *env)   { if (numbersP3(args)) ((type *)number(car(args)))[number(cadr(args))]= (type)number(caddr(args));  return caddr(args); }

access(char)
access(short)
access(int)
access(long)
access(ptr)

#undef access

#include <dlfcn.h>

void *rtldDefault= 0;

Cell *dlsymSubr(Cell *args, Cell *env)  { return stringP(car(args)) ? mkPsubr(dlsym(rtldDefault, string(car(args)))) : 0; }
Cell *fsubrSubr(Cell *args, Cell *env)  { return psubrP (car(args)) ? mkFsubr(psubr(car(args))) : 0; }
Cell *subrSubr (Cell *args, Cell *env)  { return psubrP (car(args)) ? mkSubr (psubr(car(args))) : 0; }

int xFlag= 0;
int vFlag= 0;

Cell *repl(FILE *in)
{
  Cell *expr= 0, *value= 0;
  GC_PROTECT(expr);
  GC_PROTECT(value);
  while (!feof(in)) {
    if (isatty(fileno(in))) {
      printf("> ");
      fflush(stdout);
    }
    expr= readFile(in);
    if (CEOF == expr) break;
    if (xFlag) println(expr, stderr);
    if (expr) {
      value= eval(expr, globals);
      if (isatty(fileno(in))) println(value, stderr);
      if (vFlag) { fprintf(stderr, "==> ");  println(value, stderr); }
    }
  }
  GC_UNPROTECT(expr);
  return value;
}

#if !BDWGC
void markFunction(void *ptr)
{
  Cell *cell= (Cell *)ptr;
  assert(ptr);
  switch (cell->mTag) {
  case Number: case String: case Symbol: case Subr: case Fsubr:
    return;
  case Cons:
  case Expr:
  case Fexpr:
    if (cell->mCons.a) GC_mark(cell->mCons.a);
    if (cell->mCons.d) GC_mark(cell->mCons.d);
    return;
  default:
    fatal("unknown tag");
  }
}

void freeFunction(void *ptr)
{
  Cell *cell= (Cell *)ptr;
  switch (cell->mTag) {
  case String:  free((void *)string(cell)); return;
  case Symbol:  free((void *)symbol(cell)); return;
  default:                  return;
  }
}
#endif

int main(int argc, char **argv)
{
  int i;

#if BDWGC
  GC_INIT();
#else
  GC_mark_function= markFunction;
  GC_free_function= freeFunction;
#endif

  for (i= 0;  i < 256;  ++i) readers[i]= readIllegal;
  initReaders(readBlank,  " \t\n\v\f\r");
  initReaders(readDigit,  "0123456789");
  initReaders(readAlpha,  "abcdefghijklmnopqrstuvwxyz");
  initReaders(readAlpha,  "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
  initReaders(readAlpha,  "!#$%&*/:<=>?@\\^_|~");
  initReaders(readSign,   "+-");
  initReaders(readString, "\"");
  initReaders(readQuote,  "'");
  initReaders(readQquote, "`");
  initReaders(readUquote, ",");
  initReaders(readList,   "([{");
  initReaders(readAlpha,  ".");
  initReaders(readSemi,   ";");

  rtldDefault= dlopen(0, RTLD_NOW | RTLD_GLOBAL);

  _S_t       = intern("t");
  _S_quote   = intern("quote");
  _S_qquote  = intern("quasiquote");
  _S_uquote  = intern("unquote");
  _S_uquotes = intern("unquote-splicing");

  globals= cons(cons(intern("t" ),     _S_t          ), globals);
  globals= cons(cons(intern("dlsym" ), mkSubr (dlsymSubr    )), globals);
  globals= cons(cons(intern("fsubr"     ), mkSubr (fsubrSubr    )), globals);
  globals= cons(cons(intern("subr"  ), mkSubr (subrSubr     )), globals);
  globals= cons(cons(intern("define"    ), mkFsubr(defineFsubr  )), globals);

  globals= cons((syntaxTable= cons(intern("*syntax-table*"), 0)), globals);

  GC_PROTECT(globals);
  GC_PROTECT(interns);

  if (argc == 1) repl(stdin);
  else {
    for (++argv;  argc > 1;  --argc, ++argv) {
      if      (!strcmp(*argv, "-v")) vFlag= 1;
      else if (!strcmp(*argv, "-x")) xFlag= 1;
      else if (!strcmp(*argv, "-" )) repl(stdin);
      else {
    FILE *in= fopen(*argv, "r");
    if (!in) perror(*argv);
    else {
      repl(in);
      fclose(in);
    }
      }
    }
  }

  return 0;
}

相关文章

网友评论

      本文标题:https://github.com/janet-lang/ja

      本文链接:https://www.haomeiwen.com/subject/qlynnhtx.html