Starting packages

This commit is contained in:
rogerl%netscape.com 2003-04-22 22:51:38 +00:00
parent 0bc89daad7
commit be2c3f401f
2 changed files with 138 additions and 12 deletions

View File

@ -447,11 +447,21 @@ namespace MetaData {
case Attribute::Virtual:
case Attribute::Final:
{
// XXX Here the spec. has ???, so the following is tentative
FunctionInstance *fObj = validateStaticFunction(&f->function, compileThis, prototype, unchecked, cxt, env);
JS2Class *c = checked_cast<JS2Class *>(env->getTopFrame());
Multiname *mn = new Multiname(f->function.name, a->namespaces);
InstanceMember *m = new InstanceMethod(mn, fObj, (memberMod == Attribute::Final), true);
InstanceMember *m;
switch (f->function.prefix) {
case FunctionName::normal:
m = new InstanceMethod(mn, fObj, (memberMod == Attribute::Final), true);
break;
case FunctionName::Set:
m = new InstanceSetter(mn, fObj, objectClass, (memberMod == Attribute::Final), true);
break;
case FunctionName::Get:
m = new InstanceGetter(mn, fObj, objectClass, (memberMod == Attribute::Final), true);
break;
}
defineInstanceMember(c, cxt, f->function.name, a->namespaces, a->overrideMod, a->xplicit, m, p->pos);
}
break;
@ -639,6 +649,67 @@ namespace MetaData {
break;
case StmtNode::empty:
break;
case StmtNode::Package:
{
PackageStmtNode *ps = checked_cast<PackageStmtNode *>(p);
String packageName = getPackageName(ps->packageIdList);
Package *package = new Package(packageName, new Namespace(&world.identifiers["internal"]));
package->status = Package::InTransit;
packages.push_back(package);
env->addFrame(package);
ValidateStmt(cxt, env, pl, ps->body);
env->removeTopFrame();
package->status = Package::InHand;
}
break;
case StmtNode::Import:
{
ImportStmtNode *i = checked_cast<ImportStmtNode *>(p);
String packageName;
if (i->packageIdList)
packageName = getPackageName(i->packageIdList);
else
packageName = *i->packageString;
if (!checkForPackage(packageName, i->pos))
loadPackage(packageName, packageName + ".js");
Multiname mn(&packageName, publicNamespace);
js2val packageValue;
env->lexicalRead(this, &mn, CompilePhase, &packageValue, NULL);
if (JS2VAL_IS_VOID(packageValue) || JS2VAL_IS_NULL(packageValue) || !JS2VAL_IS_OBJECT(packageValue)
|| (JS2VAL_TO_OBJECT(packageValue)->kind != PackageKind))
reportError(Exception::badValueError, "Package expected in Import directive", i->pos);
#if 0
Package *package = checked_cast<Package *>(JS2VAL_TO_OBJECT(packageValue));
if (i->varName)
// defineVariable(m_cx, *i->varName, NULL, Package_Type, JSValue::newPackage(package));
// scan all local bindings in 'package' and handle the alias-ing issue...
for (PropertyIterator it = package->mProperties.begin(), end = package->mProperties.end();
(it != end); it++)
{
ASSERT(PROPERTY_KIND(it) == ValuePointer);
bool makeAlias = true;
if (i->includeExclude) {
makeAlias = i->exclude;
IdentifierList *idList = i->includeExclude;
while (idList) {
if (idList->name.compare(PROPERTY_NAME(it)) == 0) {
makeAlias = !makeAlias;
break;
}
idList = idList->next;
}
}
if (makeAlias)
defineAlias(m_cx, PROPERTY_NAME(it), PROPERTY_NAMESPACELIST(it), PROPERTY_ATTR(it), PROPERTY_TYPE(it), PROPERTY_VALUEPOINTER(it));
}
#endif
}
break;
default:
NOT_REACHED("Not Yet Implemented");
} // switch (p->getKind())
@ -649,6 +720,49 @@ namespace MetaData {
}
}
/*
Build a name for the package from the identifier list
*/
String JS2Metadata::getPackageName(IdentifierList *packageIdList)
{
String packagePath;
IdentifierList *idList = packageIdList;
while (idList) {
packagePath += idList->name;
idList = idList->next;
if (idList)
packagePath += '/'; // XXX how to get path separator for OS?
}
return packagePath;
}
/*
See if the specified package is already loaded - return true
Throw an exception if the package is being loaded already
*/
bool JS2Metadata::checkForPackage(const String &packageName, size_t pos)
{
// XXX linear search
for (PackageList::iterator pi = packages.begin(), end = packages.end(); (pi != end); pi++) {
if ((*pi)->name.compare(packageName) == 0) {
if ((*pi)->status == Package::InTransit)
reportError(Exception::referenceError, "Package circularity", pos);
else
return true;
}
}
return false;
}
/*
Load the specified package from the file
*/
void JS2Metadata::loadPackage(const String & /*packageName*/, const String &filename)
{
// XXX need some rules for search path
// XXX need to extract just the target package from the file
readEvalFile(filename);
}
JS2Class *JS2Metadata::getVariableType(Variable *v, Phase phase, size_t pos)
{
@ -3406,7 +3520,7 @@ bool nullClass_BracketDelete(JS2Metadata *meta, js2val base, JS2Class *limit, Mu
engine(new JS2Engine(world)),
publicNamespace(new Namespace(engine->public_StringAtom)),
bCon(new BytecodeContainer()),
glob(new Package(new Namespace(&world.identifiers["internal"]))),
glob(new Package(widenCString("global"), new Namespace(&world.identifiers["internal"]))),
env(new Environment(new MetaData::SystemFrame(), glob)),
flags(JS1),
showTrees(false),
@ -4409,7 +4523,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
JS2Object *obj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass);
DEFINE_ROOTKEEPER(rk2, obj);
meta->createDynamicProperty(this, meta->engine->prototype_StringAtom, OBJECT_TO_JS2VAL(obj), ReadWriteAccess, false, true);
meta->createDynamicProperty(this, meta->engine->prototype_StringAtom, OBJECT_TO_JS2VAL(obj), ReadWriteAccess, true, false);
}

