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 spec, selfspec, superclass, subclasses, name, modname.
var instvars, classinstvars, classvars, pooldics. var instvars, classinstvars, classvars, pooldics.
var instmthdic, classmthdic, nsup, nsdic, cdic. var instmthdic, classmthdic, nsup, nsdic.
var trsize, initv, initv_ci. var trsize, initv, initv_ci.
method(#class) initialize { ^self } method(#class) initialize { ^self }

View File

@ -217,13 +217,13 @@ extend MethodContext
method isExceptionContext method isExceptionContext
{ {
## 12 - MOO_METHOD_PREAMBLE_EXCEPTION in VM. ## 12 - MOO_METHOD_PREAMBLE_EXCEPTION in VM.
^self.method preambleCode == 12. ^self.method preambleCode == 13.
} }
method isEnsureContext method isEnsureContext
{ {
## 13 - MOO_METHOD_PREAMBLE_ENSURE in VM. ## 13 - MOO_METHOD_PREAMBLE_ENSURE in VM.
^self.method preambleCode == 13 ^self.method preambleCode == 14
} }
method ensureBlock method ensureBlock
@ -236,7 +236,7 @@ extend MethodContext
* instance variables of the method context. As MethodContex has * instance variables of the method context. As MethodContex has
* 8 instance variables, the ensure block must be at the 9th position * 8 instance variables, the ensure block must be at the 9th position
* which translates to index 8 *) * 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_GLOBAL,
VAR_ARGUMENT, VAR_ARGUMENT,
VAR_TEMPORARY VAR_TEMPORARY,
VAR_LITERAL /* used when compiling pooldic elements only */
}; };
typedef enum var_type_t var_type_t; typedef enum var_type_t var_type_t;
@ -75,8 +77,12 @@ struct var_info_t
{ {
var_type_t type; var_type_t type;
moo_ooi_t pos; /* not used for VAR_GLOBAL */ 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_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; typedef struct var_info_t var_info_t;
@ -91,8 +97,6 @@ static struct voca_t
{ 5, { 'c','l','a','s','s' } }, { 5, { 'c','l','a','s','s' } },
{ 6, { '#','c','l','a','s','s' } }, { 6, { '#','c','l','a','s','s' } },
{ 10, { '#','c','l','a','s','s','i','n','s','t' } }, { 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' } }, { 8, { 'c','o','n','t','i','n','u','e' } },
{ 3, { 'd','c','l' } }, { 3, { 'd','c','l' } },
{ 2, { 'd','o' } }, { 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',':' } },
{ 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' } }, { 4, { 's','e','l','f' } },
{ 6, { 's','e','l','f','n','s' } },
{ 5, { 's','u','p','e','r' } }, { 5, { 's','u','p','e','r' } },
{ 11, { 't','h','i','s','C','o','n','t','e','x','t' } }, { 11, { 't','h','i','s','C','o','n','t','e','x','t' } },
{ 11, { 't','h','i','s','P','r','o','c','e','s','s' } }, { 11, { 't','h','i','s','P','r','o','c','e','s','s' } },
@ -151,8 +156,6 @@ enum voca_id_t
VOCA_CLASS, VOCA_CLASS,
VOCA_CLASS_S, VOCA_CLASS_S,
VOCA_CLASSINST_S, VOCA_CLASSINST_S,
VOCA_CONST,
VOCA_CONSTANT,
VOCA_CONTINUE, VOCA_CONTINUE,
VOCA_DCL, VOCA_DCL,
VOCA_DO, VOCA_DO,
@ -183,6 +186,7 @@ enum voca_id_t
VOCA_PRIMITIVE_COLON, VOCA_PRIMITIVE_COLON,
VOCA_PRIMITIVE_S, VOCA_PRIMITIVE_S,
VOCA_SELF, VOCA_SELF,
VOCA_SELFNS,
VOCA_SUPER, VOCA_SUPER,
VOCA_THIS_CONTEXT, VOCA_THIS_CONTEXT,
VOCA_THIS_PROCESS, 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 compile_method_expression (moo_t* moo, int pop);
static int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index); 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 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) 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_ERROR,
VOCA_THIS_CONTEXT, VOCA_THIS_CONTEXT,
VOCA_THIS_PROCESS, VOCA_THIS_PROCESS,
VOCA_SELFNS,
VOCA_IF, VOCA_IF,
VOCA_ELSE, VOCA_ELSE,
VOCA_ELSIF, 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); 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)) else if (is_token_word(moo, VOCA_IF))
{ {
SET_TOKEN_TYPE (moo, MOO_IOTOK_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 newcapa, oldcapa;
/*moo_oow_t i;*/ /*moo_oow_t i;*/
moo_oop_t* tmp; moo_initv_t* tmp;
oldcapa = moo->c->cls.var[var_type].initv_capa; oldcapa = moo->c->cls.var[var_type].initv_capa;
newcapa = MOO_ALIGN_POW2 ((var_index + 1), 32); 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; if (!tmp) return -1;
/*for (i = moo->c->cls.var[var_type].initv_capa; i < newcapa; i++) tmp[i] = MOO_NULL;*/ /*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; moo_oow_t i;
for (i = moo->c->cls.var[var_type].initv_count; i < var_index; 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_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; 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) if (find_word_in_string(&hs, name, &pos) >= 0)
{ {
super = self->superclass; 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. /* 'self' may be MOO_NULL if MOO_NULL has been given for it.
* the caller must take good care when interpreting the meaning of * 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; super = self->superclass;
MOO_ASSERT (moo, super == moo->c->cls.super_oop);
} }
else 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) if (find_word_in_string(&moo->c->cls.var[index].str, name, &pos) >= 0)
{ {
super = moo->c->cls.super_oop; super = moo->c->cls.super_oop;
var->cls = self; var->cls = MOO_NULL; /* the current class being compiled */
goto done; goto done;
} }
} }
@ -3276,11 +3292,11 @@ if super is variable-nonpointer, no instance variable is allowed.
GET_TOKEN (moo); 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 * the initial values for instance variables and
* class instance variables are set to read-only. * class instance variables are set to read-only.
* this is likely to change if the actual initial * I may change this if i get the actual initial
* value assignment upon instantiation employes * value assignment upon instantiation to employ
* deep-copying in moo_instantiate() and in the compiler. */ * deep-copying in moo_instantiate() and in the compiler. */
lit = token_to_literal (moo, dcl_type != VAR_CLASS); lit = token_to_literal (moo, dcl_type != VAR_CLASS);
if (!lit) return -1; if (!lit) return -1;
@ -3433,139 +3449,6 @@ static int compile_class_level_imports (moo_t* moo)
return 0; 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) static int compile_unary_method_name (moo_t* moo)
{ {
@ -3951,144 +3834,8 @@ static int compile_method_pragma (moo_t* moo)
return 0; 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) switch (var->type)
{ {
case VAR_INSTANCE: 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); moo_seterrnum (moo, MOO_EINTERN);
return -1; 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 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; moo_oop_association_t ass;
lookup_in_dics: if (moo->c->cls.self_oop)
/* find an undotted identifier in dictionaries */ {
/* 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) 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 */ 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->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) if (var->pos > MAX_CODE_INDEX)
{ {
/* the assignee is not usable because its index is too large /* 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 */ /* the caller has read the identifier and the next word */
handle_ident: 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; if (get_variable_info(moo, ident, ident_loc, ident_dotted, &var) <= -1) return -1;
switch (var.type) 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 code compiled before the deletion will still access
* the deleted association * 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; emit_single_param_instruction(moo, BCODE_PUSH_OBJECT_0, index) <= -1) return -1;
break; break;
@ -4840,6 +4802,11 @@ static int compile_expression_primary (moo_t* moo, const moo_oocs_t* ident, cons
GET_TOKEN (moo); GET_TOKEN (moo);
break; 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: case MOO_IOTOK_CHARLIT:
MOO_ASSERT (moo, TOKEN_NAME_LEN(moo) == 1); MOO_ASSERT (moo, TOKEN_NAME_LEN(moo) == 1);
if (emit_push_character_literal(moo, TOKEN_NAME_PTR(moo)[0]) <= -1) return -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 * assignee to update the actual pointer after the recursive
* compile_method_expression() call */ * compile_method_expression() call */
assignee.ptr = &moo->c->mth.assignees.ptr[assignee_offset]; 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; if (get_variable_info(moo, &assignee, &assignee_loc, assignee_dotted, &var) <= -1) goto oops;
switch (var.type) switch (var.type)
@ -5771,7 +5739,7 @@ static int compile_method_expression (moo_t* moo, int pop)
break; break;
case VAR_GLOBAL: 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; emit_single_param_instruction(moo, (pop? BCODE_POP_INTO_OBJECT_0: BCODE_STORE_INTO_OBJECT_0), index) <= -1) return -1;
ret = pop; ret = pop;
break; break;
@ -6051,6 +6019,10 @@ static int add_compiled_method (moo_t* moo)
preamble_code = MOO_METHOD_PREAMBLE_RETURN_PROCESS; preamble_code = MOO_METHOD_PREAMBLE_RETURN_PROCESS;
break; break;
case BCODE_PUSH_RECEIVER_NS:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS;
break;
case BCODE_PUSH_NIL: case BCODE_PUSH_NIL:
preamble_code = MOO_METHOD_PREAMBLE_RETURN_NIL; preamble_code = MOO_METHOD_PREAMBLE_RETURN_NIL;
break; 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++) for (i = 0; i < moo->c->cls.var[var_type].initv_count; i++)
{ {
if (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]; ((moo_oop_oop_t)tmp)->slot[j] = moo->c->cls.var[var_type].initv[i].v;
j++; 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)); 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++) 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].v;
moo->c->cls.self_oop->slot[j] = moo->c->cls.var[VAR_CLASS].initv[i];
j++; j++;
} }
} }
@ -6929,6 +6900,7 @@ static int __compile_class_definition (moo_t* moo, int extend)
else else
{ {
int super_is_nil = 0; 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); 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; if (set_superclass_fqn(moo, TOKEN_NAME(moo)) <= -1) return -1;
moo->c->cls.superfqn_loc = moo->c->tok.loc; moo->c->cls.superfqn_loc = moo->c->tok.loc;
if (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED) superfqn_is_dotted = (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;
}
GET_TOKEN (moo); GET_TOKEN (moo);
if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN) if (TOKEN_TYPE(moo) != MOO_IOTOK_RPAREN)
@ -6980,7 +6942,6 @@ static int __compile_class_definition (moo_t* moo, int extend)
GET_TOKEN (moo); 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); ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.ns_oop, &moo->c->cls.name);
if (ass) if (ass)
{ {
@ -7009,19 +6970,21 @@ static int __compile_class_definition (moo_t* moo, int extend)
} }
else else
{ {
ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->c->cls.superns_oop, &moo->c->cls.supername); var_info_t var;
if (!ass && moo->c->cls.superns_oop != moo->sysdic)
ass = moo_lookupdic (moo, (moo_oop_dic_t)moo->sysdic, &moo->c->cls.supername); if (get_variable_info (moo, &moo->c->cls.superfqn, &moo->c->cls.superfqn_loc, superfqn_is_dotted, &var) <= -1) return -1;
if (ass &&
MOO_CLASSOF(moo, ass->value) == moo->_class &&
MOO_OBJ_GET_FLAGS_KERNEL(ass->value) != 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 /* the value found must be a class and it must not be
* an incomplete internal class object. * an incomplete internal class object.
* 0(non-kernel object) * 0(non-kernel object)
* 1(incomplete kernel object), * 1(incomplete kernel object),
* 2(complete 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. */ /* the superclass became known. */
if (((moo_oop_class_t)moo->c->cls.super_oop)->trsize != moo->_nil && 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 else
{ {
unknown_superclass:
/* there is no object with such a name. or, /* there is no object with such a name. or,
* the object found with the name is not a class object. or, * the object found with the name is not a class object. or,
* the class object found is a internally defined kernel * 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); GET_TOKEN (moo);
if (compile_class_level_imports(moo) <= -1) return -1; 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; else break;
} }
while (1); while (1);
@ -7247,12 +7205,6 @@ static int __compile_class_definition (moo_t* moo, int extend)
GET_TOKEN (moo); GET_TOKEN (moo);
if (compile_method_definition(moo) <= -1) return -1; 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; else break;
} }
while (1); while (1);
@ -7385,14 +7337,22 @@ static moo_oop_t token_to_literal (moo_t* moo, int rdonly)
{ {
var_info_t var; 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 (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)); set_syntax_error (moo, MOO_SYNERR_VARINACC, TOKEN_LOC(moo), TOKEN_NAME(moo));
return MOO_NULL; return MOO_NULL;
} }
/* [NOTE] i don't mark RDONLY on a value resolved via an identifier */ /* [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 */ 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) static int __compile_pooldic_definition (moo_t* moo, moo_pooldic_t* pd)
{ {
moo_oop_t lit; moo_oop_t lit;
@ -7441,14 +7421,9 @@ static int __compile_pooldic_definition (moo_t* moo, moo_pooldic_t* pd)
goto oops; goto oops;
} }
if (moo->c->cls.self_oop && TOKEN_TYPE(moo) == MOO_IOTOK_IDENT_DOTTED) MOO_ASSERT (moo, moo->c->cls.ns_oop == MOO_NULL);
{ MOO_ASSERT (moo, moo->c->cls.super_oop == MOO_NULL);
/* nested pooldic definition in a class definition */ MOO_ASSERT (moo, moo->c->cls.self_oop == MOO_NULL);
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 */
if (set_pooldic_fqn(moo, pd, TOKEN_NAME(moo)) <= -1) goto oops; if (set_pooldic_fqn(moo, pd, TOKEN_NAME(moo)) <= -1) goto oops;
pd->fqn_loc = moo->c->tok.loc; 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); GET_TOKEN (moo);
pd->start = moo->c->arlit.count;
pd->end = moo->c->arlit.count;
while (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT) while (TOKEN_TYPE(moo) == MOO_IOTOK_IDENT)
{ {
lit = moo_makesymbol (moo, TOKEN_NAME_PTR(moo), TOKEN_NAME_LEN(moo)); 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 }, /* for this definition, #pooldic MyPoolDic { a := 10. b := 20 },
* arlit_buffer contains (#a 10 #b 20) when the 'while' loop is over. */ * arlit_buffer contains (#a 10 #b 20) when the 'while' loop is over. */
if (add_to_array_literal_buffer(moo, lit) <= -1) goto oops; if (add_to_array_literal_buffer(moo, lit) <= -1) goto oops;
pd->end = moo->c->arlit.count;
GET_TOKEN (moo); GET_TOKEN (moo);
/*if (TOKEN_TYPE(moo) == MOO_IOTOK_RBRACE) goto done; /*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++) for (j = 0; j < moo->c->cls.var[i].initv_count; j++)
{ {
register moo_oop_t x = moo->c->cls.var[i].initv[j]; register moo_oop_t x = moo->c->cls.var[i].initv[j].v;
if (x) moo->c->cls.var[i].initv[j] = moo_moveoop (moo, x); 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"); LOG_INST_0 (moo, "push_process");
break; break;
case BCODE_PUSH_RECEIVER_NS:
LOG_INST_0 (moo, "push_receiver_ns");
break;
case BCODE_PUSH_NEGONE: case BCODE_PUSH_NEGONE:
LOG_INST_0 (moo, "push_negone"); LOG_INST_0 (moo, "push_negone");
break; 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"); LOG_INST_0 (moo, "push_two");
break; break;
case BCODE_PUSH_INTLIT: case BCODE_PUSH_INTLIT:
FETCH_PARAM_CODE_TO (moo, b1); FETCH_PARAM_CODE_TO (moo, b1);
LOG_INST_1 (moo, "push_intlit %zu", 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); MOO_STACK_SETTOP (moo, (moo_oop_t)moo->processor->active);
break; 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: case MOO_METHOD_PREAMBLE_RETURN_NIL:
LOG_INST_0 (moo, "preamble_return_nil"); LOG_INST_0 (moo, "preamble_return_nil");
MOO_STACK_POPS (moo, nargs); 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); MOO_STACK_PUSH (moo, (moo_oop_t)moo->processor->active);
break; 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: case BCODE_PUSH_NEGONE:
LOG_INST_0 (moo, "push_negone"); LOG_INST_0 (moo, "push_negone");
MOO_STACK_PUSH (moo, MOO_SMOOI_TO_OOP(-1)); MOO_STACK_PUSH (moo, MOO_SMOOI_TO_OOP(-1));

View File

@ -320,6 +320,7 @@ struct moo_iotok_t
MOO_IOTOK_NUMLIT, MOO_IOTOK_NUMLIT,
MOO_IOTOK_RADNUMLIT, MOO_IOTOK_RADNUMLIT,
MOO_IOTOK_ERRLIT, /* error(NN) */ MOO_IOTOK_ERRLIT, /* error(NN) */
MOO_IOTOK_ERROR, /* error */ MOO_IOTOK_ERROR, /* error */
MOO_IOTOK_NIL, MOO_IOTOK_NIL,
MOO_IOTOK_SELF, MOO_IOTOK_SELF,
@ -328,6 +329,18 @@ struct moo_iotok_t
MOO_IOTOK_FALSE, MOO_IOTOK_FALSE,
MOO_IOTOK_THIS_CONTEXT, MOO_IOTOK_THIS_CONTEXT,
MOO_IOTOK_THIS_PROCESS, 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,
MOO_IOTOK_IDENT_DOTTED, MOO_IOTOK_IDENT_DOTTED,
MOO_IOTOK_BINSEL, MOO_IOTOK_BINSEL,
@ -348,17 +361,7 @@ struct moo_iotok_t
MOO_IOTOK_DICBRACE, /* :{ - dictionary expression */ MOO_IOTOK_DICBRACE, /* :{ - dictionary expression */
MOO_IOTOK_PERIOD, MOO_IOTOK_PERIOD,
MOO_IOTOK_COMMA, MOO_IOTOK_COMMA,
MOO_IOTOK_SEMICOLON, 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
} type; } type;
moo_oocs_t name; moo_oocs_t name;
@ -425,6 +428,9 @@ struct moo_pooldic_t
moo_oop_dic_t pd_oop; moo_oop_dic_t pd_oop;
moo_oop_nsdic_t ns_oop; moo_oop_nsdic_t ns_oop;
moo_oow_t start;
moo_oow_t end;
}; };
typedef struct moo_oopbuf_t moo_oopbuf_t; typedef struct moo_oopbuf_t moo_oopbuf_t;
@ -443,6 +449,13 @@ struct moo_oobbuf_t
moo_oow_t capa; 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 struct moo_compiler_t
{ {
/* input handler */ /* input handler */
@ -490,9 +503,6 @@ struct moo_compiler_t
moo_oop_class_t self_oop; moo_oop_class_t self_oop;
moo_oop_t super_oop; /* this may be nil. so the type is moo_oop_t */ 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_oop_nsdic_t ns_oop;
moo_oocs_t fqn; moo_oocs_t fqn;
moo_oocs_t name; moo_oocs_t name;
@ -508,10 +518,11 @@ struct moo_compiler_t
moo_oocs_t modname; /* module name after 'from' */ moo_oocs_t modname; /* module name after 'from' */
moo_oow_t modname_capa; 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[0] - named instance variables
* var[1] - class instance variables * var[1] - class instance variables
* var[2] - class variables */ * var[2] - class variables
*/
struct struct
{ {
moo_oocs_t str; /* long string containing all variables declared delimited by a space */ 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 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_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; moo_oow_t initv_capa;
/* initv_count holds the index to the last variable with a /* initv_count holds the index to the last variable with a
* default initial value defined in this class only plus one. * default initial value defined in this class only plus one.
@ -545,7 +556,6 @@ struct moo_compiler_t
moo_oop_dic_t* oops; moo_oop_dic_t* oops;
moo_oow_t oops_capa; moo_oow_t oops_capa;
} pooldic_imp; } pooldic_imp;
} cls; } cls;
/* pooldic declaration */ /* pooldic declaration */
@ -611,27 +621,6 @@ struct moo_compiler_t
moo_oow_t code_capa; moo_oow_t code_capa;
} mth; } 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 #endif
#if defined(MOO_USE_METHOD_TRAILER) #if defined(MOO_USE_METHOD_TRAILER)
@ -891,13 +880,14 @@ enum moo_bcode_t
BCODE_PUSH_FALSE = 0x84, /* 132 */ BCODE_PUSH_FALSE = 0x84, /* 132 */
BCODE_PUSH_CONTEXT = 0x85, /* 133 */ BCODE_PUSH_CONTEXT = 0x85, /* 133 */
BCODE_PUSH_PROCESS = 0x86, /* 134 */ BCODE_PUSH_PROCESS = 0x86, /* 134 */
BCODE_PUSH_NEGONE = 0x87, /* 135 */ BCODE_PUSH_RECEIVER_NS = 0x87, /* 135 */
BCODE_POP_INTO_INSTVAR_X = 0x88, /* 136 ## */ BCODE_POP_INTO_INSTVAR_X = 0x88, /* 136 ## */
BCODE_PUSH_ZERO = 0x89, /* 137 */ BCODE_PUSH_NEGONE = 0x89, /* 137 */
BCODE_PUSH_ONE = 0x8A, /* 138 */ BCODE_PUSH_ZERO = 0x8A, /* 138 */
BCODE_PUSH_TWO = 0x8B, /* 139 */ BCODE_PUSH_ONE = 0x8B, /* 139 */
BCODE_PUSH_TWO = 0x8C, /* 140 */
BCODE_PUSH_INSTVAR_X = 0x90, /* 144 ## */ BCODE_PUSH_INSTVAR_X = 0x90, /* 144 ## */
BCODE_PUSH_TEMPVAR_X = 0x98, /* 152 ## */ 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_nsdic_t;
typedef struct moo_nsdic_t* moo_oop_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_class_t;
typedef struct moo_class_t* moo_oop_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 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_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 */ moo_oop_t trsize; /* trailer size for new instances */
/* [0] - initial values for instance variables of 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: * The code can be one of the following values:
* 0 - no special action * 0 - no special action
* 1 - return self * 1 - return self (receiver)
* 2 - return thisContext (not used) * 2 - return thisContext (not used)
* 3 - return thisProcess * 3 - return thisProcess
* 4 - return nil * 4 - return nil
@ -627,11 +625,12 @@ struct moo_method_t
* 6 - return false * 6 - return false
* 7 - return index. * 7 - return index.
* 8 - return -index. * 8 - return -index.
* 9 - return instvar[index] * 9 - return selfns
* 10 - do primitive[index] * 10 - return instvar[index]
* 11 - do named primitive[index] * 11 - do primitive[index]
* 12 - exception handler * 12 - do named primitive[index]
* 13 - ensure block * 13 - exception handler
* 14 - ensure block
*/ */
/* [NOTE] changing preamble code bit structure requires changes to CompiledMethod>>preambleCode */ /* [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_RECEIVER 1
#define MOO_METHOD_PREAMBLE_RETURN_CONTEXT 2 #define MOO_METHOD_PREAMBLE_RETURN_CONTEXT 2
#define MOO_METHOD_PREAMBLE_RETURN_PROCESS 3 #define MOO_METHOD_PREAMBLE_RETURN_PROCESS 3
#define MOO_METHOD_PREAMBLE_RETURN_NIL 4 #define MOO_METHOD_PREAMBLE_RETURN_RECEIVER_NS 4
#define MOO_METHOD_PREAMBLE_RETURN_TRUE 5 #define MOO_METHOD_PREAMBLE_RETURN_NIL 5
#define MOO_METHOD_PREAMBLE_RETURN_FALSE 6 #define MOO_METHOD_PREAMBLE_RETURN_TRUE 6
#define MOO_METHOD_PREAMBLE_RETURN_INDEX 7 #define MOO_METHOD_PREAMBLE_RETURN_FALSE 7
#define MOO_METHOD_PREAMBLE_RETURN_NEGINDEX 8 #define MOO_METHOD_PREAMBLE_RETURN_INDEX 8
#define MOO_METHOD_PREAMBLE_RETURN_INSTVAR 9 #define MOO_METHOD_PREAMBLE_RETURN_NEGINDEX 9
#define MOO_METHOD_PREAMBLE_PRIMITIVE 10 #define MOO_METHOD_PREAMBLE_RETURN_INSTVAR 10
#define MOO_METHOD_PREAMBLE_NAMED_PRIMITIVE 11 /* index is an index to the symbol table */ #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 12 /* NOTE changing this requires changes in Except.st */ #define MOO_METHOD_PREAMBLE_EXCEPTION 13 /* 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_ENSURE 14 /* NOTE changing this requires changes in Except.st */
/* the index is an 16-bit unsigned integer. */ /* the index is an 16-bit unsigned integer. */
#define MOO_METHOD_PREAMBLE_INDEX_MIN 0x0000 #define MOO_METHOD_PREAMBLE_INDEX_MIN 0x0000