/**\memberof PNFile \c "write" a binary representation of obj to the file handle. \param obj PNString, PNBytes, PNInteger (long or double), PNBoolean (char 0 or 1) \return PNInteger written bytes or PN_NIL */ PN potion_file_write(Potion *P, PN cl, pn_file self, PN obj) { long len = 0; char *ptr = NULL; union { double d; long l; char c; } tmp; //TODO: maybe extract ptr+len to seperate function if (!PN_IS_PTR(obj)) { if (!obj) return PN_NIL; //silent else if (PN_IS_INT(obj)) { tmp.l = PN_NUM(obj); len = sizeof(tmp); ptr = (char *)&tmp.l; } else if (PN_IS_BOOL(obj)) { tmp.c = (obj == PN_TRUE) ? 1 : 0; len = 1; ptr = (char *)&tmp.c; } else { assert(0 && "Invalid primitive type"); } } else { switch (PN_TYPE(obj)) { case PN_TSTRING: len = PN_STR_LEN(obj); ptr = PN_STR_PTR(obj); break; case PN_TBYTES: len = potion_send(obj, PN_STR("length")); ptr = PN_STR_PTR(obj); break; case PN_TNUMBER: { tmp.d = PN_DBL(obj); len = sizeof(tmp); ptr = (char *)&tmp.d; break; } default: return potion_type_error(P, obj); } } int r = write(self->fd, ptr, len); if (r == -1) return potion_io_error(P, "write"); return PN_NUM(r); }
PN potion_error(Potion *P, PN msg, long lineno, long charno, PN excerpt) { struct PNError *e = PN_ALLOC(PN_TERROR, struct PNError); e->message = msg; e->line = PN_NUM(lineno); e->chr = PN_NUM(charno); e->excerpt = excerpt; return (PN)e; }
PN potion_gc_fixed(Potion *P, PN cl, PN self) { int total = 0; if (P->mem->protect != NULL) total += (char *)P->mem->protect - (char *)P->mem; return PN_NUM(total); }
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))); }
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))); }
PN potion_file_write(Potion *P, PN cl, pn_file self, PN str) { int r = write(self->fd, PN_STR_PTR(str), PN_STR_LEN(str)); if (r == -1) { perror("write"); // TODO: error return PN_NIL; } return PN_NUM(r); }
PN potion_gc_reserved(Potion *P, PN cl, PN self) { int total = (char *)P->mem->birth_hi - (char *)P->mem->birth_lo; if (P->mem != P->mem->birth_lo) total += (char *)P->mem->protect - (char *)P->mem; if (P->mem->old_lo != NULL) total += (char *)P->mem->old_hi - (char *)P->mem->old_lo; return PN_NUM(total); }
PN potion_file_read(Potion *P, PN cl, pn_file self, PN n) { n = PN_INT(n); char buf[n]; int r = read(self->fd, buf, n); if (r == -1) { perror("read"); // TODO: error return PN_NUM(-1); } else if (r == 0) { return PN_NIL; } return potion_byte_str2(P, buf, r); }
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 }
// // potion-test.c // tests of the Potion C api // // (c) 2008 why the lucky stiff, the freelance professor // (c) 2013 perl11 org // #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include "potion.h" #include "internal.h" #include "CuTest.h" PN num = PN_NUM(490); Potion *P; 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?"))); } void potion_test_bool(CuTest *T) { CuAssert(T, "true isn't a bool type", PN_TYPE(PN_TRUE) == PN_TBOOLEAN); CuAssert(T, "true is a ref", !PN_IS_PTR(PN_TRUE)); CuAssert(T, "false isn't a bool type", PN_TYPE(PN_FALSE) == PN_TBOOLEAN); CuAssert(T, "false is a ref", !PN_IS_PTR(PN_FALSE)); }