interim commit of various experiments

This commit is contained in:
hyunghwan.chung
2017-06-16 09:45:22 +00:00
parent 9b3c3007fd
commit d311c7cb6e
20 changed files with 444 additions and 1463 deletions

View File

@ -273,14 +273,18 @@ static MOO_INLINE int is_binselchar (moo_ooci_t c)
{
/*
* binary-selector-character :=
* '%' | '&' | '*' | '+' | '-' |
* '/' | '<' | '>' | '=' | '?' |
* '@' | '\' | '~' | '|'
* '&' | '*' | '+' | '-' | '/' |
* '<' | '>' | '=' | '?' | '@' |
* '\' | '~' | '|'
*
* - a comma is special in moo and doesn't form a binary selector.
* - a percent sign is special in moo and doesn't form a binary selector.
* - an exclamation mark is excluded intentioinally because i can't tell
* the method symbol #! from the comment introducer #!.
*/
switch (c)
{
case '%':
case '&':
case '*':
case '+':
@ -1652,11 +1656,6 @@ retry:
SET_TOKEN_TYPE (moo, MOO_IOTOK_ASSIGN);
ADD_TOKEN_CHAR (moo, c);
}
else if (c == '{')
{
SET_TOKEN_TYPE (moo, MOO_IOTOK_DICBRACE);
ADD_TOKEN_CHAR (moo, c);
}
else
{
unget_char (moo, &moo->c->lxc);
@ -1708,6 +1707,34 @@ retry:
SET_TOKEN_TYPE (moo, MOO_IOTOK_SEMICOLON);
goto single_char_token;
case '%':
SET_TOKEN_TYPE (moo, MOO_IOTOK_PERCENT);
ADD_TOKEN_CHAR(moo, c);
GET_CHAR_TO (moo, c);
/* TODO: byte array expression token -> %[ */
if (c == '(')
{
/* %( - array expression */
ADD_TOKEN_CHAR(moo, c);
SET_TOKEN_TYPE (moo, MOO_IOTOK_PERCPAREN);
}
else if (c == '{')
{
/* %{ - dictionary expression */
ADD_TOKEN_CHAR(moo, c);
SET_TOKEN_TYPE (moo, MOO_IOTOK_PERCBRACE);
}
else
{
/* NOTE the percent sign not followed by ( or } is
* meaningless at this moment. however, i return
* it as a token so that the compiler anyway
* will fail eventually */
unget_char (moo, &moo->c->lxc);
}
break;
case '#':
ADD_TOKEN_CHAR(moo, c);
GET_CHAR_TO (moo, c);
@ -1720,19 +1747,14 @@ retry:
case '(':
/* #( - array literal */
ADD_TOKEN_CHAR(moo, c);
SET_TOKEN_TYPE (moo, MOO_IOTOK_APAREN);
SET_TOKEN_TYPE (moo, MOO_IOTOK_HASHPAREN);
break;
case '[':
/* #[ - byte array literal */
ADD_TOKEN_CHAR(moo, c);
SET_TOKEN_TYPE (moo, MOO_IOTOK_BABRACK);
SET_TOKEN_TYPE (moo, MOO_IOTOK_HASHBRACK);
break;
case '{':
/* #{ - array expression */
ADD_TOKEN_CHAR(moo, c);
SET_TOKEN_TYPE (moo, MOO_IOTOK_ABRACE);
break;
case '\'':
@ -1923,7 +1945,7 @@ retry:
break;
}
MOO_DEBUG2 (moo, "TOKEN: [%.*js]\n", (moo_ooi_t)moo->c->tok.name.len, moo->c->tok.name.ptr);
MOO_DEBUG3 (moo, "TOKEN: [%.*js] %d\n", (moo_ooi_t)moo->c->tok.name.len, moo->c->tok.name.ptr, (int)moo->c->tok.type);
return 0;
}
@ -4604,7 +4626,7 @@ static int compile_byte_array_literal (moo_t* moo)
moo_oow_t index;
MOO_ASSERT (moo, moo->c->balit.count == 0);
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_BABRACK);
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_HASHBRACK);
if (read_byte_array_literal(moo, &lit) <= -1 ||
add_literal(moo, lit, &index) <= -1 ||
@ -4620,7 +4642,7 @@ static int compile_array_literal (moo_t* moo)
moo_oow_t index;
MOO_ASSERT (moo, moo->c->arlit.count == 0);
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_APAREN);
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_HASHPAREN);
if (read_array_literal(moo, 0, &lit) <= -1 ||
add_literal(moo, lit, &index) <= -1 ||
@ -4635,7 +4657,7 @@ static int compile_array_expression (moo_t* moo)
moo_oow_t maip;
moo_ioloc_t aeloc;
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_ABRACE);
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_PERCPAREN);
maip = moo->c->mth.code.len;
if (emit_single_param_instruction(moo, BCODE_MAKE_ARRAY, 0) <= -1) return -1;
@ -4659,7 +4681,7 @@ static int compile_array_expression (moo_t* moo)
return -1;
}
if (TOKEN_TYPE(moo) == MOO_IOTOK_RBRACE) break;
if (TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN) break;
if (TOKEN_TYPE(moo) != MOO_IOTOK_COMMA)
{
@ -4689,7 +4711,7 @@ static int compile_dictionary_expression (moo_t* moo)
{
moo_oow_t mdip;
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_DICBRACE);
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_PERCBRACE);
GET_TOKEN (moo); /* read a token after :{ */
@ -4931,21 +4953,21 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
GET_TOKEN (moo);
break;
case MOO_IOTOK_BABRACK: /* #[ */
case MOO_IOTOK_HASHBRACK: /* #[ */
/*GET_TOKEN (moo);*/
if (compile_byte_array_literal(moo) <= -1) return -1;
break;
case MOO_IOTOK_APAREN: /* #( */
case MOO_IOTOK_HASHPAREN: /* #( */
/*GET_TOKEN (moo);*/
if (compile_array_literal(moo) <= -1) return -1;
break;
case MOO_IOTOK_ABRACE: /* #{ */
case MOO_IOTOK_PERCPAREN: /* %( */
if (compile_array_expression(moo) <= -1) return -1;
break;
case MOO_IOTOK_DICBRACE: /* :{ */
case MOO_IOTOK_PERCBRACE: /* %{ */
if (compile_dictionary_expression(moo) <= -1) return -1;
break;
@ -6939,7 +6961,6 @@ static int make_defined_class (moo_t* moo)
if (make_getters_and_setters (moo) <= -1) return -1;
if (just_made)
{
@ -7456,6 +7477,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
* inherit so that the inherited methods work well when they
* access the trailer space */
moo->c->cls.self_oop->trsize = ((moo_oop_class_t)moo->c->cls.self_oop->superclass)->trsize;
moo->c->cls.self_oop->trgc = ((moo_oop_class_t)moo->c->cls.self_oop->superclass)->trgc;
}
}
@ -7614,10 +7636,9 @@ static moo_oop_t token_to_literal (moo_t* moo, int rdonly)
}
/* [NOTE] i don't mark RDONLY on a value resolved via an identifier */
}
case MOO_IOTOK_BABRACK: /* #[ - byte array literal parenthesis */
case MOO_IOTOK_HASHBRACK: /* #[ - byte array literal parenthesis */
{
moo_oop_t lit;
if (read_byte_array_literal(moo, &lit) <= -1) return MOO_NULL;
@ -7629,7 +7650,7 @@ static moo_oop_t token_to_literal (moo_t* moo, int rdonly)
return lit;
}
case MOO_IOTOK_APAREN: /* #( - array literal parenthesis */
case MOO_IOTOK_HASHPAREN: /* #( - array literal parenthesis */
{
moo_oop_t lit;
if (read_array_literal(moo, rdonly, &lit) <= -1) return MOO_NULL;

View File

@ -47,7 +47,7 @@ static moo_ooch_t errstr_13[] = {'n','o','t',' ','a',' ','d','i','r','e','c','t'
static moo_ooch_t errstr_14[] = {'i','n','t','e','r','r','u','p','t','e','d','\0'};
static moo_ooch_t errstr_15[] = {'p','i','p','e',' ','e','r','r','o','r','\0'};
static moo_ooch_t errstr_16[] = {'r','e','s','o','u','r','c','e',' ','t','e','m','p','o','r','a','r','i','l','y',' ','u','n','a','v','a','i','l','a','b','l','e','\0'};
static moo_ooch_t errstr_17[] = {'d','a','t','a',' ','t','o','o',' ','l','a','r','g','e','\0'};
static moo_ooch_t errstr_17[] = {'d','a','t','a',' ','n','o','t',' ','a','v','a','i','l','a','b','l','e','\0'};
static moo_ooch_t errstr_18[] = {'m','e','s','s','a','g','e',' ','r','e','c','e','i','v','e','r',' ','e','r','r','o','r','\0'};
static moo_ooch_t errstr_19[] = {'m','e','s','s','a','g','e',' ','s','e','n','d','i','n','g',' ','e','r','r','o','r','\0'};
static moo_ooch_t errstr_20[] = {'w','r','o','n','g',' ','n','u','m','b','e','r',' ','o','f',' ','a','r','g','u','m','e','n','t','s','\0'};

View File

@ -232,6 +232,18 @@ static int ignite_1 (moo_t* moo)
!moo->_small_pointer || !moo->_system) return -1;
MOO_OBJ_SET_CLASS (moo->_nil, (moo_oop_t)moo->_undefined_object);
#if defined(MOO_USE_METHOD_TRAILER)
/* an instance of a method class stores byte codes in the trailer space
* when compiled with MOO_USE_METHOD_TRAILER. unlike other classes with
* trailer size set, the size of the trailer space is not really determined
* by the traailer size set in the class. the compiler determines the
* actual size of the trailer space depending on the byte codes generated.
* i should set the following fields to avoid confusion at the GC phase. */
moo->_method->trsize = MOO_SMOOI_TO_OOP(0);
moo->_method->trgc = MOO_SMPTR_TO_OOP(0);
#endif
return 0;
}
@ -419,7 +431,6 @@ static MOO_INLINE moo_oow_t get_payload_bytes (moo_t* moo, moo_oop_t oop)
{
moo_oow_t nbytes_aligned;
#if defined(MOO_USE_METHOD_TRAILER)
if (MOO_OBJ_GET_FLAGS_TRAILER(oop))
{
moo_oow_t nbytes;
@ -446,12 +457,9 @@ static MOO_INLINE moo_oow_t get_payload_bytes (moo_t* moo, moo_oop_t oop)
}
else
{
#endif
/* calculate the payload size in bytes */
nbytes_aligned = MOO_ALIGN (MOO_OBJ_BYTESOF(oop), MOO_SIZEOF(moo_oop_t));
#if defined(MOO_USE_METHOD_TRAILER)
}
#endif
return nbytes_aligned;
}
@ -517,7 +525,6 @@ static moo_uint8_t* scan_new_heap (moo_t* moo, moo_uint8_t* ptr)
oop = (moo_oop_t)ptr;
#if defined(MOO_USE_METHOD_TRAILER)
if (MOO_OBJ_GET_FLAGS_TRAILER(oop))
{
moo_oow_t nbytes;
@ -532,11 +539,8 @@ static moo_uint8_t* scan_new_heap (moo_t* moo, moo_uint8_t* ptr)
}
else
{
#endif
nbytes_aligned = MOO_ALIGN (MOO_OBJ_BYTESOF(oop), MOO_SIZEOF(moo_oop_t));
#if defined(MOO_USE_METHOD_TRAILER)
}
#endif
MOO_OBJ_SET_CLASS (oop, moo_moveoop(moo, (moo_oop_t)MOO_OBJ_GET_CLASS(oop)));
if (MOO_OBJ_GET_FLAGS_TYPE(oop) == MOO_OBJ_TYPE_OOP)
@ -566,6 +570,25 @@ static moo_uint8_t* scan_new_heap (moo_t* moo, moo_uint8_t* ptr)
}
}
if (MOO_OBJ_GET_FLAGS_TRAILER(oop))
{
moo_oop_class_t c;
moo_trgc_t trgc;
/* i use SMPTR(0) to indicate no trailer gc callback.
* i don't use moo->_nil because c->trgc field may not have
* been updated to a new nil address while moo->_nil could
* have been updated in the process of garbage collection.
* this comment will be invalidated when moo->_nil is
* stored in a permanent heap or GC gets changed to
* a non-copying collector. no matter what GC implementation
* i choose, using SMPTR(0) for this purpose is safe. */
c = MOO_OBJ_GET_CLASS(oop);
MOO_ASSERT(moo, MOO_OOP_IS_SMPTR(c->trgc));
trgc = MOO_OOP_TO_SMPTR(c->trgc);
if (trgc) trgc (moo, oop);
}
ptr = ptr + MOO_SIZEOF(moo_obj_t) + nbytes_aligned;
}

