changed find_dotted_ident() and find_undotted_ident()

This commit is contained in:
hyunghwan.chung 2019-10-03 10:30:05 +00:00
parent 209c6bf691
commit e1d71f340e

View File

@ -260,7 +260,6 @@ static int compile_class_definition (moo_t* moo, int class_type);
static int compile_block_statement (moo_t* moo); static int compile_block_statement (moo_t* moo);
static int compile_method_statement (moo_t* moo); 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 MOO_INLINE 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_oop_t find_element_in_compiling_pooldic (moo_t* moo, const moo_oocs_t* name);
@ -2432,6 +2431,94 @@ static int end_include (moo_t* moo)
return 1; /* ended the included file successfully */ return 1; /* ended the included file successfully */
} }
/* ---------------------------------------------------------------------
* Literal
* --------------------------------------------------------------------- */
static MOO_INLINE int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index)
{
#if 0
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
moo_oow_t i;
for (i = 0; i < cc->mth.literals.count; i++)
{
/*
* this removes redundancy of symbols, characters, and small integers.
* more complex redundacy check may be done somewhere else like
* in add_string_literal().
*/
if (cc->mth.literals.ptr[i] == lit)
{
*index = i;
return 0;
}
}
if (add_oop_to_oopbuf(moo, &cc->mth.literals, lit) <= -1) return -1;
*index = cc->mth.literals.count - 1;
return 0;
#else
/*
* this removes redundancy of symbols, characters, and small integers.
* more complex redundacy check may be done somewhere else like
* in add_string_literal().
*/
return add_oop_to_oopbuf_nodup(moo, &((moo_cunit_class_t*)moo->c->cunit)->mth.literals, lit, index);
#endif
}
static int add_string_literal (moo_t* moo, const moo_oocs_t* str, moo_oow_t* index)
{
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
moo_oop_t lit;
moo_oow_t i;
for (i = 0; i < cc->mth.literals.count; i++)
{
lit = cc->mth.literals.ptr[i];
if (MOO_CLASSOF(moo, lit) == moo->_string &&
MOO_OBJ_GET_SIZE(lit) == str->len &&
moo_equal_oochars(MOO_OBJ_GET_CHAR_SLOT(lit), str->ptr, str->len))
{
*index = i;
return 0;
}
}
lit = moo_instantiate(moo, moo->_string, str->ptr, str->len);
if (!lit) return -1;
MOO_OBJ_SET_FLAGS_RDONLY (lit, 1);
return add_literal(moo, lit, index);
}
static int add_symbol_literal (moo_t* moo, const moo_oocs_t* str, moo_oow_t offset, moo_oow_t* index)
{
moo_oop_t tmp;
tmp = moo_makesymbol(moo, str->ptr + offset, str->len - offset);
if (!tmp) return -1;
MOO_OBJ_SET_FLAGS_RDONLY (tmp, 1);
return add_literal(moo, tmp, index);
}
static int add_byte_array_literal (moo_t* moo, const moo_oocs_t* str, moo_oow_t* index)
{
/* see read_byte_array_literal for comparision */
moo_oop_t tmp;
moo_oow_t i;
tmp = moo_instantiate(moo, moo->_byte_array, MOO_NULL, str->len);
if (!tmp) return -1;
for (i = 0; i < str->len; i++) MOO_OBJ_SET_BYTE_VAL(tmp, i, str->ptr[i]);
MOO_OBJ_SET_FLAGS_RDONLY (tmp, 1);
return add_literal(moo, tmp, index);
}
/* --------------------------------------------------------------------- /* ---------------------------------------------------------------------
* Byte-Code Manipulation Functions * Byte-Code Manipulation Functions
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
@ -3006,90 +3093,6 @@ static void eliminate_instructions (moo_t* moo, moo_oow_t start, moo_oow_t end)
* Compiler * Compiler
* --------------------------------------------------------------------- */ * --------------------------------------------------------------------- */
static MOO_INLINE int add_literal (moo_t* moo, moo_oop_t lit, moo_oow_t* index)
{
#if 0
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
moo_oow_t i;
for (i = 0; i < cc->mth.literals.count; i++)
{
/*
* this removes redundancy of symbols, characters, and small integers.
* more complex redundacy check may be done somewhere else like
* in add_string_literal().
*/
if (cc->mth.literals.ptr[i] == lit)
{
*index = i;
return 0;
}
}
if (add_oop_to_oopbuf(moo, &cc->mth.literals, lit) <= -1) return -1;
*index = cc->mth.literals.count - 1;
return 0;
#else
/*
* this removes redundancy of symbols, characters, and small integers.
* more complex redundacy check may be done somewhere else like
* in add_string_literal().
*/
return add_oop_to_oopbuf_nodup(moo, &((moo_cunit_class_t*)moo->c->cunit)->mth.literals, lit, index);
#endif
}
static int add_string_literal (moo_t* moo, const moo_oocs_t* str, moo_oow_t* index)
{
moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
moo_oop_t lit;
moo_oow_t i;
for (i = 0; i < cc->mth.literals.count; i++)
{
lit = cc->mth.literals.ptr[i];
if (MOO_CLASSOF(moo, lit) == moo->_string &&
MOO_OBJ_GET_SIZE(lit) == str->len &&
moo_equal_oochars(MOO_OBJ_GET_CHAR_SLOT(lit), str->ptr, str->len))
{
*index = i;
return 0;
}
}
lit = moo_instantiate(moo, moo->_string, str->ptr, str->len);
if (!lit) return -1;
MOO_OBJ_SET_FLAGS_RDONLY (lit, 1);
return add_literal(moo, lit, index);
}
static int add_symbol_literal (moo_t* moo, const moo_oocs_t* str, moo_oow_t offset, moo_oow_t* index)
{
moo_oop_t tmp;
tmp = moo_makesymbol(moo, str->ptr + offset, str->len - offset);
if (!tmp) return -1;
MOO_OBJ_SET_FLAGS_RDONLY (tmp, 1);
return add_literal(moo, tmp, index);
}
static int add_byte_array_literal (moo_t* moo, const moo_oocs_t* str, moo_oow_t* index)
{
/* see read_byte_array_literal for comparision */
moo_oop_t tmp;
moo_oow_t i;
tmp = moo_instantiate(moo, moo->_byte_array, MOO_NULL, str->len);
if (!tmp) return -1;
for (i = 0; i < str->len; i++) MOO_OBJ_SET_BYTE_VAL(tmp, i, str->ptr[i]);
MOO_OBJ_SET_FLAGS_RDONLY (tmp, 1);
return add_literal(moo, tmp, index);
}
static MOO_INLINE int set_class_fqn (moo_t* moo, moo_cunit_class_t* cc, const moo_oocs_t* name) static MOO_INLINE int set_class_fqn (moo_t* moo, moo_cunit_class_t* cc, const moo_oocs_t* name)
{ {
if (copy_string_to(moo, name, &cc->fqn, &cc->fqn_capa, 0, '\0') <= -1) return -1; if (copy_string_to(moo, name, &cc->fqn, &cc->fqn_capa, 0, '\0') <= -1) return -1;
@ -4611,32 +4614,61 @@ static MOO_INLINE int find_dotted_ident (moo_t* moo, const moo_oocs_t* name, con
} }
} }
if (!cc->self_oop) goto varinacc;
top_dic = cc->self_oop->nsdic; /* namespace that the current interface starts */
pxlen++; /* include . into the length */
break; break;
} }
case MOO_CUNIT_INTERFACE: case MOO_CUNIT_INTERFACE:
default: {
/* interface doesn't support inheritance nor does it allow moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;
* method body. let it flow down to the next check to if (!ifce->self_oop) goto varinacc;
* trigger an error(MOO_SYNERR_VARINACC below) */ top_dic = ifce->self_oop->nsdic; /* namespace that the current interface starts */
pxlen++; /* include . into the length */
break; break;
}
default:
varinacc:
moo_setsynerr (moo, MOO_SYNERR_VARINACC, name_loc, name);
return -1;
} }
} }
else
if (moo->c->cunit->cunit_type != MOO_CUNIT_CLASS || !((moo_cunit_class_t*)moo->c->cunit)->self_oop)
{ {
/* self is not usable when it's not compiling in a class. /* more than 3 segments. e.g. self.XXX.YYY */
* a pooldic definition cannot contain subdictionaries. switch (moo->c->cunit->cunit_type)
* the pooldic is a terminal point and the items inside {
* are final nodes. if self is followed by more than 1 case MOO_CUNIT_POOLDIC:
* subsegments, it's an error */ /* a pooldic definition cannot contain subdictionaries.
moo_setsynerr (moo, MOO_SYNERR_VARINACC, name_loc, name); * the pooldic is a terminal point and the items inside
return -1; * are final nodes. if self is followed by more than 1
} * subsegments, it's an error. */
goto varinacc;
/* namespace that the current class starts */ case MOO_CUNIT_CLASS:
top_dic = ((moo_cunit_class_t*)moo->c->cunit)->self_oop->nsdic; {
pxlen++; /* include . into the length */ moo_cunit_class_t* cc = (moo_cunit_class_t*)moo->c->cunit;
if (!cc->self_oop) goto varinacc;
top_dic = cc->self_oop->nsdic; /* namespace that the current class starts */
pxlen++; /* include . into the length */
break;
}
case MOO_CUNIT_INTERFACE:
{
moo_cunit_interface_t* ifce = (moo_cunit_interface_t*)moo->c->cunit;
if (!ifce->self_oop) goto varinacc;
top_dic = ifce->self_oop->nsdic; /* namespace that the current interface starts */
pxlen++; /* include . into the length */
break;
}
default:
goto varinacc;
}
}
} }
else if ((pxlen = is_dotted_ident_prefixed(name, VOCA_SELFNS)) > 0) else if ((pxlen = is_dotted_ident_prefixed(name, VOCA_SELFNS)) > 0)
{ {
@ -4695,101 +4727,151 @@ static MOO_INLINE int find_undotted_ident (moo_t* moo, const moo_oocs_t* name, c
moo_oow_t index; moo_oow_t index;
moo_oop_association_t ass; moo_oop_association_t ass;
if (moo->c->cunit->cunit_type == MOO_CUNIT_POOLDIC) switch (moo->c->cunit->cunit_type)
{ {
moo_oop_t v; case MOO_CUNIT_POOLDIC:
/* called inside a pooldic definition */
MOO_ASSERT (moo, ((moo_cunit_pooldic_t*)moo->c->cunit)->ns_oop != MOO_NULL);
MOO_ASSERT (moo, ((moo_cunit_pooldic_t*)moo->c->cunit)->pd_oop == MOO_NULL);
v = find_element_in_compiling_pooldic(moo, name);
if (!v)
{ {
moo_setsynerr (moo, MOO_SYNERR_VARUNDCL, name_loc, name); moo_oop_t v;
return -1;
}
var->type = VAR_LITERAL; /* called inside a pooldic definition */
var->u.lit = v; /* TODO: change this */ MOO_ASSERT (moo, ((moo_cunit_pooldic_t*)moo->c->cunit)->ns_oop != MOO_NULL);
} MOO_ASSERT (moo, ((moo_cunit_pooldic_t*)moo->c->cunit)->pd_oop == MOO_NULL);
else
{
moo_cunit_class_t* cc = ((moo_cunit_class_t*)moo->c->cunit);
MOO_ASSERT (moo, moo->c->cunit->cunit_type == MOO_CUNIT_CLASS);
if (cc->self_oop) v = find_element_in_compiling_pooldic(moo, name);
{ if (!v)
/* the current class being compiled has been instantiated.
* look up in the temporary variable list if compiling in a method */
if (cc->mth.active && find_temporary_variable(moo, &cc->mth, name, &index) >= 0)
{
var->type = (index < cc->mth.tmpr_nargs)? VAR_ARGUMENT: VAR_TEMPORARY;
var->pos = index;
return 0;
}
}
if (cc->in_class_body)
{
/* called inside a class definition */
/* read a comment in find_dotted_ident() for the reason behind
* the 'if' condition above. */
MOO_ASSERT (moo, cc->super_oop != MOO_NULL);
MOO_ASSERT (moo, cc->ns_oop != MOO_NULL);
if (find_class_level_variable(moo, cc->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 cc->self_oop? validate_class_level_variable(moo, var, name, name_loc): 0;
}
}
/* find an undotted identifier in dictionaries */
if (cc->ns_oop)
{
ass = moo_lookupdic(moo, (moo_oop_dic_t)cc->ns_oop, name); /* in the current name space */
if (!ass && cc->ns_oop != moo->sysdic)
ass = moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, name); /* in the top-level system dictionary */
}
else
{
ass = moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, name); /* in the top-level system dictionary */
}
if (!ass)
{
moo_oow_t i;
moo_oop_association_t ass2 = MOO_NULL;
/* attempt to find the variable in pool dictionaries */
for (i = 0; i < cc->pdimp.dcl_count; i++)
{
ass = moo_lookupdic(moo, cc->pdimp.oops[i], name);
if (ass)
{
if (ass2)
{
/* the variable name has been found at least in 2 dictionaries - ambiguous */
moo_setsynerr (moo, MOO_SYNERR_VARAMBIG, name_loc, name);
return -1;
}
ass2 = ass;
}
}
ass = ass2;
if (!ass)
{ {
moo_setsynerr (moo, MOO_SYNERR_VARUNDCL, name_loc, name); moo_setsynerr (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1; return -1;
} }
var->type = VAR_LITERAL;
var->u.lit = v; /* TODO: change this */
break;
} }
var->type = VAR_GLOBAL;
var->u.gbl = ass; case MOO_CUNIT_CLASS:
{
moo_cunit_class_t* cc = ((moo_cunit_class_t*)moo->c->cunit);
if (cc->self_oop)
{
/* the current class being compiled has been instantiated.
* look up in the temporary variable list if compiling in a method */
if (cc->mth.active && find_temporary_variable(moo, &cc->mth, name, &index) >= 0)
{
var->type = (index < cc->mth.tmpr_nargs)? VAR_ARGUMENT: VAR_TEMPORARY;
var->pos = index;
return 0;
}
}
if (cc->in_class_body)
{
/* called inside a class definition */
/* read a comment in find_dotted_ident() for the reason behind
* the 'if' condition above. */
MOO_ASSERT (moo, cc->super_oop != MOO_NULL);
MOO_ASSERT (moo, cc->ns_oop != MOO_NULL);
if (find_class_level_variable(moo, cc->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 cc->self_oop? validate_class_level_variable(moo, var, name, name_loc): 0;
}
}
/* find an undotted identifier in dictionaries */
if (cc->ns_oop)
{
ass = moo_lookupdic(moo, (moo_oop_dic_t)cc->ns_oop, name); /* in the current name space */
if (!ass && cc->ns_oop != moo->sysdic)
ass = moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, name); /* in the top-level system dictionary */
}
else
{
ass = moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, name); /* in the top-level system dictionary */
}
if (!ass)
{
moo_oow_t i;
moo_oop_association_t ass2 = MOO_NULL;
/* attempt to find the variable in pool dictionaries */
for (i = 0; i < cc->pdimp.dcl_count; i++)
{
ass = moo_lookupdic(moo, cc->pdimp.oops[i], name);
if (ass)
{
if (ass2)
{
/* the variable name has been found at least in 2 dictionaries - ambiguous */
moo_setsynerr (moo, MOO_SYNERR_VARAMBIG, name_loc, name);
return -1;
}
ass2 = ass;
}
}
ass = ass2;
if (!ass)
{
moo_setsynerr (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
}
var->type = VAR_GLOBAL;
var->u.gbl = ass;
break;
}
case MOO_CUNIT_INTERFACE:
{
/* TODO: */
moo_cunit_interface_t* ifce = ((moo_cunit_interface_t*)moo->c->cunit);
if (ifce->self_oop)
{
/* the current class being compiled has been instantiated.
* look up in the temporary variable list if compiling in a method */
if (ifce->mth.active && find_temporary_variable(moo, &ifce->mth, name, &index) >= 0)
{
var->type = (index < ifce->mth.tmpr_nargs)? VAR_ARGUMENT: VAR_TEMPORARY;
var->pos = index;
return 0;
}
}
if (ifce->ns_oop)
{
ass = moo_lookupdic(moo, (moo_oop_dic_t)ifce->ns_oop, name); /* in the current name space */
if (!ass && ifce->ns_oop != moo->sysdic)
ass = moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, name); /* in the top-level system dictionary */
}
else
{
ass = moo_lookupdic(moo, (moo_oop_dic_t)moo->sysdic, name); /* in the top-level system dictionary */
}
if (!ass)
{
moo_setsynerr (moo, MOO_SYNERR_VARUNDCL, name_loc, name);
return -1;
}
var->type = VAR_GLOBAL;
var->u.gbl = ass;
break;
}
default:
/* it must not happen. internal error if it happens */
moo_setsynerr (moo, MOO_SYNERR_VARINACC, name_loc, name);
return -1;
} }
return 0; return 0;