26 printf(
"usage: potion [options] [filename] [arguments]\n"
27 " -e code execute code instead of filename\n"
28 " -B, --bytecode run with bytecode VM (slower, but cross-platform)\n"
29 " -X, --x86 run with x86 JIT VM (faster, x86 and x86-64)\n"
30 " -I, --inspect print only the return value\n"
31 " -V, --verbose show bytecode and ast info\n"
32 " -Ldirectory add library search path\n"
33 " -Mmodule[=args] load module\n"
34 " -d[module[=args]] debug script\n"
35 " --debug[=module[,args]]\n"
36 " -c, --compile compile the script to bytecode\n"
37 " --compile={target[,args]} compile to target: c or exe\n"
38 " --check check the script syntax and exit\n"
39 " -h, --help show this helpful stuff\n"
41 " -D[itPpcvGJ?] debugging flags, try -D?\n"
43 " -v, --version show version\n"
54 printf(
"sizeof(PN=%d, PNObject=%d, PNTuple=%d, PNTuple+1=%d, PNTable=%d)\n",
57 printf(
"GC (fixed=%ld, actual=%ld, reserved=%ld)\n",
67 if (P->flags & DEBUG_VERBOSE) \
71 if (P->flags & (DEBUG_INSPECT|DEBUG_VERBOSE)) \
79 if (!buf && filename) {
81 if (stat(filename, &stats) == -1) {
82 fprintf(stderr,
"** %s does not exist.", filename);
85 fd = open(filename, O_RDONLY |
O_BINARY);
87 fprintf(stderr,
"** could not open %s. check permissions.", filename);
90 long size = stats.st_size;
93 int len = strlen(addcode);
104 if (read(fd, bufptr, stats.st_size) == stats.st_size) {
107 fprintf(stderr,
"** could not read entire file.");
111 else if (!filename) filename =
"-e";
115 DBG_v(
"\n-- loaded --\n");
122 DBG_v(
"\n-- parsed --\n");
126 DBG_v(
"\n-- compiled --\n");
131 DBG_v(
"\n-- vm returned %p (fixed=%ld, actual=%ld, reserved=%ld, time=%0.6gms %dx/%dm/%di) --\n",
138 #ifdef POTION_JIT_TARGET
143 DBG_v(
"\n-- jit returned %p (fixed=%ld, actual=%ld, reserved=%ld, time=%0.6gms %dx/%dm/%di) --\n",
PN_PROTO(code)->jit,
149 fprintf(stderr,
"** potion built without JIT support\n");
153 DBG_v(
"\n-- check --\n");
160 potion_fatal(
"fatal: stack corruption (exec > MAX_EXEC)\n");
169 if ((c_opts = strchr(compile,
','))) {
175 if (!compile || !strcmp(compile,
"bc"))
176 sprintf(outpath,
"%sb", filename);
177 else if (!strcmp(compile,
"c"))
178 sprintf(outpath,
"%s.c", filename);
179 else if (!strcmp(compile,
"exe"))
180 sprintf(outpath,
"%s.out", filename);
185 pnb = fopen(outpath,
"wb");
187 fprintf(stderr,
"** could not open %s for writing. check permissions.\n", outpath);
198 printf(
"** compiled code saved to %s\n", outpath);
201 if (!compile || !strcmp(compile,
"bc"))
202 printf(
"** run it with: potion %s\n", outpath);
204 else if (!strcmp(compile,
"c"))
206 else if (!strcmp(compile,
"exe"))
207 printf(
"** run it with: ./%s\n", outpath);
209 fprintf(stderr,
"** could not write all %s compiled code (%u/%u) to %s\n",
210 compile?compile:
"bytecode", written, code?
PN_STR_LEN(code):0, outpath);
215 if (P->
flags & DEBUG_GC) {
216 fprintf(stderr,
"\n-- gc check --\n");
217 void *scanptr = (
void *)((
char *)P->
mem->
old_lo + (
sizeof(
PN) * 2));
219 fprintf(stderr,
"%p.vt = %x (%u)\n",
220 scanptr, ((
struct PNObject *)scanptr)->vt,
225 if ((
signed int)vt < 0 || vt >
PN_TUSER) {
226 fprintf(stderr,
"** wrong type for allocated object: %p.vt = %x\n",
233 fprintf(stderr,
"** allocated object goes beyond GC pointer\n");
248 char *
args = strchr(name,
'=');
250 if (args) *args++ =
'\0';
252 pn_printf(P, out,
"load \"%s/%s\"\n", prefix, name);
254 pn_printf(P, out,
"load \"%s\"\n", name);
257 pn_printf(P, out,
"%s(%s)\n", name, args);
263 int main(
int argc,
char *argv[]) {
269 char *compile = NULL;
271 char *addmodules = NULL;
273 #if defined(STATIC) || defined(SANDBOX)
281 for (i = 1; i < argc; i++) {
282 if (!strcmp(argv[i],
"--")) { i++;
break; }
283 if (!strcmp(argv[i],
"-I") || !strcmp(argv[i],
"--inspect")) {
285 if (!strcmp(argv[i],
"-L")) {
289 char *extra_path = &argv[i][2];
294 fprintf(stderr,
"-L missing directory\n");
303 if (!strcmp(argv[i],
"-V") || !strcmp(argv[i],
"--verbose")) {
305 if (!strcmp(argv[i],
"-v") || !strcmp(argv[i],
"--version")) {
307 if (!strcmp(argv[i],
"-h") || !strcmp(argv[i],
"--help")) {
309 if (!strcmp(argv[i],
"-s") || !strcmp(argv[i],
"--stats")) {
311 if (!strcmp(argv[i],
"--check")) { exec =
EXEC_CHECK;
continue; }
312 if (!strncmp(argv[i],
"--compile=", 10)) {
313 exec =
EXEC_COMPILE; compile = &argv[i][10];
continue; }
314 if (!strcmp(argv[i],
"--compile") || !strcmp(argv[i],
"-c")) {
316 if (!strcmp(argv[i],
"-B") || !strcmp(argv[i],
"--bytecode")) {
318 if (!strcmp(argv[i],
"-X") || !strcmp(argv[i],
"--x86")) {
320 if (!strcmp(argv[i],
"--debug") || !strcmp(argv[i],
"-d")) {
321 addmodules =
addmodule(P, addmodules, NULL,
"debug");
323 if (!strcmp(argv[i],
"--debug=")) {
324 addmodules =
addmodule(P, addmodules,
"debug", &argv[i][9]);
326 if (argv[i][0] ==
'-' && argv[i][1] ==
'd') {
327 if (argv[i][2] ==
'=')
328 addmodules =
addmodule(P, addmodules, NULL,
331 addmodules =
addmodule(P, addmodules,
"debug", &argv[i][2]);
333 if (argv[i][0] ==
'-' && argv[i][1] ==
'M') {
334 addmodules =
addmodule(P, addmodules, NULL, &argv[i][2]);
337 if (argv[i][0] ==
'-' && argv[i][1] ==
'D') {
338 if (strchr(&argv[i][2],
'?')) {
339 printf(
"-D debugging flags:\n");
340 printf(
" i inspect\n");
341 printf(
" v verbose\n");
342 printf(
" t trace\n");
343 printf(
" p parse\n");
344 printf(
" P parse verbose\n");
345 printf(
" c compile\n");
346 printf(
" J disassemble Jit code\n");
347 printf(
" G GC (use w/ or wo/ -Dv\n");
352 if (strchr(&argv[i][2],
't')) { P->
flags |= DEBUG_TRACE;
354 if (strchr(&argv[i][2],
'p')) P->
flags |= DEBUG_PARSE;
355 if (strchr(&argv[i][2],
'P')) P->
flags |= DEBUG_PARSE_VERBOSE;
356 if (strchr(&argv[i][2],
'c')) P->
flags |= DEBUG_COMPILE;
357 if (strchr(&argv[i][2],
'J')) P->
flags |= DEBUG_JIT;
358 if (strchr(&argv[i][2],
'G')) P->
flags |= DEBUG_GC;
362 if (argv[i][0] ==
'-') {
363 if (argv[i][1] ==
'e') {
365 if (strlen(argv[i]) == 2) {
367 }
else if (i <= argc) {
379 fprintf(stderr,
"** Unrecognized option: %s\n", argv[i]);
388 if (buf || i < argc) {
405 "load 'readline'\n" \
407 " code = readline('>> ')\n" \
408 " if (not code): \"\\n\" print, break.\n" \
409 " if (code != ''):\n" \
410 " obj = code eval\n" \
411 " if (obj kind == Error):\n" \
412 " obj string print." \
413 " else: ('=> ', obj, \"\\n\") join print.\n" \
418 #if !defined(POTION_JIT_TARGET) || defined(DEBUG)
volatile void * old_lo
the old region (TODO: consider making the old region common to all threads)
PN potion_vm(Potion *, PN, PN, PN, PN_SIZE, PN *volatile)
the bytecode run-loop
PN potion_bytes(Potion *, size_t)
PN potion_closure_new(Potion *P, PN_F meth, PN sig, PN_SIZE extra)
forwarding pointer (in case of reallocation)
bytecode (switch or cgoto)
void potion_destroy(Potion *P)
PN potion_str(Potion *, const char *)
void Potion_Init_readline(Potion *P)
PN potion_gc_actual(Potion *P, PN cl, PN self)
klib hash table library based on double hashing http://en.wikipedia.org/wiki/Double_hashing ...
PN_F potion_jit_proto(Potion *, PN)
exec_mode_t
the interpreter (one per thread, houses its own garbage collector)
a tuple is an array of PNs.
const char potion_banner[]
Potion_Flags flags
vm flags: execution model and debug flags
static void potion_cmd_usage(Potion *P)
PN PN potion_byte_str(Potion *, const char *)
PN potion_source_dumpbc(Potion *P, PN cl, PN proto, PN options)
int main(int argc, char *argv[])
struct PNMemory * mem
allocator/gc
PN potion_source_load(Potion *P, PN cl, PN buf)
const char potion_version[]
the Potion VM instruction set (heavily based on Lua's)
PN potion_source_dump(Potion *P, PN cl, PN self, PN backend, PN options)
standard objects act like C structs the fields are defined by the type and it's a fixed size...
#define POTION_INIT_STACK(x)
DLLEXPORT void Potion_Init_buffile(Potion *P)
the table class, based on khash
void potion_define_global(Potion *P, PN name, PN val)
PN potion_parse(Potion *, PN, char *)
char * addmodule(Potion *P, char *result, char *prefix, char *name)
#define PN_MEMCPY_N(X, Y, T, N)
PN potion_gc_fixed(Potion *P, PN cl, PN self)
PN potion_eval(Potion *P, PN bytes)
static void potion_cmd_version(Potion *P)
JIT if detected at config-time (x86, ppc)
-c stop after compilation
DLLEXPORT void Potion_Init_aio(Potion *P)
PN_SIZE potion_type_size(Potion *P, const struct PNObject *ptr)
Potion * potion_create(void *sp)
the potion API
sanity-check (possible stack overwrites by callcc)
-d: instrumented bytecode (line stepping) or just slow runloop?
the global interpreter state P. currently singleton (not threads yet)
PN_SIZE pn_printf(Potion *, PN, const char *,...) __attribute__((format(printf
static void potion_cmd_stats(Potion *P)
PN potion_strcat(Potion *P, char *str, char *str2)
static PN potion_cmd_exec(Potion *P, PN buf, char *filename, char *compile, char *addcode)
the central table type, based on core/khash.h
_PN(* PN_F)(Potion *, PN, PN,...)
#define potion_send(RCV, MSG, ARGS...)
method caches (more great stuff from ian piumarta)
void potion_p(Potion *P, PN x)
PN potion_gc_reserved(Potion *P, PN cl, PN self)
void potion_loader_add(Potion *P, PN path)
void potion_fatal(char *message)