View File

@ -345,8 +345,9 @@ struct moo_iotok_t
MOO_IOTOK_IDENT_DOTTED,
MOO_IOTOK_BINSEL,
MOO_IOTOK_KEYWORD,
MOO_IOTOK_ASSIGN,
MOO_IOTOK_COLON,
MOO_IOTOK_ASSIGN, /* := */
MOO_IOTOK_COLON, /* : */
MOO_IOTOK_PERCENT, /* % */
MOO_IOTOK_RETURN, /* ^ */
MOO_IOTOK_LOCAL_RETURN, /* ^^ */
MOO_IOTOK_LBRACE,
@ -355,10 +356,10 @@ struct moo_iotok_t
MOO_IOTOK_RBRACK,
MOO_IOTOK_LPAREN,
MOO_IOTOK_RPAREN,
MOO_IOTOK_APAREN, /* #( - array literal */
MOO_IOTOK_BABRACK, /* #[ - byte array literal */
MOO_IOTOK_ABRACE, /* #{ - array expression */
MOO_IOTOK_DICBRACE, /* :{ - dictionary expression */
MOO_IOTOK_HASHPAREN, /* #( - array literal */
MOO_IOTOK_HASHBRACK, /* #[ - byte array literal */
MOO_IOTOK_PERCPAREN, /* %{ - array expression */
MOO_IOTOK_PERCBRACE, /* %{ - dictionary expression */
MOO_IOTOK_PERIOD,
MOO_IOTOK_COMMA,
MOO_IOTOK_SEMICOLON
@ -1009,14 +1010,12 @@ moo_oop_t moo_allocoopobj (
moo_oow_t size
);
#if defined(MOO_USE_METHOD_TRAILER)
moo_oop_t moo_allocoopobjwithtrailer (
moo_t* moo,
moo_oow_t size,
const moo_oob_t* tptr,
moo_oow_t tlen
);
#endif
moo_oop_t moo_alloccharobj (
moo_t* moo,

View File

@ -829,23 +829,35 @@ int moo_genpfmethods (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class, const
moo_pfbase_t* moo_findpfbase (moo_t* moo, moo_pfinfo_t* pfinfo, moo_oow_t pfcount, const moo_ooch_t* name, moo_oow_t namelen)
{
moo_oow_t left, right, mid;
int n;
/* binary search */
#if 0
/* [NOTE] this algorithm is NOT underflow safe with moo_oow_t types */
int left, right, mid;
left = 0; right = pfcount - 1;
while (left <= right)
for (left = 0, right = pfcount - 1; left <= right; )
{
/*mid = (left + right) / 2;*/
mid = left + ((right - left) / 2);
n = moo_compoocharsoocstr (name, namelen, pfinfo[mid].mthname);
if (n < 0) right = mid - 1;
if (n < 0) right = mid - 1; /* this substraction can make right negative. so i can't use moo_oow_t for the variable */
else if (n > 0) left = mid + 1;
else return &pfinfo[mid].base;
}
#else
/* [NOTE] this algorithm is underflow safe with moo_oow_t types */
moo_oow_t base, mid, lim;
for (base = 0, lim = pfcount; lim > 0; lim >>= 1)
{
mid = base + (lim >> 1);
n = moo_compoocharsoocstr (name, namelen, pfinfo[mid].mthname);
if (n == 0) return &pfinfo[mid].base;
if (n > 0) { base = mid + 1; lim--; }
}
#endif
moo_seterrnum (moo, MOO_ENOENT);
return MOO_NULL;
@ -853,14 +865,14 @@ moo_pfbase_t* moo_findpfbase (moo_t* moo, moo_pfinfo_t* pfinfo, moo_oow_t pfcoun
/* -------------------------------------------------------------------------- */
int moo_setclasstrsize (moo_t* moo, moo_oop_class_t _class, moo_oow_t size)
int moo_setclasstrsize (moo_t* moo, moo_oop_class_t _class, moo_oow_t size, moo_trgc_t trgc)
{
moo_oop_class_t sc;
moo_oow_t spec;
MOO_ASSERT (moo, MOO_CLASSOF(moo, _class) == moo->_class);
MOO_ASSERT (moo, size <= MOO_SMOOI_MAX);
MOO_ASSERT (moo, size <= MOO_SMOOI_MAX);
if (_class == moo->_method)
{
/* the bytes code emitted by the compiler go to the trailer part
@ -884,12 +896,14 @@ int moo_setclasstrsize (moo_t* moo, moo_oop_class_t _class, moo_oow_t size)
if (_class->trsize != moo->_nil)
{
MOO_ASSERT (moo, _class->trgc != moo->_nil);
MOO_DEBUG3 (moo, "Not allowed to re-set trailer size to %zu on the %.*js class\n",
size,
MOO_OBJ_GET_SIZE(_class->name),
MOO_OBJ_GET_CHAR_SLOT(_class->name));
goto eperm;
}
MOO_ASSERT (moo, _class->trgc == moo->_nil);
sc = (moo_oop_class_t)_class->superclass;
if (MOO_OOP_IS_SMOOI(sc->trsize) && size < MOO_OOP_TO_SMOOI(sc->trsize))
@ -906,10 +920,13 @@ int moo_setclasstrsize (moo_t* moo, moo_oop_class_t _class, moo_oow_t size)
/* you can only set the trailer size once when it's not set yet */
_class->trsize = MOO_SMOOI_TO_OOP(size);
MOO_DEBUG3 (moo, "Set trailer size to %zu on the %.*js class\n",
_class->trgc = MOO_SMPTR_TO_OOP(trgc); /* i don't replace NULL by nil for GC safety. */
MOO_DEBUG5 (moo, "Set trailer size to %zu on the %.*js class with gc callback of %p(%p)\n",
size,
MOO_OBJ_GET_SIZE(_class->name),
MOO_OBJ_GET_CHAR_SLOT(_class->name));
MOO_OBJ_GET_CHAR_SLOT(_class->name),
MOO_SMPTR_TO_OOP(trgc), trgc);
return 0;
eperm:

View File

@ -64,7 +64,7 @@ enum moo_errnum_t
MOO_EPIPE,
MOO_EAGAIN,
MOO_ETOOBIG, /**< data too large */
MOO_ENOAVAIL, /**< data not available*/
MOO_EMSGRCV, /**< mesasge receiver error */
MOO_EMSGSND, /**< message sending error. even doesNotUnderstand: is not found */
MOO_ENUMARGS, /**< wrong number of arguments */
@ -494,7 +494,7 @@ struct moo_dic_t
typedef struct moo_nsdic_t moo_nsdic_t;
typedef struct moo_nsdic_t* moo_oop_nsdic_t;
#define MOO_CLASS_NAMED_INSTVARS 17
#define MOO_CLASS_NAMED_INSTVARS 18
typedef struct moo_class_t moo_class_t;
typedef struct moo_class_t* moo_oop_class_t;
@ -538,6 +538,7 @@ struct moo_class_t
moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */
moo_oop_t trsize; /* trailer size for new instances */
moo_oop_t trgc; /* trailer gc callback */
/* [0] - initial values for instance variables of new instances
* [1] - initial values for class instance variables */
@ -980,7 +981,6 @@ struct moo_mod_data_t
};
typedef struct moo_mod_data_t moo_mod_data_t;
struct moo_sbuf_t
{
moo_ooch_t* ptr;
@ -989,6 +989,9 @@ struct moo_sbuf_t
};
typedef struct moo_sbuf_t moo_sbuf_t;
/* special callback to be called for trailer */
typedef void (*moo_trgc_t) (moo_t* moo, moo_oop_t obj);
/* =========================================================================
* MOO VM
* ========================================================================= */
@ -1623,7 +1626,8 @@ MOO_EXPORT moo_oop_t moo_findclass (
MOO_EXPORT int moo_setclasstrsize (
moo_t* moo,
moo_oop_class_t _class,
moo_oow_t size
moo_oow_t size,
moo_trgc_t trgc
);
MOO_EXPORT void* moo_getobjtrailer (

View File

@ -78,7 +78,6 @@ moo_oop_t moo_allocoopobj (moo_t* moo, moo_oow_t size)
return (moo_oop_t)hdr;
}
#if defined(MOO_USE_METHOD_TRAILER)
moo_oop_t moo_allocoopobjwithtrailer (moo_t* moo, moo_oow_t size, const moo_oob_t* bptr, moo_oow_t blen)
{
moo_oop_oop_t hdr;
@ -112,7 +111,6 @@ moo_oop_t moo_allocoopobjwithtrailer (moo_t* moo, moo_oow_t size, const moo_oob_
return (moo_oop_t)hdr;
}
#endif
static MOO_INLINE moo_oop_t alloc_numeric_array (moo_t* moo, const void* ptr, moo_oow_t len, moo_obj_type_t type, moo_oow_t unit, int extra)
{