gave up the idea of constants.

enhanced namespace handling with selfns and self
uniformified identifier handling related to namespacing
This commit is contained in:
hyunghwan.chung 2017-06-01 15:42:05 +00:00
parent 36c48a8daf
commit 34a5e0cab8
7 changed files with 428 additions and 433 deletions

View File

@ -6,7 +6,7 @@ class(#pointer,#limited) Class(Apex)
{
var spec, selfspec, superclass, subclasses, name, modname.
var instvars, classinstvars, classvars, pooldics.
var instmthdic, classmthdic, nsup, nsdic, cdic.
var instmthdic, classmthdic, nsup, nsdic.
var trsize, initv, initv_ci.
method(#class) initialize { ^self }

View File

@ -217,13 +217,13 @@ extend MethodContext
method isExceptionContext
{
## 12 - MOO_METHOD_PREAMBLE_EXCEPTION in VM.
^self.method preambleCode == 12.
^self.method preambleCode == 13.
}
method isEnsureContext
{
## 13 - MOO_METHOD_PREAMBLE_ENSURE in VM.
^self.method preambleCode == 13
^self.method preambleCode == 14
}
method ensureBlock
@ -236,7 +236,7 @@ extend MethodContext
* instance variables of the method context. As MethodContex has
* 8 instance variables, the ensure block must be at the 9th position
* which translates to index 8 *)
^if (self.method preambleCode == 13) { self basicAt: 8 } else { nil }
^if (self.method preambleCode == 14) { self basicAt: 8 } else { nil }
}

View File

@ -67,7 +67,9 @@ enum var_type_t
VAR_GLOBAL,
VAR_ARGUMENT,
VAR_TEMPORARY
VAR_TEMPORARY,
VAR_LITERAL /* used when compiling pooldic elements only */
};
typedef enum var_type_t var_type_t;
@ -75,8 +77,12 @@ struct var_info_t
{
var_type_t type;
moo_ooi_t pos; /* not used for VAR_GLOBAL */
moo_oop_class_t cls; /* useful if type is VAR_CLASS. note MOO_NULL indicates the self class. */
moo_oop_class_t cls; /* useful if type is VAR_CLASS(class variable). note MOO_NULL indicates the self class. */
union
{
moo_oop_association_t gbl; /* used for VAR_GLOBAL only */
moo_oop_t lit; /* used for VAR_LITERAL only */
} u;
};
typedef struct var_info_t var_info_t;
@ -91,8 +97,6 @@ static struct voca_t
{ 5, { 'c','l','a','s','s' } },
{ 6, { '#','c','l','a','s','s' } },
{ 10, { '#','c','l','a','s','s','i','n','s','t' } },
{ 5, { 'c','o','n','s','t' } },
{ 8, { 'c','o','n','s','t','a','n','t' } },
{ 8, { 'c','o','n','t','i','n','u','e' } },
{ 3, { 'd','c','l' } },
{ 2, { 'd','o' } },
@ -123,6 +127,7 @@ static struct voca_t
{ 10, { 'p','r','i','m','i','t','i','v','e',':' } },
{ 10, { '#','p','r','i','m','i','t','i','v','e' } },
{ 4, { 's','e','l','f' } },
{ 6, { 's','e','l','f','n','s' } },
{ 5, { 's','u','p','e','r' } },
{ 11, { 't','h','i','s','C','o','n','t','e','x','t' } },
{ 11, { 't','h','i','s','P','r','o','c','e','s','s' } },
@ -151,8 +156,6 @@ enum voca_id_t
VOCA_CLASS,
VOCA_CLASS_S,
VOCA_CLASSINST_S,
VOCA_CONST,
VOCA_CONSTANT,
VOCA_CONTINUE,
VOCA_DCL,
VOCA_DO,
@ -183,6 +186,7 @@ enum voca_id_t
VOCA_PRIMITIVE_COLON,
VOCA_PRIMITIVE_S,
VOCA_SELF,
VOCA_SELFNS,
VOCA_SUPER,
VOCA_THIS_CONTEXT,
VOCA_THIS_PROCESS,
@ -210,6 +214,7 @@ static int compile_method_statement (moo_t* moo);
static int compile_method_expression (moo_t* moo, int pop);
static int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index);
static moo_oop_t token_to_literal (moo_t* moo, int rdonly);
static moo_oop_t find_element_in_compiling_pooldic (moo_t* moo, const moo_oocs_t* name);
static MOO_INLINE int is_spacechar (moo_ooci_t c)
{
@ -328,6 +333,7 @@ static int is_reserved_word (const moo_oocs_t* ucs)
VOCA_ERROR,
VOCA_THIS_CONTEXT,
VOCA_THIS_PROCESS,
VOCA_SELFNS,
VOCA_IF,
VOCA_ELSE,
VOCA_ELSIF,
@ -1128,6 +1134,10 @@ static int get_ident (moo_t* moo, moo_ooci_t char_read_ahead)
{
SET_TOKEN_TYPE (moo, MOO_IOTOK_THIS_PROCESS);
}
else if (is_token_word(moo, VOCA_SELFNS))
{
SET_TOKEN_TYPE (moo, MOO_IOTOK_SELFNS);
}
else if (is_token_word(moo, VOCA_IF))
{
SET_TOKEN_TYPE (moo, MOO_IOTOK_IF);
@ -2594,11 +2604,11 @@ static int set_class_level_variable_initv (moo_t* moo, var_type_t var_type, moo_
{
moo_oow_t newcapa, oldcapa;
/*moo_oow_t i;*/
moo_oop_t* tmp;
moo_initv_t* tmp;
oldcapa = moo->c->cls.var[var_type].initv_capa;
newcapa = MOO_ALIGN_POW2 ((var_index + 1), 32);
tmp = moo_reallocmem (moo, moo->c->cls.var[var_type].initv, newcapa * MOO_SIZEOF(moo_oop_t));
tmp = moo_reallocmem (moo, moo->c->cls.var[var_type].initv, newcapa * MOO_SIZEOF(*tmp));
if (!tmp) return -1;
/*for (i = moo->c->cls.var[var_type].initv_capa; i < newcapa; i++) tmp[i] = MOO_NULL;*/
@ -2613,12 +2623,16 @@ static int set_class_level_variable_initv (moo_t* moo, var_type_t var_type, moo_
moo_oow_t i;
for (i = moo->c->cls.var[var_type].initv_count; i < var_index; i++)
moo->c->cls.var[var_type].initv[i] = MOO_NULL;
{
moo->c->cls.var[var_type].initv[i].v = MOO_NULL;
moo->c->cls.var[var_type].initv[i].flags = 0;
}
moo->c->cls.var[var_type].initv_count = var_index + 1;
}
moo->c->cls.var[var_type].initv[var_index] = initv;
moo->c->cls.var[var_type].initv[var_index].v = initv;
moo->c->cls.var[var_type].initv[var_index].flags = 0; /* TODO: set flags properly */
return 0;
}
@ -2674,6 +2688,7 @@ static moo_ooi_t find_class_level_variable (moo_t* moo, moo_oop_class_t self, co
if (find_word_in_string(&hs, name, &pos) >= 0)
{
super = self->superclass;
MOO_ASSERT (moo, super == moo->c->cls.super_oop);
/* 'self' may be MOO_NULL if MOO_NULL has been given for it.
* the caller must take good care when interpreting the meaning of
@ -2684,6 +2699,7 @@ static moo_ooi_t find_class_level_variable (moo_t* moo, moo_oop_class_t self, co
}
super = self->superclass;
MOO_ASSERT (moo, super == moo->c->cls.super_oop);
}
else
{
@ -2694,7 +2710,7 @@ static moo_ooi_t find_class_level_variable (moo_t* moo, moo_oop_class_t self, co
if (find_word_in_string(&moo->c->cls.var[index].str, name, &pos) >= 0)
{
super = moo->c->cls.super_oop;
var->cls = self;
var->cls = MOO_NULL; /* the current class being compiled */
goto done;
}
}
@ -3276,11 +3292,11 @@ if super is variable-nonpointer, no instance variable is allowed.
GET_TOKEN (moo);
/* [NOTE] default value assignment. only a literal is allowed
/* [NOTE] default value assignment. only a literal is allowed.
* the initial values for instance variables and
* class instance variables are set to read-only.
* this is likely to change if the actual initial
* value assignment upon instantiation employes
* I may change this if i get the actual initial
* value assignment upon instantiation to employ
* deep-copying in moo_instantiate() and in the compiler. */
lit = token_to_literal (moo, dcl_type != VAR_CLASS);
if (!lit) return -1;
@ -3433,139 +3449,6 @@ static int compile_class_level_imports (moo_t* moo)
return 0;
}
static int compile_class_level_constants (moo_t* moo)
{
#if 0
if (moo->c->cls.self_oop)
{
/* the current class has been created already */
}
else
{
}
#endif
if (TOKEN_TYPE(moo) == MOO_IOTOK_LPAREN)
{
/* process variable declaration modifiers */
GET_TOKEN (moo);
if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN)
{
do
{
/* [NOTE] no modifier is supported for constant declarations.
* the following code is for consistency sake only */
if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_RPAREN)
{
/* no modifier is present */
set_syntax_error (moo, MOO_SYNERR_MODIFIER, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
else
{
/* invalid modifier */
set_syntax_error (moo, MOO_SYNERR_MODIFIERINVAL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
if (TOKEN_TYPE(moo) != MOO_IOTOK_COMMA) break; /* hopefully ) */
GET_TOKEN (moo); /* get the token after , */
}
while (1);
}
if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN)
{
/* ) expected */
set_syntax_error (moo, MOO_SYNERR_RPAREN, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
GET_TOKEN (moo);
}
/* variable declaration */
do
{
if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT)
{
var_info_t var;
#if 0
if (dcl_type == VAR_INSTANCE && (moo->c->cls.flags & CLASS_INDEXED) && (moo->c->cls.indexed_type != MOO_OBJ_TYPE_OOP))
{
set_syntax_error (moo, MOO_SYNERR_VARNAMEDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
if (find_class_level_variable(moo, MOO_NULL, TOKEN_NAME(moo), &var) >= 0 ||
moo_lookupdic (moo, (moo_oop_dic_t)moo->sysdic, TOKEN_NAME(moo)) || /* conflicts with a top global name */
moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.ns_oop, TOKEN_NAME(moo))) /* conflicts with a global name in the class'es name space */
{
set_syntax_error (moo, MOO_SYNERR_VARNAMEDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
if (add_class_level_variable(moo, dcl_type, TOKEN_NAME(moo)) <= -1) return -1;
#endif
GET_TOKEN (moo);
if (TOKEN_TYPE(moo) == MOO_IOTOK_ASSIGN)
{
moo_oop_t lit;
GET_TOKEN (moo); /* skip := and go on the the value token */
/* [NOTE] default value assignment. only a literal is allowed
* the initial values for instance variables and
* class instance variables are set to read-only.
* this is likely to change if the actual initial
* value assignment upon instantiation employes
* deep-copying in moo_instantiate() and in the compiler. */
lit = token_to_literal (moo, 1);
if (!lit) return -1;
/* TODO: store the constannt value... */
GET_TOKEN (moo);
}
else
{
set_syntax_error (moo, MOO_SYNERR_ASSIGN, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
}
else if (TOKEN_TYPE(moo) == MOO_IOTOK_COMMA || TOKEN_TYPE(moo) == MOO_IOTOK_EOF || TOKEN_TYPE(moo) == MOO_IOTOK_PERIOD)
{
/* no variable name is present */
set_syntax_error (moo, MOO_SYNERR_VARNAMEDUPL, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
else
{
break;
}
if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT)
{
set_syntax_error (moo, MOO_SYNERR_COMMA, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
else if (TOKEN_TYPE(moo) != MOO_IOTOK_COMMA) break; /* hopefully . */
GET_TOKEN (moo);
}
while (1);
if (TOKEN_TYPE(moo) != MOO_IOTOK_PERIOD)
{
set_syntax_error (moo, MOO_SYNERR_PERIOD, TOKEN_LOC(moo), TOKEN_NAME(moo));
return -1;
}
GET_TOKEN (moo);
return 0;
}
static int compile_unary_method_name (moo_t* moo)
{
@ -3951,144 +3834,8 @@ static int compile_method_pragma (moo_t* moo)
return 0;
}
static int find_dotted_ident (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, var_info_t* var)
static int validate_class_level_variable (moo_t* moo, var_info_t* var, const moo_oocs_t* name, const moo_ioloc_t* name_loc)
{
/* if a name is dotted,
*
* self.XXX - instance variable
* A.B.C - namespace or pool dictionary related reference.
* self.B.C - B.C under the current class where B is not an instance variable
*/
moo_oocs_t last;
moo_oop_nsdic_t top_dic, ns_oop;
moo_oop_association_t ass;
const moo_ooch_t* dot;
moo_oocs_t xname;
moo_ioloc_t xname_loc;
top_dic = MOO_NULL;
xname = *name;
xname_loc = *name_loc;
dot = moo_findoochar (name->ptr, name->len, '.');
MOO_ASSERT (moo, dot != MOO_NULL);
if (dot - (const moo_ooch_t*)name->ptr == 4 &&
moo_equaloochars(name->ptr, vocas[VOCA_SELF].str, 4))
{
/* special case. the dotted name begins with self.
* the special prefix 'self' is used to refer to the data
* contained in a class or in its instance. */
dot = moo_findoochar (dot + 1, name->len - 5, '.');
if (!dot)
{
/* the dotted name is composed of 2 segments only */
last.ptr = name->ptr + 5;
last.len = name->len - 5;
if (is_reserved_word(&last))
{
/* self. is followed by a reserved word.
* a proper variable name is expected. */
set_syntax_error (moo, MOO_SYNERR_VARNAME, name_loc, name);
return -1;
}
if (moo->c->cls.self_oop)
{
/* it's probably called from a method or
* a nested pooldic definition inside a class */
if (find_class_level_variable(moo, moo->c->cls.self_oop, &last, var) >= 0)
{
/* indicate that it's not a global variable */
return 1;
}
goto self_not_class_level;
}
else
{
goto self_inacc;
}
}
else
{
if (moo->c->cls.self_oop)
{
self_not_class_level:
top_dic = moo->c->cls.ns_oop;
if ((moo_oop_t)top_dic == moo->_nil) top_dic = MOO_NULL;
xname.ptr += 5;
xname.len -= 5;
xname_loc.colm += 5;
}
else
{
self_inacc:
top_dic = moo->c->cls.self_oop->nsdic;
if ((moo_oop_t)top_dic == moo->_nil) top_dic = MOO_NULL;
xname.ptr += 5;
xname.len -= 5;
xname_loc.colm += 5;
#if 0
/* called without a class defined. possibly the following cases:
* used as a value for a pooldic item
* used as an initial value for a class-level variables */
set_syntax_error (moo, MOO_SYNERR_SELFINACC, name_loc, name);
return -1;
#endif
}
}
}
/*if (preprocess_dotted_name (moo, PDN_DONT_ADD_NS | PDN_ACCEPT_POOLDIC_AS_NS, top_dic, name, name_loc, &last, &ns_oop) <= -1) return -1;*/
if (preprocess_dotted_name (moo, PDN_DONT_ADD_NS | PDN_ACCEPT_POOLDIC_AS_NS, top_dic, &xname, &xname_loc, &last, &ns_oop) <= -1) return -1;
ass = moo_lookupdic (moo, (moo_oop_dic_t)ns_oop, &last);
if (!ass)
{
/* undeclared identifier */
set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
var->type = VAR_GLOBAL;
var->gbl = ass;
return 0;
}
static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, int name_dotted, var_info_t* var)
{
moo_oow_t index;
MOO_MEMSET (var, 0, MOO_SIZEOF(*var));
if (name_dotted)
{
int n;
if ((n = find_dotted_ident (moo, name, name_loc, var)) <= -1) return -1;
if (n >= 1) goto class_level_variable; /* prefixed with self. */
return 0;
}
if (!moo->c->cls.self_oop)
{
/* it's called before a class is made available. commonly, outside a class.
* no need to check class level variables and temporary variables */
goto lookup_in_dics;
}
if (moo->c->mth.active && find_temporary_variable (moo, name, &index) >= 0)
{
var->type = (index < moo->c->mth.tmpr_nargs)? VAR_ARGUMENT: VAR_TEMPORARY;
var->pos = index;
}
else
{
if (find_class_level_variable(moo, moo->c->cls.self_oop, name, var) >= 0)
{
class_level_variable:
switch (var->type)
{
case VAR_INSTANCE:
@ -4131,14 +3878,216 @@ static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_iolo
moo_seterrnum (moo, MOO_EINTERN);
return -1;
}
return 0;
}
static moo_oow_t is_dotted_ident_prefixed (const moo_oocs_t* name, int voca_id)
{
if (name->len > vocas[voca_id].len &&
moo_equaloochars(name->ptr, vocas[voca_id].str, vocas[voca_id].len) &&
name->ptr[vocas[voca_id].len] == '.') return vocas[voca_id].len;
return 0;
}
static MOO_INLINE int find_dotted_ident (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, var_info_t* var)
{
/* if a name is dotted,
*
* self.XXX - instance variable
* A.B.C - namespace or pool dictionary related reference.
* self.B.C - B.C under the current class where B is not an instance variable
*/
moo_oocs_t last;
moo_oop_nsdic_t top_dic, ns_oop;
moo_oop_association_t ass;
moo_oow_t pxlen;
moo_oocs_t xname;
moo_ioloc_t xname_loc;
top_dic = MOO_NULL;
xname = *name;
xname_loc = *name_loc;
if ((pxlen = is_dotted_ident_prefixed (name, VOCA_SELF)) > 0)
{
/* the first word in the dotted notation is self */
if (!moo_findoochar (name->ptr + pxlen + 1, name->len - pxlen - 1, '.'))
{
/* the dotted name is composed of 2 segments only */
last.ptr = name->ptr + pxlen + 1;
last.len = name->len - pxlen - 1;
if (is_reserved_word(&last))
{
/* self. is followed by a reserved word.
* a proper variable name is expected. */
set_syntax_error (moo, MOO_SYNERR_VARNAME, name_loc, name);
return -1;
}
if (moo->c->cls.super_oop)
{
/* called inside a class definition */
/* [NOTE]
* cls.ns_oop is set when the class name is enountered.
* cls.super_oop is set when the parent class name is enountered.
* cls.super_oop may still be MOO_NULL even if cls.ns_oop is not.
* on the other hand, cls.ns_oop is not MOO_NULL as long as
* cls.super_oop is not MOO_NULL.
*/
MOO_ASSERT (moo, moo->c->cls.ns_oop != MOO_NULL);
MOO_ASSERT (moo, moo->c->pooldic.ns_oop == MOO_NULL);
/* moo->c->cls.self_oop may still be MOO_NULL if the class has not been instantiated */
if (find_class_level_variable(moo, moo->c->cls.self_oop, &last, var) >= 0)
{
/* if the current class has not been instantiated,
* no validation nor adjustment of the var->pos field is performed */
if (moo->c->cls.self_oop && validate_class_level_variable (moo, var, name, name_loc) <= -1) return -1;
return 0;
}
}
else if (moo->c->pooldic.ns_oop)
{
moo_oop_t v;
/* called inside a pooldic definition */
MOO_ASSERT (moo, moo->c->cls.ns_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->cls.super_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->cls.self_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->pooldic.pd_oop == MOO_NULL);
v = find_element_in_compiling_pooldic (moo, &last);
if (!v)
{
set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
var->type = VAR_LITERAL;
var->u.lit = v; /* TODO: change this */
return 0;
}
}
if (!moo->c->cls.self_oop)
{
/* self is not usable when it's not compiling in a class.
* a pooldic definition cannot contain subdictionaries.
* the pooldic is a terminal point and the items inside
* are final nodes. if self is followed by more than 1
* subsegments, it's */
set_syntax_error (moo, MOO_SYNERR_VARINACC, name_loc, name);
return -1;
}
/* namespace that the current class starts */
top_dic = moo->c->cls.self_oop->nsdic;
pxlen++; /* include . into the length */
}
else if ((pxlen = is_dotted_ident_prefixed (name, VOCA_SELFNS)) > 0)
{
/* the first segment is selfns which indicates a namespace that
* the current class belongs to */
if (moo->c->cls.ns_oop)
{
/* compiling in a class definition */
top_dic = moo->c->cls.ns_oop;
}
else
{
/* compiling in a pooldic definition */
MOO_ASSERT (moo, moo->c->pooldic.ns_oop != MOO_NULL);
top_dic = moo->c->pooldic.ns_oop;
}
pxlen++; /* include . into the length */
}
if ((moo_oop_t)top_dic == moo->_nil) top_dic = MOO_NULL;
xname.ptr += pxlen;
xname.len -= pxlen;
xname_loc.colm += pxlen;
/*if (preprocess_dotted_name (moo, PDN_DONT_ADD_NS | PDN_ACCEPT_POOLDIC_AS_NS, top_dic, name, name_loc, &last, &ns_oop) <= -1) return -1;*/
if (preprocess_dotted_name (moo, PDN_DONT_ADD_NS | PDN_ACCEPT_POOLDIC_AS_NS, top_dic, &xname, &xname_loc, &last, &ns_oop) <= -1) return -1;
ass = moo_lookupdic (moo, (moo_oop_dic_t)ns_oop, &last);
if (!ass)
{
/* undeclared identifier */
set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
var->type = VAR_GLOBAL;
var->u.gbl = ass;
return 0;
}
static MOO_INLINE int find_undotted_ident (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, var_info_t* var)
{
moo_oow_t index;
moo_oop_association_t ass;
lookup_in_dics:
/* find an undotted identifier in dictionaries */
if (moo->c->cls.self_oop)
{
/* the current class being compiled has been instantiated.
* look up in the temporary variable list if compiling in a method */
if (moo->c->mth.active && find_temporary_variable (moo, name, &index) >= 0)
{
var->type = (index < moo->c->mth.tmpr_nargs)? VAR_ARGUMENT: VAR_TEMPORARY;
var->pos = index;
return 0;
}
}
if (moo->c->cls.super_oop)
{
/* called inside a class definition */
/* read a comment in find_dotted_ident() for the reason behind
* the if condition above. */
MOO_ASSERT (moo, moo->c->cls.ns_oop != MOO_NULL);
MOO_ASSERT (moo, moo->c->pooldic.ns_oop == MOO_NULL);
if (find_class_level_variable(moo, moo->c->cls.self_oop, name, var) >= 0)
{
/* if the current class being compiled has not been instantiated,
* no validation nor adjustment of the var->pos field is performed */
return moo->c->cls.self_oop? validate_class_level_variable (moo, var, name, name_loc): 0;
}
}
else if (moo->c->pooldic.ns_oop)
{
moo_oop_t v;
/* called inside a pooldic definition */
MOO_ASSERT (moo, moo->c->cls.ns_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->cls.super_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->cls.self_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->pooldic.pd_oop == MOO_NULL);
v = find_element_in_compiling_pooldic (moo, name);
if (!v)
{
set_syntax_error (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
var->type = VAR_LITERAL;
var->u.lit = v; /* TODO: change this */
return 0;
}
/* find an undotted identifier in dictionaries */
if (moo->c->cls.ns_oop)
{
ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.ns_oop, name); /* in the current name space */
@ -4180,10 +4129,22 @@ static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_iolo
}
var->type = VAR_GLOBAL;
var->gbl = ass;
}
var->u.gbl = ass;
return 0;
}
static int get_variable_info (moo_t* moo, const moo_oocs_t* name, const moo_ioloc_t* name_loc, int name_dotted, var_info_t* var)
{
int x;
MOO_MEMSET (var, 0, MOO_SIZEOF(*var));
x = name_dotted? find_dotted_ident (moo, name, name_loc, var): find_undotted_ident (moo, name, name_loc, var);
if (x <= -1) return -1;
/* final validation on the range of pos field. just check regardless of var->type.
* i assume the functions above don't taint the var-type field when it's meaningless. */
if (var->pos > MAX_CODE_INDEX)
{
/* the assignee is not usable because its index is too large
@ -4710,6 +4671,7 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
{
/* the caller has read the identifier and the next word */
handle_ident:
MOO_ASSERT (moo, moo->c->cls.super_oop != MOO_NULL && moo->c->cls.self_oop != MOO_NULL);
if (get_variable_info(moo, ident, ident_loc, ident_dotted, &var) <= -1) return -1;
switch (var.type)
@ -4761,7 +4723,7 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
* the code compiled before the deletion will still access
* the deleted association
*/
if (add_literal(moo, (moo_oop_t)var.gbl, &index) <= -1 ||
if (add_literal(moo, (moo_oop_t)var.u.gbl, &index) <= -1 ||
emit_single_param_instruction(moo, BCODE_PUSH_OBJECT_0, index) <= -1) return -1;
break;
@ -4840,6 +4802,11 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
GET_TOKEN (moo);
break;
case MOO_IOTOK_SELFNS:
if (emit_byte_instruction(moo, BCODE_PUSH_RECEIVER_NS) <= -1) return -1;
GET_TOKEN (moo);
break;
case MOO_IOTOK_CHARLIT:
MOO_ASSERT (moo, TOKEN_NAME_LEN(moo) == 1);
if (emit_push_character_literal(moo, TOKEN_NAME_PTR(moo)[0]) <= -1) return -1;
@ -5725,6 +5692,7 @@ static int compile_method_expression (moo_t* moo, int pop)
* assignee to update the actual pointer after the recursive
* compile_method_expression() call */
assignee.ptr = &moo->c->mth.assignees.ptr[assignee_offset];
MOO_ASSERT (moo, moo->c->cls.super_oop != MOO_NULL && moo->c->cls.self_oop != MOO_NULL);
if (get_variable_info(moo, &assignee, &assignee_loc, assignee_dotted, &var) <= -1) goto oops;
switch (var.type)
@ -5771,7 +5739,7 @@ static int compile_method_expression (moo_t* moo, int pop)
break;
case VAR_GLOBAL:
if (add_literal(moo, (moo_oop_t)var.gbl, &index) <= -1 ||
if (add_literal(moo, (moo_oop_t)var.u.gbl, &index) <= -1 ||
emit_single_param_instruction(moo, (pop? BCODE_POP_INTO_OBJECT_0: BCODE_STORE_INTO_OBJECT_0), index) <= -1) return -1;
ret = pop;
break;
@ -6051,6 +6019,10 @@ static int add_compiled_method (moo_t* moo)
preamble_code = MOO_METHOD_PREAMBLE_RETURN_PROCESS;
break;
case BCODE_PUSH_RECEIVER_NS:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS;
break;
case BCODE_PUSH_NIL:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_NIL;
break;
@ -6548,8 +6520,8 @@ static int make_default_initial_values (moo_t* moo, var_type_t var_type)
for (i = 0; i < moo->c->cls.var[var_type].initv_count; i++)
{
if (moo->c->cls.var[var_type].initv[i])
((moo_oop_oop_t)tmp)->slot[j] = moo->c->cls.var[var_type].initv[i];
if (moo->c->cls.var[var_type].initv[i].v)
((moo_oop_oop_t)tmp)->slot[j] = moo->c->cls.var[var_type].initv[i].v;
j++;
}
@ -6698,8 +6670,7 @@ static int make_defined_class (moo_t* moo)
MOO_ASSERT (moo, MOO_CLASS_NAMED_INSTVARS + j + initv_count <= MOO_OBJ_GET_SIZE(moo->c->cls.self_oop));
for (i = 0; i < initv_count; i++)
{
/* ((moo_oop_oop_t)moo->c->cls.self_oop)->slot[MOO_CLASS_NAMED_INSTVARS + j] = moo->c->cls.var[VAR_CLASS].initv[i]; */
moo->c->cls.self_oop->slot[j] = moo->c->cls.var[VAR_CLASS].initv[i];
moo->c->cls.self_oop->slot[j] = moo->c->cls.var[VAR_CLASS].initv[i].v;
j++;
}
}
@ -6929,6 +6900,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
else
{
int super_is_nil = 0;
int superfqn_is_dotted;
MOO_INFO2 (moo, "Defining a class %.*js\n", moo->c->cls.fqn.len, moo->c->cls.fqn.ptr);
@ -6959,17 +6931,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
if (set_superclass_fqn(moo, TOKEN_NAME(moo)) <= -1) return -1;
moo->c->cls.superfqn_loc = moo->c->tok.loc;
if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
{
if (preprocess_dotted_name(moo, PDN_DONT_ADD_NS, MOO_NULL, &moo->c->cls.superfqn, &moo->c->cls.superfqn_loc, &moo->c->cls.supername, &moo->c->cls.superns_oop) <= -1) return -1;
}
else
{
/* if no fully qualified name is specified for the super class name,
* the name is searched in the name space that the class being defined
* belongs to first and in the 'moo->sysdic'. */
moo->c->cls.superns_oop = moo->c->cls.ns_oop;
}
superfqn_is_dotted = (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED);
GET_TOKEN (moo);
if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN)
@ -6980,7 +6942,6 @@ static int __compile_class_definition (moo_t* moo, int extend)
GET_TOKEN (moo);
/*ass = moo_lookupsysdic(moo, &moo->c->cls.name);*/
ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.ns_oop, &moo->c->cls.name);
if (ass)
{
@ -7009,19 +6970,21 @@ static int __compile_class_definition (moo_t* moo, int extend)
}
else
{
ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.superns_oop, &moo->c->cls.supername);
if (!ass && moo->c->cls.superns_oop != moo->sysdic)
ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->sysdic, &moo->c->cls.supername);
if (ass &&
MOO_CLASSOF(moo, ass->value) == moo->_class &&
MOO_OBJ_GET_FLAGS_KERNEL(ass->value) != 1)
var_info_t var;
if (get_variable_info (moo, &moo->c->cls.superfqn, &moo->c->cls.superfqn_loc, superfqn_is_dotted, &var) <= -1) return -1;
if (var.type != VAR_GLOBAL) goto unknown_superclass;
if (MOO_CLASSOF(moo, var.u.gbl->value) == moo->_class && MOO_OBJ_GET_FLAGS_KERNEL(var.u.gbl->value) != 1)
{
/* the value found must be a class and it must not be
* an incomplete internal class object.
* 0(non-kernel object)
* 1(incomplete kernel object),
* 2(complete kernel object) */
moo->c->cls.super_oop = ass->value;
moo->c->cls.super_oop = var.u.gbl->value;
/* the superclass became known. */
if (((moo_oop_class_t)moo->c->cls.super_oop)->trsize != moo->_nil &&
@ -7042,6 +7005,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
}
else
{
unknown_superclass:
/* there is no object with such a name. or,
* the object found with the name is not a class object. or,
* the class object found is a internally defined kernel
@ -7204,12 +7168,6 @@ static int __compile_class_definition (moo_t* moo, int extend)
GET_TOKEN (moo);
if (compile_class_level_imports(moo) <= -1) return -1;
}
else if (is_token_word(moo, VOCA_CONST) || is_token_word(moo, VOCA_CONSTANT))
{
/* constant declaration */
GET_TOKEN (moo);
if (compile_class_level_constants(moo) <= -1) return -1;
}
else break;
}
while (1);
@ -7247,12 +7205,6 @@ static int __compile_class_definition (moo_t* moo, int extend)
GET_TOKEN (moo);
if (compile_method_definition(moo) <= -1) return -1;
}
else if (is_token_word(moo, VOCA_CONST) || is_token_word(moo, VOCA_CONSTANT))
{
/* constant declaration */
GET_TOKEN (moo);
if (compile_class_level_constants(moo) <= -1) return -1;
}
else break;
}
while (1);
@ -7385,14 +7337,22 @@ static moo_oop_t token_to_literal (moo_t* moo, int rdonly)
{
var_info_t var;
if (get_variable_info (moo, TOKEN_NAME(moo), TOKEN_LOC(moo), TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED, &var) <= -1) return MOO_NULL;
if (var.type != VAR_GLOBAL)
if (var.type == VAR_GLOBAL)
{
return var.u.gbl->value;
}
else if (var.type == VAR_LITERAL)
{
return var.u.lit;
}
else
{
set_syntax_error (moo, MOO_SYNERR_VARINACC, TOKEN_LOC(moo), TOKEN_NAME(moo));
return MOO_NULL;
}
/* [NOTE] i don't mark RDONLY on a value resolved via an identifier */
return var.gbl->value;
}
case MOO_IOTOK_BABRACK: /* #[ - byte array literal parenthesis */
@ -7425,6 +7385,26 @@ static moo_oop_t token_to_literal (moo_t* moo, int rdonly)
}
}
static moo_oop_t find_element_in_compiling_pooldic (moo_t* moo, const moo_oocs_t* name)
{
moo_oow_t i;
moo_oop_char_t s;
for (i = moo->c->pooldic.start; i < moo->c->pooldic.end; i += 2)
{
s = (moo_oop_char_t)moo->c->arlit.ptr[i];
MOO_ASSERT (moo, MOO_CLASSOF(moo,s) == moo->_symbol);
if (MOO_OBJ_GET_SIZE(s) == name->len &&
moo_equaloochars (name->ptr, MOO_OBJ_GET_CHAR_SLOT(s), name->len))
{
return moo->c->arlit.ptr[i + 1];
}
}
moo_seterrnum (moo, MOO_ENOENT);
return MOO_NULL;
}
static int __compile_pooldic_definition (moo_t* moo, moo_pooldic_t* pd)
{
moo_oop_t lit;
@ -7441,14 +7421,9 @@ static int __compile_pooldic_definition (moo_t* moo, moo_pooldic_t* pd)
goto oops;
}
if (moo->c->cls.self_oop && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED)
{
/* nested pooldic definition in a class definition */
set_syntax_error (moo, MOO_SYNERR_IDENT, TOKEN_LOC(moo), TOKEN_NAME(moo)); /* TODO: change error code - plain ident or undotted ident */
goto oops;
}
/* TODO: if defined in a class, it also should be imported automatically to the containing class
* or import K.X */
MOO_ASSERT (moo, moo->c->cls.ns_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->cls.super_oop == MOO_NULL);
MOO_ASSERT (moo, moo->c->cls.self_oop == MOO_NULL);
if (set_pooldic_fqn(moo, pd, TOKEN_NAME(moo)) <= -1) goto oops;
pd->fqn_loc = moo->c->tok.loc;
@ -7480,6 +7455,8 @@ static int __compile_pooldic_definition (moo_t* moo, moo_pooldic_t* pd)
GET_TOKEN (moo);
pd->start = moo->c->arlit.count;
pd->end = moo->c->arlit.count;
while (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT)
{
lit = moo_makesymbol (moo, TOKEN_NAME_PTR(moo), TOKEN_NAME_LEN(moo));
@ -7504,6 +7481,8 @@ static int __compile_pooldic_definition (moo_t* moo, moo_pooldic_t* pd)
/* for this definition, #pooldic MyPoolDic { a := 10. b := 20 },
* arlit_buffer contains (#a 10 #b 20) when the 'while' loop is over. */
if (add_to_array_literal_buffer(moo, lit) <= -1) goto oops;
pd->end = moo->c->arlit.count;
GET_TOKEN (moo);
/*if (TOKEN_TYPE(moo) == MOO_IOTOK_RBRACE) goto done;
@ -7648,8 +7627,8 @@ static void gc_compiler (moo_t* moo)
{
for (j = 0; j < moo->c->cls.var[i].initv_count; j++)
{
register moo_oop_t x = moo->c->cls.var[i].initv[j];
if (x) moo->c->cls.var[i].initv[j] = moo_moveoop (moo, x);
register moo_oop_t x = moo->c->cls.var[i].initv[j].v;
if (x) moo->c->cls.var[i].initv[j].v = moo_moveoop (moo, x);
}
}

View File

@ -463,6 +463,10 @@ int moo_decode (moo_t* moo, moo_oop_method_t mth, const moo_oocs_t* classfqn)
LOG_INST_0 (moo, "push_process");
break;
case BCODE_PUSH_RECEIVER_NS:
LOG_INST_0 (moo, "push_receiver_ns");
break;
case BCODE_PUSH_NEGONE:
LOG_INST_0 (moo, "push_negone");
break;
@ -479,6 +483,7 @@ int moo_decode (moo_t* moo, moo_oop_method_t mth, const moo_oocs_t* classfqn)
LOG_INST_0 (moo, "push_two");
break;
case BCODE_PUSH_INTLIT:
FETCH_PARAM_CODE_TO (moo, b1);
LOG_INST_1 (moo, "push_intlit %zu", b1);

View File

@ -3944,6 +3944,18 @@ static int start_method (moo_t* moo, moo_oop_method_t method, moo_oow_t nargs)
MOO_STACK_SETTOP (moo, (moo_oop_t)moo->processor->active);
break;
case MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS:
{
moo_oop_t c;
LOG_INST_0 (moo, "preamble_return_receiver_ns");
MOO_STACK_POPS (moo, nargs); /* pop arguments only*/
c = MOO_STACK_GETTOP (moo); /* get receiver */
c = (moo_oop_t)MOO_CLASSOF(moo, c);
if (c == (moo_oop_t)moo->_class) c = MOO_STACK_GETTOP (moo);
MOO_STACK_SETTOP (moo, (moo_oop_t)((moo_oop_class_t)c)->nsup);
break;
}
case MOO_METHOD_PREAMBLE_RETURN_NIL:
LOG_INST_0 (moo, "preamble_return_nil");
MOO_STACK_POPS (moo, nargs);
@ -5030,6 +5042,16 @@ int moo_execute (moo_t* moo)
MOO_STACK_PUSH (moo, (moo_oop_t)moo->processor->active);
break;
case BCODE_PUSH_RECEIVER_NS:
{
register moo_oop_t c;
LOG_INST_0 (moo, "push_receiver_ns");
c = (moo_oop_t)MOO_CLASSOF(moo, moo->active_context->origin->receiver_or_source);
if (c == (moo_oop_t)moo->_class) c = moo->active_context->origin->receiver_or_source;
MOO_STACK_PUSH (moo, (moo_oop_t)((moo_oop_class_t)c)->nsup);
break;
}
case BCODE_PUSH_NEGONE:
LOG_INST_0 (moo, "push_negone");
MOO_STACK_PUSH (moo, MOO_SMOOI_TO_OOP(-1));

View File

@ -320,6 +320,7 @@ struct moo_iotok_t
MOO_IOTOK_NUMLIT,
MOO_IOTOK_RADNUMLIT,
MOO_IOTOK_ERRLIT, /* error(NN) */
MOO_IOTOK_ERROR, /* error */
MOO_IOTOK_NIL,
MOO_IOTOK_SELF,
@ -328,6 +329,18 @@ struct moo_iotok_t
MOO_IOTOK_FALSE,
MOO_IOTOK_THIS_CONTEXT,
MOO_IOTOK_THIS_PROCESS,
MOO_IOTOK_SELFNS,
MOO_IOTOK_IF,
MOO_IOTOK_ELSE,
MOO_IOTOK_ELSIF,
MOO_IOTOK_WHILE,
MOO_IOTOK_UNTIL,
MOO_IOTOK_DO,
MOO_IOTOK_BREAK,
MOO_IOTOK_CONTINUE,
MOO_IOTOK_IDENT,
MOO_IOTOK_IDENT_DOTTED,
MOO_IOTOK_BINSEL,
@ -348,17 +361,7 @@ struct moo_iotok_t
MOO_IOTOK_DICBRACE, /* :{ - dictionary expression */
MOO_IOTOK_PERIOD,
MOO_IOTOK_COMMA,
MOO_IOTOK_SEMICOLON,
MOO_IOTOK_IF,
MOO_IOTOK_ELSE,
MOO_IOTOK_ELSIF,
MOO_IOTOK_WHILE,
MOO_IOTOK_UNTIL,
MOO_IOTOK_DO,
MOO_IOTOK_BREAK,
MOO_IOTOK_CONTINUE
MOO_IOTOK_SEMICOLON
} type;
moo_oocs_t name;
@ -425,6 +428,9 @@ struct moo_pooldic_t
moo_oop_dic_t pd_oop;
moo_oop_nsdic_t ns_oop;
moo_oow_t start;
moo_oow_t end;
};
typedef struct moo_oopbuf_t moo_oopbuf_t;
@ -443,6 +449,13 @@ struct moo_oobbuf_t
moo_oow_t capa;
};
typedef struct moo_initv_t moo_initv_t;
struct moo_initv_t
{
moo_oop_t v;
int flags;
};
struct moo_compiler_t
{
/* input handler */
@ -490,9 +503,6 @@ struct moo_compiler_t
moo_oop_class_t self_oop;
moo_oop_t super_oop; /* this may be nil. so the type is moo_oop_t */
#if 0
moo_oop_dic_t pooldic_oop; /* used when compiling a pooldic definition */
#endif
moo_oop_nsdic_t ns_oop;
moo_oocs_t fqn;
moo_oocs_t name;
@ -508,10 +518,11 @@ struct moo_compiler_t
moo_oocs_t modname; /* module name after 'from' */
moo_oow_t modname_capa;
/* instance variable, class variable, class instance variable
/* instance variable, class variable, class instance variable, constant
* var[0] - named instance variables
* var[1] - class instance variables
* var[2] - class variables */
* var[2] - class variables
*/
struct
{
moo_oocs_t str; /* long string containing all variables declared delimited by a space */
@ -520,7 +531,7 @@ struct moo_compiler_t
moo_oow_t count; /* the number of variables declared in this class only */
moo_oow_t total_count; /* the number of variables declared in this class and superclasses */
moo_oop_t* initv;
moo_initv_t* initv;
moo_oow_t initv_capa;
/* initv_count holds the index to the last variable with a
* default initial value defined in this class only plus one.
@ -545,7 +556,6 @@ struct moo_compiler_t
moo_oop_dic_t* oops;
moo_oow_t oops_capa;
} pooldic_imp;
} cls;
/* pooldic declaration */
@ -611,27 +621,6 @@ struct moo_compiler_t
moo_oow_t code_capa;
} mth;
};
/*
typedef struct moo_bchbuf_t moo_bchbuf_t;
struct moo_bchbuf_t
{
moo_bch_t buf[128];
moo_bch_t* ptr;
moo_oow_t capa;
};
typedef struct moo_oochbuf_t moo_oochbuf_t;
struct moo_oochbuf_t
{
moo_ooch_t buf[128];
moo_ooch_t* ptr;
moo_oow_t capa;
};
*/
#endif
#if defined(MOO_USE_METHOD_TRAILER)
@ -891,13 +880,14 @@ enum moo_bcode_t
BCODE_PUSH_FALSE = 0x84, /* 132 */
BCODE_PUSH_CONTEXT = 0x85, /* 133 */
BCODE_PUSH_PROCESS = 0x86, /* 134 */
BCODE_PUSH_NEGONE = 0x87, /* 135 */
BCODE_PUSH_RECEIVER_NS = 0x87, /* 135 */
BCODE_POP_INTO_INSTVAR_X = 0x88, /* 136 ## */
BCODE_PUSH_ZERO = 0x89, /* 137 */
BCODE_PUSH_ONE = 0x8A, /* 138 */
BCODE_PUSH_TWO = 0x8B, /* 139 */
BCODE_PUSH_NEGONE = 0x89, /* 137 */
BCODE_PUSH_ZERO = 0x8A, /* 138 */
BCODE_PUSH_ONE = 0x8B, /* 139 */
BCODE_PUSH_TWO = 0x8C, /* 140 */
BCODE_PUSH_INSTVAR_X = 0x90, /* 144 ## */
BCODE_PUSH_TEMPVAR_X = 0x98, /* 152 ## */

View File

@ -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 18
#define MOO_CLASS_NAMED_INSTVARS 17
typedef struct moo_class_t moo_class_t;
typedef struct moo_class_t* moo_oop_class_t;
@ -537,8 +537,6 @@ struct moo_class_t
moo_oop_nsdic_t nsup; /* pointer to the upper namespace */
moo_oop_nsdic_t nsdic; /* dictionary used for namespacing - may be nil when there are no subitems underneath */
moo_oop_dic_t cdic; /* constant dictionary */
moo_oop_t trsize; /* trailer size for new instances */
/* [0] - initial values for instance variables of new instances
@ -619,7 +617,7 @@ struct moo_method_t
*
* The code can be one of the following values:
* 0 - no special action
* 1 - return self
* 1 - return self (receiver)
* 2 - return thisContext (not used)
* 3 - return thisProcess
* 4 - return nil
@ -627,11 +625,12 @@ struct moo_method_t
* 6 - return false
* 7 - return index.
* 8 - return -index.
* 9 - return instvar[index]
* 10 - do primitive[index]
* 11 - do named primitive[index]
* 12 - exception handler
* 13 - ensure block
* 9 - return selfns
* 10 - return instvar[index]
* 11 - do primitive[index]
* 12 - do named primitive[index]
* 13 - exception handler
* 14 - ensure block
*/
/* [NOTE] changing preamble code bit structure requires changes to CompiledMethod>>preambleCode */
@ -645,17 +644,17 @@ struct moo_method_t
#define MOO_METHOD_PREAMBLE_RETURN_RECEIVER 1
#define MOO_METHOD_PREAMBLE_RETURN_CONTEXT 2
#define MOO_METHOD_PREAMBLE_RETURN_PROCESS 3
#define MOO_METHOD_PREAMBLE_RETURN_NIL 4
#define MOO_METHOD_PREAMBLE_RETURN_TRUE 5
#define MOO_METHOD_PREAMBLE_RETURN_FALSE 6
#define MOO_METHOD_PREAMBLE_RETURN_INDEX 7
#define MOO_METHOD_PREAMBLE_RETURN_NEGINDEX 8
#define MOO_METHOD_PREAMBLE_RETURN_INSTVAR 9
#define MOO_METHOD_PREAMBLE_PRIMITIVE 10
#define MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE 11 /* index is an index to the symbol table */
#define MOO_METHOD_PREAMBLE_EXCEPTION 12 /* NOTE changing this requires changes in Except.st */
#define MOO_METHOD_PREAMBLE_ENSURE 13 /* NOTE changing this requires changes in Except.st */
#define MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS 4
#define MOO_METHOD_PREAMBLE_RETURN_NIL 5
#define MOO_METHOD_PREAMBLE_RETURN_TRUE 6
#define MOO_METHOD_PREAMBLE_RETURN_FALSE 7
#define MOO_METHOD_PREAMBLE_RETURN_INDEX 8
#define MOO_METHOD_PREAMBLE_RETURN_NEGINDEX 9
#define MOO_METHOD_PREAMBLE_RETURN_INSTVAR 10
#define MOO_METHOD_PREAMBLE_PRIMITIVE 11
#define MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE 12 /* index is an index to the symbol table */
#define MOO_METHOD_PREAMBLE_EXCEPTION 13 /* NOTE changing this requires changes in Except.st */
#define MOO_METHOD_PREAMBLE_ENSURE 14 /* NOTE changing this requires changes in Except.st */
/* the index is an 16-bit unsigned integer. */
#define MOO_METHOD_PREAMBLE_INDEX_MIN 0x0000