Exemplo n.º 1
0
static pic_value
pic_proc_for_each(pic_state *pic)
{
  struct pic_proc *proc;
  size_t argc;
  pic_value *args;
  int i;
  pic_value cars;

  pic_get_args(pic, "l*", &proc, &argc, &args);

  do {
    cars = pic_nil_value();
    for (i = argc - 1; i >= 0; --i) {
      if (! pic_pair_p(args[i])) {
        break;
      }
      cars = pic_cons(pic, pic_car(pic, args[i]), cars);
      args[i] = pic_cdr(pic, args[i]);
    }
    if (i >= 0)
      break;
    pic_apply(pic, proc, cars);
  } while (1);

  return pic_none_value();
}
Exemplo n.º 2
0
bool
pic_equal_p(pic_state *pic, pic_value x, pic_value y)
{
  enum pic_tt type;

  if (pic_eqv_p(x, y))
    return true;

  type = pic_type(x);
  if (type != pic_type(y))
    return false;
  switch (type) {
  case PIC_TT_PAIR:
    return pic_equal_p(pic, pic_car(pic, x), pic_car(pic, y))
      && pic_equal_p(pic, pic_cdr(pic, x), pic_cdr(pic, y));
  default:
    return false;
  }
}
Exemplo n.º 3
0
Arquivo: pair.c Projeto: hiromu/picrin
pic_value
pic_reverse(pic_state *pic, pic_value list)
{
  pic_value v, acc = pic_nil_value();

  for (v = list; ! pic_nil_p(v); v = pic_cdr(pic ,v)) {
    acc = pic_cons(pic, pic_car(pic, v), acc);
  }
  return acc;
}
Exemplo n.º 4
0
static void
write_pair(struct writer_control *p, struct pic_pair *pair)
{
  pic_state *pic = p->pic;
  xFILE *file = p->file;
  pic_sym *tag;

  if (pic_pair_p(pair->cdr) && pic_nil_p(pic_cdr(pic, pair->cdr)) && pic_sym_p(pair->car)) {
    tag = pic_sym_ptr(pair->car);
    if (tag == pic->sQUOTE) {
      xfprintf(pic, file, "'");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sUNQUOTE) {
      xfprintf(pic, file, ",");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sUNQUOTE_SPLICING) {
      xfprintf(pic, file, ",@");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sQUASIQUOTE) {
      xfprintf(pic, file, "`");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sSYNTAX_QUOTE) {
      xfprintf(pic, file, "#'");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sSYNTAX_UNQUOTE) {
      xfprintf(pic, file, "#,");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sSYNTAX_UNQUOTE_SPLICING) {
      xfprintf(pic, file, "#,@");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
    else if (tag == pic->sSYNTAX_QUASIQUOTE) {
      xfprintf(pic, file, "#`");
      write_core(p, pic_car(pic, pair->cdr));
      return;
    }
  }
  xfprintf(pic, file, "(");
  write_pair_help(p, pair);
  xfprintf(pic, file, ")");
}
Exemplo n.º 5
0
Arquivo: lib.c Projeto: omasanori/benz
struct pic_lib *
pic_find_library(pic_state *pic, pic_value spec)
{
  pic_value v;

  v = pic_assoc(pic, spec, pic->libs, NULL);
  if (pic_false_p(v)) {
    return NULL;
  }
  return pic_lib_ptr(pic_cdr(pic, v));
}
Exemplo n.º 6
0
Arquivo: pair.c Projeto: hiromu/picrin
int
pic_length(pic_state *pic, pic_value obj)
{
  int c = 0;

  while (! pic_nil_p(obj)) {
    obj = pic_cdr(pic, obj);
    ++c;
  }

  return c;
}
Exemplo n.º 7
0
void
pic_end_try(pic_state *pic, pic_value cookie)
{
  struct checkpoint *here = (struct checkpoint *)pic_obj_ptr(pic_car(pic, cookie));
  pic_value out = pic_cdr(pic, cookie);

  pic->cp = here;

  pic_call(pic, out, 0); /* exit */

  pic_exit_point(pic);
}
Exemplo n.º 8
0
static void
write_pair(pic_state *pic, pic_value pair, pic_value port, struct writer_control *p)
{
  pic_value tag;

  if (pic_pair_p(pic, pic_cdr(pic, pair)) && pic_nil_p(pic, pic_cddr(pic, pair)) && pic_sym_p(pic, pic_car(pic, pair))) {
    tag = pic_car(pic, pair);
    if (EQ(tag, "quote")) {
      pic_fprintf(pic, port, "'");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "unquote")) {
      pic_fprintf(pic, port, ",");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "unquote-splicing")) {
      pic_fprintf(pic, port, ",@");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "quasiquote")) {
      pic_fprintf(pic, port, "`");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "syntax-quote")) {
      pic_fprintf(pic, port, "#'");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "syntax-unquote")) {
      pic_fprintf(pic, port, "#,");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "syntax-unquote-splicing")) {
      pic_fprintf(pic, port, "#,@");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
    else if (EQ(tag, "syntax-quasiquote")) {
      pic_fprintf(pic, port, "#`");
      write_core(pic, pic_cadr(pic, pair), port, p);
      return;
    }
  }
  pic_fprintf(pic, port, "(");
  write_pair_help(pic, pair, port, p);
  pic_fprintf(pic, port, ")");
}
Exemplo n.º 9
0
static void
traverse(pic_state *pic, pic_value obj, struct writer_control *p)
{
  pic_value shared = p->shared;

  if (p->op == OP_WRITE_SIMPLE) {
    return;
  }

  switch (pic_type(pic, obj)) {
  case PIC_TYPE_PAIR:
  case PIC_TYPE_VECTOR:
  case PIC_TYPE_DICT: {

    if (! pic_weak_has(pic, shared, obj)) {
      /* first time */
      pic_weak_set(pic, shared, obj, pic_int_value(pic, 0));

      if (pic_pair_p(pic, obj)) {
        /* pair */
        traverse(pic, pic_car(pic, obj), p);
        traverse(pic, pic_cdr(pic, obj), p);
      } else if (pic_vec_p(pic, obj)) {
        /* vector */
        int i, len = pic_vec_len(pic, obj);
        for (i = 0; i < len; ++i) {
          traverse(pic, pic_vec_ref(pic, obj, i), p);
        }
      } else {
        /* dictionary */
        int it = 0;
        pic_value val;
        while (pic_dict_next(pic, obj, &it, NULL, &val)) {
          traverse(pic, val, p);
        }
      }

      if (p->op == OP_WRITE) {
        if (pic_int(pic, pic_weak_ref(pic, shared, obj)) == 0) {
          pic_weak_del(pic, shared, obj);
        }
      }
    } else {
      /* second time */
      pic_weak_set(pic, shared, obj, pic_int_value(pic, 1));
    }
    break;
  }
  default:
    break;
  }
}
Exemplo n.º 10
0
pic_value
pic_raise_continuable(pic_state *pic, pic_value err)
{
  pic_value stack, exc = pic_ref(pic, "picrin.base", "current-exception-handlers");

  stack = pic_call(pic, exc, 0);

  if (pic_nil_p(pic, stack)) {
    pic_panic(pic, "no exception handler");
  }

  return pic_dynamic_bind(pic, exc, pic_cdr(pic, stack), pic_lambda(pic, raise_continuable, 2, pic_car(pic, stack), err));
}
Exemplo n.º 11
0
void
pic_raise(pic_state *pic, pic_value err)
{
  pic_value stack, exc = pic_ref(pic, "picrin.base", "current-exception-handlers");

  stack = pic_call(pic, exc, 0);

  if (pic_nil_p(pic, stack)) {
    pic_panic(pic, "no exception handler");
  }

  pic_dynamic_bind(pic, exc, pic_cdr(pic, stack), pic_lambda(pic, raise, 2, pic_car(pic, stack), err));

  PIC_UNREACHABLE();
}
Exemplo n.º 12
0
struct pic_vector *
pic_vec_new_from_list(pic_state *pic, pic_value data)
{
  struct pic_vector *vec;
  size_t i, len;

  len = pic_length(pic, data);

  vec = pic_vec_new(pic, len);
  for (i = 0; i < len; ++i) {
    vec->data[i] = pic_car(pic, data);
    data = pic_cdr(pic, data);
  }
  return vec;
}
Exemplo n.º 13
0
void
pic_errorf(pic_state *pic, const char *fmt, ...)
{
  va_list ap;
  pic_value err_line, irrs;
  const char *msg;

  va_start(ap, fmt);
  err_line = pic_xvformat(pic, fmt, ap);
  va_end(ap);

  msg = pic_str_cstr(pic, pic_str_ptr(pic_car(pic, err_line)));
  irrs = pic_cdr(pic, err_line);

  pic_error(pic, msg, irrs);
}
Exemplo n.º 14
0
int
pic_length(pic_state *pic, pic_value obj)
{
  int c = 0;

  if (! pic_list_p(obj)) {
    pic_errorf(pic, "length: expected list, but got ~s", obj);
  }

  while (! pic_nil_p(obj)) {
    obj = pic_cdr(pic, obj);
    ++c;
  }

  return c;
}
Exemplo n.º 15
0
Arquivo: pair.c Projeto: hiromu/picrin
pic_value
pic_assq(pic_state *pic, pic_value key, pic_value assoc)
{
  pic_value cell;

 enter:

  if (pic_nil_p(assoc))
    return assoc;

  cell = pic_car(pic, assoc);
  if (pic_eq_p(key, pic_car(pic, cell)))
    return cell;

  assoc = pic_cdr(pic, assoc);
  goto enter;
}
Exemplo n.º 16
0
static void
write_pair_help(pic_state *pic, pic_value pair, pic_value port, struct writer_control *p)
{
  pic_value cdr = pic_cdr(pic, pair);

  write_core(pic, pic_car(pic, pair), port, p);

  if (pic_nil_p(pic, cdr)) {
    return;
  }
  else if (pic_pair_p(pic, cdr) && ! is_shared_object(pic, cdr, p)) {
    pic_fprintf(pic, port, " ");
    write_pair_help(pic, cdr, port, p);
  }
  else {
    pic_fprintf(pic, port, " . ");
    write_core(pic, cdr, port, p);
  }
}
Exemplo n.º 17
0
Arquivo: init.c Projeto: hiromu/picrin
void
pic_load_stdlib(pic_state *pic)
{
  static const char *fn = "piclib/built-in.scm";
  FILE *file;
  int n, i;
  pic_value v, vs;
  struct pic_proc *proc;

  file = fopen(fn, "r");
  if (file == NULL) {
    fputs("fatal error: could not read built-in.scm", stderr);
    abort();
  }

  n = pic_parse_file(pic, file, &vs);
  if (n <= 0) {
    fputs("fatal error: built-in.scm broken", stderr);
    abort();
  }

  for (i = 0; i < n; ++i, vs = pic_cdr(pic, vs)) {
    v = pic_car(pic, vs);

    proc = pic_codegen(pic, v);
    if (proc == NULL) {
      fputs(pic->errmsg, stderr);
      fputs("fatal error: built-in.scm compilation failure", stderr);
      abort();
    }

    v = pic_apply(pic, proc, pic_nil_value());
    if (pic_undef_p(v)) {
      fputs(pic->errmsg, stderr);
      fputs("fatal error: built-in.scm evaluation failure", stderr);
      abort();
    }
  }

#if DEBUG
  puts("successfully loaded stdlib");
#endif
}
Exemplo n.º 18
0
Arquivo: vm.c Projeto: hiromu/picrin
pic_value
pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv)
{
  struct pic_code *pc, c;
  int ai = pic_gc_arena_preserve(pic);
  jmp_buf jmp;
  size_t argc, i;
  struct pic_code boot[2];

#if PIC_DIRECT_THREADED_VM
  static void *oplabels[] = {
    &&L_OP_POP, &&L_OP_PUSHNIL, &&L_OP_PUSHTRUE, &&L_OP_PUSHFALSE, &&L_OP_PUSHFLOAT,
    &&L_OP_PUSHINT, &&L_OP_PUSHCHAR, &&L_OP_PUSHCONST,
    &&L_OP_GREF, &&L_OP_GSET, &&L_OP_LREF, &&L_OP_LSET, &&L_OP_CREF, &&L_OP_CSET,
    &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_CALL, &&L_OP_TAILCALL, &&L_OP_RET, &&L_OP_LAMBDA,
    &&L_OP_CONS, &&L_OP_CAR, &&L_OP_CDR, &&L_OP_NILP,
    &&L_OP_ADD, &&L_OP_SUB, &&L_OP_MUL, &&L_OP_DIV,
    &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_STOP
  };
#endif

  if (setjmp(jmp) == 0) {
    pic->jmp = &jmp;
  }
  else {
    goto L_RAISE;
  }

  argc = pic_length(pic, argv) + 1;

#if VM_DEBUG
  puts("== booting VM...");
  printf("  proc = ");
  pic_debug(pic, pic_obj_value(proc));
  puts("");
  printf("  argv = ");
  pic_debug(pic, argv);
  puts("");
  printf("  irep = ");
  print_irep(pic, proc->u.irep);
  puts("\nLet's go!");
#endif

  PUSH(pic_obj_value(proc));
  for (i = 1; i < argc; ++i) {
    PUSH(pic_car(pic, argv));
    argv = pic_cdr(pic, argv);
  }

  /* boot! */
  boot[0].insn = OP_CALL;
  boot[0].u.i = argc;
  boot[1].insn = OP_STOP;
  pc = boot;
  c = *pc;
  goto L_CALL;

  VM_LOOP {
    CASE(OP_POP) {
      POPN(1);
      NEXT;
    }
    CASE(OP_PUSHNIL) {
      PUSH(pic_nil_value());
      NEXT;
    }
    CASE(OP_PUSHTRUE) {
      PUSH(pic_true_value());
      NEXT;
    }
    CASE(OP_PUSHFALSE) {
      PUSH(pic_false_value());
      NEXT;
    }
    CASE(OP_PUSHFLOAT) {
      PUSH(pic_float_value(c.u.f));
      NEXT;
    }
    CASE(OP_PUSHINT) {
      PUSH(pic_int_value(c.u.i));
      NEXT;
    }
    CASE(OP_PUSHCHAR) {
      PUSH(pic_char_value(c.u.c));
      NEXT;
    }
    CASE(OP_PUSHCONST) {
      PUSH(pic->pool[c.u.i]);
      NEXT;
    }
    CASE(OP_GREF) {
      PUSH(pic->globals[c.u.i]);
      NEXT;
    }
    CASE(OP_GSET) {
      pic->globals[c.u.i] = POP();
      NEXT;
    }
    CASE(OP_LREF) {
      PUSH(pic->ci->fp[c.u.i]);
      NEXT;
    }
    CASE(OP_LSET) {
      pic->ci->fp[c.u.i] = POP();
      NEXT;
    }
    CASE(OP_CREF) {
      int depth = c.u.r.depth;
      struct pic_env *env;

      env = pic->ci->env;
      while (depth--) {
	env = env->up;
      }
      PUSH(env->values[c.u.r.idx]);
      NEXT;
    }
    CASE(OP_CSET) {
      int depth = c.u.r.depth;
      struct pic_env *env;

      env = pic->ci->env;
      while (depth--) {
	env = env->up;
      }
      env->values[c.u.r.idx] = POP();
      NEXT;
    }
    CASE(OP_JMP) {
      pc += c.u.i;
      JUMP;
    }
    CASE(OP_JMPIF) {
      pic_value v;

      v = POP();
      if (! pic_false_p(v)) {
	pc += c.u.i;
	JUMP;
      }
      NEXT;
    }
    CASE(OP_CALL) {
      pic_value x, v;
      pic_callinfo *ci;
      struct pic_proc *proc;

    L_CALL:
      x = pic->sp[-c.u.i];
      if (! pic_proc_p(x)) {
	pic->errmsg = "invalid application";
	goto L_RAISE;
      }
      proc = pic_proc_ptr(x);

      ci = PUSHCI();
      ci->argc = c.u.i;
      ci->pc = pc;
      ci->fp = pic->sp - c.u.i;
      ci->env = NULL;
      if (pic_proc_cfunc_p(x)) {
	v = proc->u.cfunc(pic);
	pic->sp = ci->fp;
	POPCI();
	PUSH(v);
	pic_gc_arena_restore(pic, ai);
	NEXT;
      }
      else {
	int i;
	pic_value rest;

	if (ci->argc != proc->u.irep->argc) {
	  if (! (proc->u.irep->varg && ci->argc >= proc->u.irep->argc)) {
	    pic->errmsg = "wrong number of arguments";
	    goto L_RAISE;
	  }
	}
	/* prepare rest args */
	if (proc->u.irep->varg) {
	  rest = pic_nil_value();
	  for (i = 0; i < ci->argc - proc->u.irep->argc; ++i) {
	    pic_gc_protect(pic, v = POP());
	    rest = pic_cons(pic, v, rest);
	  }
	  PUSH(rest);
	}

	/* prepare env */
	if (proc->u.irep->cv_num == 0) {
	  ci->env = proc->env;
	}
	else {
	  ci->env = (struct pic_env *)pic_obj_alloc(pic, sizeof(struct pic_env), PIC_TT_ENV);
	  ci->env->up = proc->env;
	  ci->env->valuec = proc->u.irep->cv_num;
	  ci->env->values = (pic_value *)pic_calloc(pic, ci->env->valuec, sizeof(pic_value));
	  for (i = 0; i < ci->env->valuec; ++i) {
	    ci->env->values[i] = ci->fp[proc->u.irep->cv_tbl[i]];
	  }
	}

	pc = proc->u.irep->code;
	pic_gc_arena_restore(pic, ai);
	JUMP;
      }
    }
    CASE(OP_TAILCALL) {
      int argc;
      pic_value *argv;

      argc = c.u.i;
      argv = pic->sp - argc;
      for (i = 0; i < argc; ++i) {
	pic->ci->fp[i] = argv[i];
      }
      pic->sp = pic->ci->fp + argc;
      pc = POPCI()->pc;

      /* c is not changed */
      goto L_CALL;
    }
    CASE(OP_RET) {
      pic_value v;
      pic_callinfo *ci;

      if (pic->errmsg) {

      L_RAISE:
	goto L_STOP;
      }
      else {
	v = POP();
	ci = POPCI();
	pc = ci->pc;
	pic->sp = ci->fp;
	PUSH(v);
      }
      NEXT;
    }
    CASE(OP_LAMBDA) {
      struct pic_proc *proc;

      proc = pic_proc_new(pic, pic->irep[c.u.i], pic->ci->env);
      PUSH(pic_obj_value(proc));
      pic_gc_arena_restore(pic, ai);
      NEXT;
    }
    CASE(OP_CONS) {
      pic_value a, b;
      pic_gc_protect(pic, b = POP());
      pic_gc_protect(pic, a = POP());
      PUSH(pic_cons(pic, a, b));
      pic_gc_arena_restore(pic, ai);
      NEXT;
    }
    CASE(OP_CAR) {
      pic_value p;
      p = POP();
      PUSH(pic_car(pic, p));
      NEXT;
    }
    CASE(OP_CDR) {
      pic_value p;
      p = POP();
      PUSH(pic_cdr(pic, p));
      NEXT;
    }
    CASE(OP_NILP) {
      pic_value p;
      p = POP();
      PUSH(pic_bool_value(pic_nil_p(p)));
      NEXT;
    }

#define DEFINE_ARITH_OP(opcode, op)				\
    CASE(opcode) {						\
      pic_value a, b;						\
      b = POP();						\
      a = POP();						\
      if (pic_int_p(a) && pic_int_p(b)) {			\
	double f = (double)pic_int(a) op (double)pic_int(b);	\
	if (INT_MIN <= f && f <= INT_MAX) {			\
	  PUSH(pic_int_value((int)f));				\
	}							\
	else {							\
	  PUSH(pic_float_value(f));				\
	}							\
      }								\
      else if (pic_float_p(a) && pic_float_p(b)) {		\
	PUSH(pic_float_value(pic_float(a) op pic_float(b)));	\
      }								\
      else if (pic_int_p(a) && pic_float_p(b)) {		\
	PUSH(pic_float_value(pic_int(a) op pic_float(b)));	\
      }								\
      else if (pic_float_p(a) && pic_int_p(b)) {		\
	PUSH(pic_float_value(pic_float(a) op pic_int(b)));	\
      }								\
      else {							\
	pic->errmsg = #op " got non-number operands";		\
	goto L_RAISE;						\
      }								\
      NEXT;							\
    }

    DEFINE_ARITH_OP(OP_ADD, +);
    DEFINE_ARITH_OP(OP_SUB, -);
    DEFINE_ARITH_OP(OP_MUL, *);

    /* special care for (int / int) division */
    CASE(OP_DIV) {
      pic_value a, b;
      b = POP();
      a = POP();
      if (pic_int_p(a) && pic_int_p(b)) {
	PUSH(pic_float_value((double)pic_int(a) / pic_int(b)));
      }
      else if (pic_float_p(a) && pic_float_p(b)) {
	PUSH(pic_float_value(pic_float(a) / pic_float(b)));
      }
      else if (pic_int_p(a) && pic_float_p(b)) {
	PUSH(pic_float_value(pic_int(a) / pic_float(b)));
      }
      else if (pic_float_p(a) && pic_int_p(b)) {
	PUSH(pic_float_value(pic_float(a) / pic_int(b)));
      }
      else {
	pic->errmsg = "/ got non-number operands";
	goto L_RAISE;
      }
      NEXT;
    }

#define DEFINE_COMP_OP(opcode, op)				\
    CASE(opcode) {						\
      pic_value a, b;						\
      b = POP();						\
      a = POP();						\
      if (pic_int_p(a) && pic_int_p(b)) {			\
	PUSH(pic_bool_value(pic_int(a) op pic_int(b)));		\
      }								\
      else if (pic_float_p(a) && pic_float_p(b)) {		\
	PUSH(pic_bool_value(pic_float(a) op pic_float(b)));	\
      }								\
      else if (pic_int_p(a) && pic_int_p(b)) {			\
	PUSH(pic_bool_value(pic_int(a) op pic_float(b)));	\
      }								\
      else if (pic_float_p(a) && pic_int_p(b)) {		\
	PUSH(pic_bool_value(pic_float(a) op pic_int(b)));	\
      }								\
      else {							\
	pic->errmsg = #op " got non-number operands";		\
	goto L_RAISE;						\
      }								\
      NEXT;							\
    }

    DEFINE_COMP_OP(OP_EQ, ==);
    DEFINE_COMP_OP(OP_LT, <);
    DEFINE_COMP_OP(OP_LE, <=);

    CASE(OP_STOP) {
      pic_value val;

    L_STOP:
      val = POP();

      pic->jmp = NULL;
      if (pic->errmsg) {
	return pic_undef_value();
      }

#if VM_DEBUG
      puts("**VM END STATE**");
      printf("stbase\t= %p\nsp\t= %p\n", pic->stbase, pic->sp);
      printf("cibase\t= %p\nci\t= %p\n", pic->cibase, pic->ci);
      if (pic->stbase < pic->sp) {
	pic_value *sp;
	printf("* stack trace:");
	for (sp = pic->stbase; pic->sp != sp; ++sp) {
	  pic_debug(pic, *sp);
	  puts("");
	}
      }
      if (pic->stbase > pic->sp) {
	puts("*** stack underflow!");
      }
#endif

      pic_gc_protect(pic, val);

      return val;
    }
  } VM_LOOP_END;
}
Exemplo n.º 19
0
Arquivo: bool.c Projeto: KeenS/benz
static bool
internal_equal_p(pic_state *pic, pic_value x, pic_value y, size_t depth, xhash *ht)
{
  pic_value local = pic_nil_value();
  size_t c;

  if (depth > 10) {
    if (depth > 200) {
      pic_errorf(pic, "Stack overflow in equal\n");
    }
    if (pic_pair_p(x) || pic_vec_p(x)) {
      if (xh_get_ptr(ht, pic_obj_ptr(x)) != NULL) {
        return true;            /* `x' was seen already.  */
      } else {
        xh_put_ptr(ht, pic_obj_ptr(x), NULL);
      }
    }
  }

  c = 0;

 LOOP:

  if (pic_eqv_p(x, y))
    return true;

  if (pic_type(x) != pic_type(y))
    return false;

  switch (pic_type(x)) {
  case PIC_TT_STRING:
    return str_equal_p(pic_str_ptr(x), pic_str_ptr(y));

  case PIC_TT_BLOB:
    return blob_equal_p(pic_blob_ptr(x), pic_blob_ptr(y));

  case PIC_TT_PAIR: {
    if (pic_nil_p(local)) {
      local = x;
    }
    if (internal_equal_p(pic, pic_car(pic, x), pic_car(pic, y), depth + 1, ht)) {
      x = pic_cdr(pic, x);
      y = pic_cdr(pic, y);

      c++;

      if (c == 2) {
        c = 0;
        local = pic_cdr(pic, local);
        if (pic_eq_p(local, x)) {
          return true;
        }
      }
      goto LOOP;
    } else {
      return false;
    }
  }
  case PIC_TT_VECTOR: {
    size_t i;
    struct pic_vector *u, *v;

    u = pic_vec_ptr(x);
    v = pic_vec_ptr(y);

    if (u->len != v->len) {
      return false;
    }
    for (i = 0; i < u->len; ++i) {
      if (! internal_equal_p(pic, u->data[i], v->data[i], depth + 1, ht))
        return false;
    }
    return true;
  }
  default:
    return false;
  }
}