Esempio n. 1
0
PN potion_lobby_read(Potion *P, PN cl, PN self) {
  const int linemax = 1024;
  char line[linemax];
  if (fgets(line, linemax, stdin) != NULL)
    return potion_str(P, line);
  return PN_NIL;
}
Esempio n. 2
0
void potion_test_empty(CuTest *T) {
  PN empty = PN_TUP0();
  CuAssert(T, "empty isn't a tuple", PN_IS_TUPLE(empty));
  CuAssert(T, "empty isn't a ref", PN_IS_PTR(empty));
  CuAssertIntEquals(T, "tuple length is off",
                    0, PN_INT(potion_send(empty, potion_str(P, "length"))));
}
Esempio n. 3
0
void potion_load_code(Potion *P, const char *filename)
{
	PN buf, code;
	struct stat stats;
	int fd = -1;
	if (stat(filename, &stats) == -1)
	{
		potion_notice("** %s does not exist.\n", filename);
		return;
	}
	fd = open(filename, O_RDONLY | O_BINARY);
	if (fd == -1)
	{
		potion_notice("** could not open %s. check permissions.\n", filename);
		return;
	}
	buf = potion_bytes(P, stats.st_size);
	if (read(fd, PN_STR_PTR(buf), stats.st_size) == stats.st_size)
	{
		PN_STR_PTR(buf)[stats.st_size] = '\0';
		code = potion_source_load(P, PN_NIL, buf);
		if (!PN_IS_PROTO(code))
		{
			potion_run(P,
					potion_send(
							potion_parse(P, buf), PN_compile, potion_str(P, filename), PN_NIL),
					POTION_JIT);
		}
	}
	else
	{
		potion_notice("** could not read entire file: %s.\n", filename);
	}
	close(fd);
}
Esempio n. 4
0
void potion_test_int3(CuTest *T) {
  PN neg = PN_NUM(-4343);
  CuAssert(T, "negative numbers invalid", PN_INT(neg) == -4343);
  CuAssert(T, "negative not a number", PN_IS_INT(neg));
  CuAssert(T, "negative is a ref", !PN_IS_PTR(neg));
  CuAssert(T, "negative bad add",
    -3853 == PN_INT(potion_send(neg, potion_str(P, "+"), num)));
}
Esempio n. 5
0
void potion_test_int2(CuTest *T) {
  PN pos = PN_NUM(10891);
  CuAssert(T, "positive numbers invalid", PN_INT(pos) == 10891);
  CuAssert(T, "positive not a number", PN_IS_INT(pos));
  CuAssert(T, "positive is a ref", !PN_IS_PTR(pos));
  CuAssert(T, "positive bad add",
    11381 == PN_INT(potion_send(pos, potion_str(P, "+"), num)));
}
Esempio n. 6
0
void potion_test_int1(CuTest *T) {
  PN zero = PN_ZERO;
  CuAssert(T, "zero isn't zero", PN_INT(zero) == 0);
  CuAssert(T, "zero isn't a number", PN_IS_INT(zero));
  CuAssert(T, "zero is a ref", !PN_IS_PTR(zero));
  CuAssert(T, "zero bad add",
    490 == PN_INT(potion_send(zero, potion_str(P, "+"), num)));
}
Esempio n. 7
0
void potion_test_tuple(CuTest *T) {
  PN tup = potion_tuple_with_size(P, 3);
  PN_TUPLE_AT(tup, 0) = PN_NIL;
  PN_TUPLE_AT(tup, 1) = PN_string;
  PN_TUPLE_AT(tup, 2) = tup;
  CuAssert(T, "tuple isn't a tuple", PN_IS_TUPLE(tup));
  CuAssert(T, "tuple isn't a ref", PN_IS_PTR(tup));
  CuAssertIntEquals(T, "tuple length is off",
                    3, PN_INT(potion_send(tup, potion_str(P, "length"))));
}
Esempio n. 8
0
void potion_file_init(Potion *P) {
  PN file_vt = PN_VTABLE(PN_TFILE);
  char **env = environ, *key;
  PN pe = potion_table_empty(P);
  while (*env != NULL) {
    for (key = *env; *key != '='; key++);
    potion_table_put(P, PN_NIL, pe, potion_str2(P, *env, key - *env),
      potion_str(P, key + 1));
    env++;
  }
  potion_send(P->lobby, PN_def, potion_str(P, "Env"), pe);
  potion_method(P->lobby, "read", potion_lobby_read, 0);
  
  potion_type_constructor_is(file_vt, PN_FUNC(potion_file_new, "path=S,mode=S"));
  potion_class_method(file_vt, "fd", potion_file_with_fd, "fd=N");
  potion_method(file_vt, "string", potion_file_string, 0);
  potion_method(file_vt, "close", potion_file_close, 0);
  potion_method(file_vt, "read", potion_file_read, "n=N");
  potion_method(file_vt, "write", potion_file_write, "str=S");
}
Esempio n. 9
0
void potion_test_proto(CuTest *T) {
  // test compiler transformation potion_sig_compile, not just yy_sig
  PN p2;
  vPN(Closure) f2;
  vPN(Closure) f1 = PN_CLOSURE(potion_eval(P, potion_str(P, "(x,y):x+y.")));
  CuAssertIntEquals(T, "arity f1", 2, potion_sig_arity(P, f1->sig));
  CuAssertStrEquals(T, "x,y", PN_STR_PTR(potion_sig_string(P,0,f1->sig)));

  p2 = PN_FUNC(PN_CLOSURE_F(f1), "x=N,y=N");
  f2 = PN_CLOSURE(p2);
  CuAssertIntEquals(T, "sig arity f2", 2, potion_sig_arity(P, f2->sig));
  CuAssertStrEquals(T, "x=N,y=N", PN_STR_PTR(potion_sig_string(P,0,f2->sig)));
  CuAssertIntEquals(T, "cl arity f2", 2, PN_INT(potion_closure_arity(P,0,p2)));
}
Esempio n. 10
0
void potion_test_eval(CuTest *T) {
  PN add, num;
  PN_F addfn;

#if POTION_JIT
  long flags = P->flags;
  if (P->flags & EXEC_JIT) P->flags = (Potion_Flags)((int)P->flags - EXEC_JIT);
#endif
  add = potion_eval(P, potion_str(P, "(x, y): x + y."));
  addfn = PN_CLOSURE_F(add); // c callback
  CuAssertPtrNotNull(T, addfn);
  num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5));
  CuAssertIntEquals(T, "calling closure as c func", 8, PN_INT(num));

  add = potion_eval(P, potion_str(P, "(x=N|y=N): x + y."));
  addfn = PN_CLOSURE_F(add);
  num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5));
  CuAssertIntEquals(T, "calling closure as c func (opt)", 8, PN_INT(num));
  num = addfn(P, add, 1, PN_NUM(3));
  CuAssertIntEquals(T, "optional num = 0", 3, PN_INT(num));

  add = potion_eval(P, potion_str(P, "(x=N,y:=1): x + y."));
  addfn = PN_CLOSURE_F(add);
  num = addfn(P, add, 2, PN_NUM(3), PN_NUM(5));
  CuAssertIntEquals(T, "calling closure as c func (default)", 8, PN_INT(num));
  num = addfn(P, add, 1, PN_NUM(3));
  CuAssertIntEquals(T, "default num = 1", 4, PN_INT(num));