View File

@ -559,9 +559,9 @@ public:
class InstanceGetter : public InstanceMember {
public:
InstanceGetter(Multiname *multiname, Invokable *code, JS2Class *type, bool final, bool enumerable)
: InstanceMember(InstanceGetterMember, multiname, final, enumerable), code(code), type(type) { }
Invokable *code; // A callable object which does the read or write; null if this method is abstract
InstanceGetter(Multiname *multiname, FunctionInstance *fInst, JS2Class *type, bool final, bool enumerable)
: InstanceMember(InstanceGetterMember, multiname, final, enumerable), fInst(fInst), type(type) { }
FunctionInstance *fInst; // A callable object which does the read or write; null if this method is abstract
JS2Class *type; // Type of values that may be stored in this variable
virtual Access instanceMemberAccess() { return ReadAccess; }
@ -569,9 +569,9 @@ public:
class InstanceSetter : public InstanceMember {
public:
InstanceSetter(Multiname *multiname, Invokable *code, JS2Class *type, bool final, bool enumerable)
: InstanceMember(InstanceSetterMember, multiname, final, enumerable), code(code), type(type) { }
Invokable *code; // A callable object which does the read or write; null if this method is abstract
InstanceSetter(Multiname *multiname, FunctionInstance *fInst, JS2Class *type, bool final, bool enumerable)
: InstanceMember(InstanceSetterMember, multiname, final, enumerable), fInst(fInst), type(type) { }
FunctionInstance *fInst; // A callable object which does the read or write; null if this method is abstract
JS2Class *type; // Type of values that may be stored in this variable
virtual Access instanceMemberAccess() { return WriteAccess; }
@ -772,10 +772,15 @@ public:
class Package : public NonWithFrame {
public:
Package(Namespace *internal) : NonWithFrame(PackageKind), super(JS2VAL_VOID), sealed(false), internalNamespace(internal) { }
typedef enum { InTransit, InHand } PackageStatus;
Package(const String &name, Namespace *internal) : NonWithFrame(PackageKind), super(JS2VAL_VOID), sealed(false), internalNamespace(internal), name(name) { }
js2val super;
bool sealed;
Namespace *internalNamespace; // This Package's internal namespace
PackageStatus status;
String name;
virtual void markChildren();
virtual ~Package() { }
};
@ -1458,7 +1463,14 @@ public:
bool showTrees; // debug only, causes parse tree dump
Arena *referenceArena;
Arena *referenceArena; // allocation arena for all reference objects
typedef std::vector<Package *> PackageList;
PackageList packages; // the currently loaded packages, packages.back() is the current package
bool checkForPackage(const String &packageName, size_t pos); // return true if loaded, throw exception if loading
void loadPackage(const String &packageName, const String &filename); // load package from file
String getPackageName(IdentifierList *packageIdList);
};