diff --git a/core/compile.c b/core/compile.c index ab70608..eaeb04d 100644 --- a/core/compile.c +++ b/core/compile.c @@ -18,6 +18,8 @@ #include "opcodes.h" #include "asm.h" +PN potion_proto_load(Potion *P, PN up, u8 pn, u8 **ptr); + #define PN_ASM1(ins, _a) f->asmb = (PN)potion_asm_op(P, (PNAsm *)f->asmb, (u8)ins, (int)_a, 0) #define PN_ASM2(ins, _a, _b) f->asmb = (PN)potion_asm_op(P, (PNAsm *)f->asmb, (u8)ins, (int)_a, (int)_b) @@ -200,7 +202,7 @@ PN potion_proto_string(Potion *P, PN cl, PN self) { potion_source_asmb(P, f, loop, 0, t->a[n], reg); \ } #endif -#define PN_BLOCK(reg, blk, sig) ({ \ +#define PN_BLOCK(reg, blk, sig) do { \ PN block = potion_send(blk, PN_compile, (PN)f, sig); \ PN_SIZE num = PN_PUT(f->protos, block); \ PN_ASM2(OP_PROTO, reg, num); \ @@ -209,32 +211,35 @@ PN potion_proto_string(Potion *P, PN cl, PN self) { if (numup != PN_NONE) PN_ASM2(OP_GETUPVAL, reg, numup); \ else PN_ASM2(OP_GETLOCAL, reg, PN_GET(f->locals, v)); \ }); \ -}) -#define PN_UPVAL(name) ({ \ - PN_SIZE numl = PN_GET(f->locals, name); \ - PN_SIZE numup = PN_NONE; \ - if (numl == PN_NONE) { \ - numup = PN_GET(f->upvals, name); \ - if (numup == PN_NONE) { \ - vPN(Proto) up = f; \ - int depth = 1; \ - while (PN_IS_PROTO(up->source)) { \ - up = (struct PNProto *)up->source; \ - if (PN_NONE != (numup = PN_GET(up->locals, name))) break; \ - depth++; \ - } \ - if (numup != PN_NONE) { \ - up = f; \ - while (depth--) { \ - up->upvals = PN_PUSH(up->upvals, name); \ - up = (struct PNProto *)up->source; \ - } \ - } \ - numup = PN_GET(f->upvals, name); \ - } \ - } \ - numup; \ -}) +} while(0); + +#define PN_UPVAL(name) potion_upval(P, f, name) +inline PN_SIZE potion_upval(Potion *P, struct PNProto * volatile f, PN name) { + PN_SIZE numl = PN_GET(f->locals, name); + PN_SIZE numup = PN_NONE; + if (numl == PN_NONE) { + numup = PN_GET(f->upvals, name); + if (numup == PN_NONE) { + vPN(Proto) up = f; + int depth = 1; + while (PN_IS_PROTO(up->source)) { + up = (struct PNProto *)up->source; + if (PN_NONE != (numup = PN_GET(up->locals, name))) break; + depth++; + } + if (numup != PN_NONE) { + up = f; + while (depth--) { + up->upvals = PN_PUSH(up->upvals, name); + up = (struct PNProto *)up->source; + } + } + numup = PN_GET(f->upvals, name); + } + } + return numup; +} + #define PN_ARG_TABLE(args, reg, inc) potion_arg_asmb(P, f, loop, args, ®, inc) #define SRC_TUPLE_AT(src,i) PN_SRC((PN_TUPLE_AT(PN_S(src,0), i))) @@ -800,7 +805,7 @@ PN potion_sig_compile(Potion *P, vPN(Proto) f, PN src) { vPN(Source) t = PN_SRC(src); if (t->part == AST_LIST && PN_S(t,0) != PN_NIL) { //PN_TUPLE_EACH(PN_S(t,0), i, v, { - ({ struct PNTuple * volatile __tv = ((struct PNTuple *)potion_fwd(PN_S(t,0))); + struct PNTuple * volatile __tv = ((struct PNTuple *)potion_fwd(PN_S(t,0))); if (__tv->len != 0) { DBG_c("--- sig compile ---\n"); PN_SIZE i; @@ -861,7 +866,6 @@ PN potion_sig_compile(Potion *P, vPN(Proto) f, PN src) { } } }}} - }); } return sig; } @@ -906,36 +910,49 @@ PN potion_source_compile(Potion *P, PN cl, PN self, PN source, PN sig) { return (PN)f; } -#define READ_U8(ptr) ({u8 rpu = *ptr; ptr += sizeof(u8); rpu;}) -#define READ_PN(pn, ptr) ({PN rpn = *(PN *)ptr; ptr += pn; rpn;}) -#define READ_CONST(pn, ptr) ({ \ - PN val = READ_PN(pn, ptr); \ - if (PN_IS_PTR(val)) { \ - if (val & 2) { \ - size_t len = ((val ^ 2) >> 4) - 1; \ - val = potion_decimal(P, (char *)ptr, len); \ - ptr += len; \ - } else { \ - size_t len = (val >> 4) - 1; \ - val = PN_STRN((char *)ptr, len); \ - ptr += len; \ - } \ - } \ - val; \ - }) +#define READ_U8(ptr) potion_read_u8(ptr) +inline u8 potion_read_u8(u8 * ptr){ + u8 rpu = *ptr; ptr += sizeof(u8); return rpu; +} + + +#define READ_PN(pn, ptr) potion_read_pn(pn, (PN *)ptr) +inline PN potion_read_pn(PN pn, PN * ptr) { + PN rpn = *ptr; ptr += pn; return rpn; +} + +#define READ_CONST(pn, ptr) potion_read_const(P, pn, ptr) +inline PN potion_read_const(Potion *P, PN pn, u8 *ptr) { + PN val = READ_PN(pn, ptr); + if (PN_IS_PTR(val)) { + if (val & 2) { + size_t len = ((val ^ 2) >> 4) - 1; + val = potion_decimal(P, (char *)ptr, len); + ptr += len; + } else { + size_t len = (val >> 4) - 1; + val = PN_STRN((char *)ptr, len); + ptr += len; + } + } + return val; +} #define READ_TUPLE(ptr) \ long i = 0, count = READ_U8(ptr); \ PN tup = potion_tuple_with_size(P, (PN_SIZE)count); \ for (; i < count; i++) -#define READ_VALUES(pn, ptr) ({ \ - READ_TUPLE(ptr) PN_TUPLE_AT(tup, i) = READ_CONST(pn, ptr); \ - tup; \ - }) -#define READ_PROTOS(pn, ptr) ({ \ - READ_TUPLE(ptr) PN_TUPLE_AT(tup, i) = potion_proto_load(P, (PN)f, pn, &(ptr)); \ - tup; \ - }) +#define READ_VALUES(pn, ptr) potion_read_values(P, pn, ptr) +inline PN potion_read_values(Potion *P, u8 pn, u8 *ptr) { + READ_TUPLE(ptr) PN_TUPLE_AT(tup, i) = READ_CONST(pn, ptr); + return tup; +} + +#define READ_PROTOS(pn, ptr) potion_read_protos(P, f, pn, ptr) +inline PN potion_read_protos(Potion *P, struct PNProto * volatile f, u8 pn, u8 *ptr) { + READ_TUPLE(ptr) PN_TUPLE_AT(tup, i) = potion_proto_load(P, (PN)f, pn, &(ptr)); + return tup; +} // TODO: this byte string is volatile, need to avoid using ptr PN potion_proto_load(Potion *P, PN up, u8 pn, u8 **ptr) { @@ -980,9 +997,9 @@ PN potion_source_load(Potion *P, PN cl, PN buf) { } // TODO: switch to dump methods -#define WRITE_U8(un, ptr) ({*ptr = (u8)un; ptr += sizeof(u8);}) -#define WRITE_PN(pn, ptr) ({*(PN *)ptr = pn; ptr += sizeof(PN);}) -#define WRITE_CONST(val, ptr) ({ \ +#define WRITE_U8(un, ptr) (*ptr = (u8)un, ptr += sizeof(u8)) +#define WRITE_PN(pn, ptr) (*(PN *)ptr = pn, ptr += sizeof(PN)) +#define WRITE_CONST(val, ptr) do { \ if (PN_IS_STR(val)) { \ PN count = (PN_STR_LEN(val)+1) << 4; \ WRITE_PN(count, ptr); \ @@ -998,18 +1015,18 @@ PN potion_source_load(Potion *P, PN cl, PN buf) { PN cval = (PN_IS_PTR(val) ? PN_NIL : val); \ WRITE_PN(cval, ptr); \ } \ - }) +} while (0); #define WRITE_TUPLE(tup, ptr) \ long i = 0, count = PN_TUPLE_LEN(tup); \ WRITE_U8(count, ptr); \ for (; i < count; i++) -#define WRITE_VALUES(tup, ptr) ({ \ +#define WRITE_VALUES(tup, ptr) do { \ WRITE_TUPLE(tup, ptr) WRITE_CONST(PN_TUPLE_AT(tup, i), ptr); \ - }) -#define WRITE_PROTOS(tup, ptr) ({ \ + } while (0); +#define WRITE_PROTOS(tup, ptr) do { \ WRITE_TUPLE(tup, ptr) ptr += potion_proto_dumpbc(P, PN_TUPLE_AT(tup, i), \ out, (char *)ptr - PN_STR_PTR(out)); \ - }) + } while (0); ///\memberof PNProto /// compile to bytecode diff --git a/core/internal.h b/core/internal.h index aab5c7d..df2d658 100644 --- a/core/internal.h +++ b/core/internal.h @@ -37,7 +37,7 @@ typedef unsigned char u8; (N)->siz = sizeof(*(N)->ptr) * S; \ (N)->len = 0 -#define PN_FLEX_NEEDS(X, N, V, T, S) ({ \ +#define PN_FLEX_NEEDS(X, N, V, T, S) do { \ PN_SIZE capa = (N)->siz / sizeof(*(N)->ptr); \ if (capa < (N)->len + X) { \ while (capa < (N)->len + X) \ @@ -46,24 +46,24 @@ typedef unsigned char u8; PN_REALLOC(N, V, T, capa); \ (N)->siz = capa; \ } \ -}) - -#define PN_ATOI(X,N,B) ({ \ - char *Ap = X; \ - long Ai = 0; \ - size_t Al = N; \ - while (Al--) { \ - if ((*Ap >= '0') && (*Ap <= '9')) \ - Ai = (Ai * B) + (*Ap - '0'); \ - else if ((*Ap >= 'A') && (*Ap <= 'F')) \ - Ai = (Ai * B) + ((*Ap - 'A') + 10); \ - else if ((*Ap >= 'a') && (*Ap <= 'f')) \ - Ai = (Ai * B) + ((*Ap - 'a') + 10); \ - else break; \ - Ap++; \ - } \ - Ai; \ -}) +} while(0); + + +#define PN_ATOI(X,N,B) potion_atoi(X, N, B) +inline static long potion_atoi(char *Ap, size_t Al, const long B) { + long Ai = 0; + while (Al--) { + if ((*Ap >= '0') && (*Ap <= '9')) + Ai = (Ai * B) + (*Ap - '0'); + else if ((*Ap >= 'A') && (*Ap <= 'F')) + Ai = (Ai * B) + ((*Ap - 'A') + 10); + else if ((*Ap >= 'a') && (*Ap <= 'f')) + Ai = (Ai * B) + ((*Ap - 'a') + 10); + else break; + Ap++; + } + return Ai; +} /// .pnb binary dump header struct PNBHeader { diff --git a/core/potion.h b/core/potion.h index 1894aae..eca2465 100644 --- a/core/potion.h +++ b/core/potion.h @@ -57,6 +57,11 @@ and optionally args, statically typed via signature strings. # include #endif +#ifdef _MSC_VER +typedef unsigned short _mode_t; +typedef _mode_t mode_t; +#endif + #define _XSTR(s) _STR(s) #define _STR(s) #s #define POTION_VERSION _XSTR(POTION_MAJOR) "." _XSTR(POTION_MINOR) @@ -241,14 +246,14 @@ struct PNVtable; #define PN_GET_TUPLE(t) ((struct PNTuple *)potion_fwd((PN)t)) #define PN_TUPLE_LEN(t) PN_GET_TUPLE(t)->len #define PN_TUPLE_AT(t, n) PN_GET_TUPLE(t)->set[n] -#define PN_TUPLE_COUNT(T, I, B) ({ \ +#define PN_TUPLE_COUNT(T, I, B) do { \ struct PNTuple * volatile __t##I = PN_GET_TUPLE(T); \ if (__t##I->len != 0) { \ PN_SIZE I; \ for (I = 0; I < __t##I->len; I++) B \ } \ - }) -#define PN_TUPLE_EACH(T, I, V, B) ({ \ + } while(0); +#define PN_TUPLE_EACH(T, I, V, B) do { \ struct PNTuple * volatile __t##V = PN_GET_TUPLE(T); \ if (__t##V->len != 0) { \ PN_SIZE I; \ @@ -257,7 +262,7 @@ struct PNVtable; B \ } \ } \ - }) + } while(0); /// /// standard objects act like C structs @@ -688,13 +693,18 @@ static inline struct PNData *potion_data_alloc(Potion *P, int siz) { /// method caches /// (more great stuff from ian piumarta) /// -#define potion_send(RCV, MSG, ARGS...) ({ \ + +#ifndef _MSC_VER +# define potion_send(RCV, MSG, ARGS...) ({ \ PN r = (PN)(RCV); \ PN c = potion_bind(P, r, (MSG)); \ if (PN_IS_CLOSURE(c)) \ c = ((struct PNClosure *)c)->method(P, c, r, ##ARGS); \ c; \ }) +#else +# define potion_send(RCV, MSG, ...) potion_send_real(P, RCV, MSG, __VA_ARGS__) +#endif #define potion_method(RCV, MSG, FN, SIG) \ potion_send(RCV, PN_def, potion_str(P, MSG), PN_FUNC(FN, SIG)) @@ -834,4 +844,8 @@ PN_F potion_jit_proto(Potion *, PN); PN potion_load(Potion *, PN, PN, PN); PN potion_class_find(Potion *, PN); +#ifdef _MSC_VER +PN potion_send_real(Potion *P, PN rcv, PN msg, ...); +#endif + #endif diff --git a/front/potion.c b/front/potion.c index 26d820e..4f8762a 100644 --- a/front/potion.c +++ b/front/potion.c @@ -8,7 +8,9 @@ #include #include #include -#include +#ifndef _MSC_VER +# include +#endif #include "potion.h" #include "internal.h" @@ -392,3 +394,27 @@ int main(int argc, char *argv[]) { #endif return 0; } + +#ifdef _MSC_VER +PN potion_send_real(Potion * P, PN rcv, PN msg, ...) { + PN c = potion_bind(P, rcv, msg); + if (PN_IS_CLOSURE(c)) { + void * method = ((struct PNClosure *)c)->method; + //untested + __asm { + mov eax, rcv + mov msg, eax + mov eax, c + mov rcv, eax + //Potion * P remains unmodified + mov eax, method + mov esp, ebp + pop ebp + //head of stack is return address now, simulating call + jmp eax + }; + //c = ((struct PNClosure *)c)->method(P, c, rcv, ##ARGS); + } + return c; +} +#endif