#if POTION_JIT
  P->flags = (Potion_Flags)flags; //restore JIT
  add = potion_eval(P, potion_str(P, "(x, y): x + y."));
  addfn = PN_CLOSURE_F(add); // c callback
  CuAssertPtrNotNull(T, addfn);
  num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5));
  CuAssertIntEquals(T, "calling closure as c func (jit)", 8, PN_INT(num));

#ifdef DEBUG
  //P->flags += DEBUG_COMPILE + DEBUG_JIT;
#endif
  add = potion_eval(P, potion_str(P, "(x=N|y=N): x + y."));
  addfn = PN_CLOSURE_F(add);
  num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5));
  CuAssertIntEquals(T, "calling closure as c func (jit+opt)", 8, PN_INT(num));
  //hard to make this work, would slow it down
  //num = addfn(P, add, 0, PN_NUM(3));
  //CuAssertIntEquals(T, "optional num = 0 (jit)", 3, PN_INT(num));

  add = potion_eval(P, potion_str(P, "(x=N|y:=1): x + y."));
  addfn = PN_CLOSURE_F(add);
  num = addfn(P, add, 0, PN_NUM(3), PN_NUM(5));
  CuAssertIntEquals(T, "calling closure as c func (jit+default)", 8, PN_INT(num));
  //num = addfn(P, add, 0, PN_NUM(3));
  //CuAssertIntEquals(T, "default num = 1 (jit)", 4, PN_INT(num));
#endif

}
Esempio n. 11
0
PN potion_file_string(Potion *P, PN cl, pn_file self) {
  int fd = self->fd, rv;
  char *buf;
  PN str;
  if (self->path != PN_NIL && fd != -1) {
    rv = asprintf(&buf, "<file %s fd: %d>", PN_STR_PTR(self->path), fd);
  } else if (fd != -1) {
    rv = asprintf(&buf, "<file fd: %d>", fd);
  } else {
    rv = asprintf(&buf, "<closed file>");
  }
  if (rv == -1) potion_allocation_error();
  str = potion_str(P, buf);
  free(buf);
  return str;
}
Esempio n. 12
0
void potion_test_str(CuTest *T) {
  CuAssert(T, "string isn't a string", PN_IS_STR(PN_string));
  CuAssert(T, "string isn't a ref", PN_IS_PTR(PN_string));
  CuAssert(T, "string length isn't working",
    6 == PN_INT(potion_send(PN_string, potion_str(P, "length"))));
}
Esempio n. 13
0
void potion_test_nil(CuTest *T) {
  CuAssert(T, "nil isn't a nil type", PN_TYPE(PN_NIL) == PN_TNIL);
  CuAssert(T, "nil is a ref", !PN_IS_PTR(PN_NIL));
  CuAssert(T, "nil nil? is false",
    PN_TRUE == potion_send(PN_NIL, potion_str(P, "nil?")));
}
Esempio n. 14
0
PN potion_source_name(Potion *P, PN cl, PN self) {
  struct PNSource *t = (struct PNSource *)self;
  return potion_str(P, potion_ast_names[t->part]);
}
Esempio n. 15
0
static void potion_cmd_compile
(
		char *filename,
		int exec,
		int verbose,
		void *sp
)
{
	PN buf, code;
	int fd = -1;
	struct stat stats;
	Potion *P = potion_create(sp);
	if (stat(filename, &stats) == -1)
	{
		potion_warn("** %s does not exist.\n", filename);
		goto done;
	}

	fd = open(filename, O_RDONLY | O_BINARY);
	if (fd == -1)
	{
		potion_warn("** could not open %s. check permissions.\n", filename);
		goto done;
	}

	buf = potion_bytes(P, stats.st_size);
	if (read(fd, PN_STR_PTR(buf), stats.st_size) == stats.st_size)
	{
		PN_STR_PTR(buf)[stats.st_size] = '\0';
		code = potion_source_load(P, PN_NIL, buf);
		if (PN_IS_PROTO(code))
		{
			if (verbose > 1)
				printf("\n\n-- loaded --\n");
		}
		else
		{
			code = potion_parse(P, buf);
			if (PN_TYPE(code) == PN_TERROR)
			{
				potion_send(potion_send(code, PN_string), PN_print);
				goto done;
			}
			if (verbose > 1)
			{
				printf("\n-- parsed --\n");
				potion_send(potion_send(code, PN_string), PN_print);
				printf("\n");
			}
			code =
					potion_send(code, PN_compile, potion_str(P, filename), PN_NIL);
			if (verbose > 1)
				printf("\n-- compiled --\n");
		}
		if (verbose > 1)
		{
			potion_send(potion_send(code, PN_string), PN_print);
			printf("\n");
		}
		if (exec == 1)
		{
			code = potion_vm(P, code, P->lobby, PN_NIL, 0, NULL );
			if (verbose > 1)
				printf(
						"\n-- vm returned %p (fixed=%ld, actual=%ld, reserved=%ld) --\n",
						(void *) code, PN_INT(potion_gc_fixed(P, 0, 0)),
						PN_INT(potion_gc_actual(P, 0, 0)),
						PN_INT(potion_gc_reserved(P, 0, 0)));
			if (verbose)
			{
				potion_send(potion_send(code, PN_string), PN_print);
				printf("\n");
			}
		}
		else if (exec == 2)
		{
#if POTION_JIT == 1
			PN val;
			PN cl = potion_closure_new(P, (PN_F)potion_jit_proto(P, code, POTION_JIT_TARGET), PN_NIL, 1);
			PN_CLOSURE(cl)->data[0] = code;
			val = PN_PROTO(code)->jit(P, cl, P->lobby);
			if (verbose > 1)
			printf("\n-- jit returned %p (fixed=%ld, actual=%ld, reserved=%ld) --\n", PN_PROTO(code)->jit,
					PN_INT(potion_gc_fixed(P, 0, 0)), PN_INT(potion_gc_actual(P, 0, 0)),
					PN_INT(potion_gc_reserved(P, 0, 0)));
			if (verbose)
			{
				potion_send(potion_send(val, PN_string), PN_print);
				printf("\n");
			}
#else
			potion_warn("** potion built without JIT support\n");
#endif
		}
		else
		{
			char pnbpath[255];
			FILE *pnb;
			sprintf(pnbpath, "%sb", filename);
			pnb = fopen(pnbpath, "wb");
			if (!pnb)
			{
				potion_warn("** could not open %s for writing. check permissions.\n",pnbpath);
				goto done;
			}

			code = potion_source_dump(P, PN_NIL, code);
			if (fwrite(PN_STR_PTR(code), 1, PN_STR_LEN(code),
					pnb) == PN_STR_LEN(code))
			{
				potion_notice("** compiled code saved to %s\n", pnbpath);
				potion_notice("** run it with: potion %s\n", pnbpath);
				fclose(pnb);
			}
			else
			{
				potion_warn("** could not write all bytecode.\n");
			}
		}

#if 0
		void *scanptr = (void *)((char *)P->mem->old_lo + (sizeof(PN) * 2));
		while ((PN)scanptr < (PN)P->mem->old_cur)
		{
			printf("%p.vt = %lx (%u)\n",
					scanptr, ((struct PNObject *)scanptr)->vt,
					potion_type_size(P, scanptr));
			if (((struct PNFwd *)scanptr)->fwd != POTION_FWD && ((struct PNFwd *)scanptr)->fwd != POTION_COPIED)
			{
				if (((struct PNObject *)scanptr)->vt < 0 || ((struct PNObject *)scanptr)->vt > PN_TUSER)
				{
					printf("wrong type for allocated object: %p.vt = %lx\n",
							scanptr, ((struct PNObject *)scanptr)->vt);
					break;
				}
			}
			scanptr = (void *)((char *)scanptr + potion_type_size(P, scanptr));
			if ((PN)scanptr > (PN)P->mem->old_cur)
			{
				printf("allocated object goes beyond GC pointer\n");
				break;
			}
		}
#endif

	}
	else
	{
		potion_warn("** could not read entire file.");
	}

	done: if (fd != -1)
		close(fd);
	if (P != NULL )
		potion_destroy(P);
}
Esempio n. 16
0
File: file.c Progetto: perl11/potion
/**\memberof Lobby
  global "read" method, read next line from stdin via fgets()
  \return PNString or or PN_NIL */
PN potion_lobby_read(Potion *P, PN cl, PN self) {
  char line[1024];
  if (fgets(line, 1024, stdin) != NULL)
    return potion_str(P, line);
  return PN_NIL;
}