Merged JSMap & JSObject. Introduced JSNamespace.

This commit is contained in:
beard%netscape.com 2000-04-28 23:04:43 +00:00
parent 2f139b43ae
commit 1f0e341d77
8 changed files with 134 additions and 90 deletions

View File

@ -210,13 +210,13 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
case LOAD_NAME:
{
LoadName* ln = static_cast<LoadName*>(instruction);
(*registers)[dst(ln)] = mGlobal->getProperty(*src1(ln));
(*registers)[dst(ln)] = mGlobal->getVariable(*src1(ln));
}
break;
case SAVE_NAME:
{
SaveName* sn = static_cast<SaveName*>(instruction);
mGlobal->setProperty(*dst(sn), (*registers)[src1(sn)]);
mGlobal->setVariable(*dst(sn), (*registers)[src1(sn)]);
}
break;
case NEW_OBJECT:

View File

@ -35,16 +35,16 @@ namespace Interpreter {
class Context : public gc_base {
public:
explicit Context(World& world, JSObject* aGlobal)
explicit Context(World& world, JSNamespace* aGlobal)
: mWorld(world), mGlobal(aGlobal), mLinkage(0)
{
}
JSObject* getGlobalObject() { return mGlobal; }
JSNamespace* getGlobalObject() { return mGlobal; }
JSObject* setGlobalObject(JSObject* aGlobal)
JSNamespace* setGlobalObject(JSNamespace* aGlobal)
{
JSObject* t = mGlobal;
JSNamespace* t = mGlobal;
mGlobal = aGlobal;
return t;
}
@ -72,7 +72,7 @@ namespace Interpreter {
private:
World& mWorld;
JSObject* mGlobal;
JSNamespace* mGlobal;
Linkage* mLinkage;
std::vector<Listener*> mListeners;
}; /* class Context */

View File

@ -272,7 +272,7 @@ static void testICG(World &world)
static float64 testFunctionCall(World &world, float64 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
Tracer t;
cx.addListener(&t);
@ -325,7 +325,7 @@ static float64 testFunctionCall(World &world, float64 n)
static float64 testFactorial(World &world, float64 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
// generate code for factorial, and interpret it.
uint32 position = 0;
@ -390,7 +390,7 @@ static float64 testFactorial(World &world, float64 n)
static float64 testObjects(World &world, int32 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
// create some objects, put some properties, and retrieve them.
uint32 position = 0;
@ -456,7 +456,7 @@ static float64 testObjects(World &world, int32 n)
static float64 testProto(World &world, int32 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
Tracer t;
@ -515,8 +515,8 @@ static float64 testProto(World &world, int32 n)
cx.interpret(initCode, args);
// objects now exist, do real prototype chain manipulation.
JSObject* globalObject = glob.getProperty(global).object;
globalObject->setPrototype(glob.getProperty(proto).object);
JSObject* globalObject = glob.getVariable(global).object;
globalObject->setPrototype(glob.getVariable(proto).object);
// generate call to global.increment()
ICodeGenerator callCG;
@ -533,7 +533,7 @@ static float64 testProto(World &world, int32 n)
while (n-- > 0)
(void) cx.interpret(callCode, args);
JSValue result = glob.getProperty(global).object->getProperty(counter);
JSValue result = glob.getVariable(global).object->getProperty(counter);
stdOut << "result = " << result.f64 << "\n";

View File

@ -118,17 +118,20 @@ namespace JSTypes {
extern const JSValue kUndefinedValue;
/**
* Basic behavior of all JS objects, mapping a name to a value.
* This is provided mainly to avoid having an awkward implementation
* of JSObject & JSArray, which must each define its own
* gc_allocator. This is all in flux.
* Basic behavior of all JS objects, mapping a name to a value,
* with prototype-based inheritance.
*/
class JSMap : public gc_base {
class JSObject : public gc_base {
protected:
typedef std::map<String, JSValue, std::less<String>, gc_map_allocator> JSProperties;
JSProperties mProperties;
JSMap* mPrototype;
JSObject* mPrototype;
public:
bool hasProperty(const String& name)
{
return (mProperties.count(name) != 0);
}
const JSValue& getProperty(const String& name)
{
#ifdef XP_MAC
@ -152,53 +155,33 @@ namespace JSTypes {
return (mProperties[name] = value);
}
void setPrototype(JSMap* prototype)
void setPrototype(JSObject* prototype)
{
mPrototype = prototype;
}
JSMap* getPrototype()
JSObject* getPrototype()
{
return mPrototype;
}
};
/**
* Private representation of a JS function. This simply
* holds a reference to the iCode module that is the
* compiled code of the function.
*/
class JSFunction : public JSMap {
class JSFunction : public JSObject {
ICodeModule* mICode;
public:
JSFunction(ICodeModule* iCode) : mICode(iCode) {}
ICodeModule* getICode() { return mICode; }
};
/**
* Private representation of a JavaScript object.
* This will change over time, so it is treated as an opaque
* type everywhere else but here.
*/
class JSObject : public JSMap {
public:
JSValue& defineProperty(const String& name, const JSValue& value)
{
return (mProperties[name] = value);
}
// FIXME: need to copy the ICodeModule's instruction stream.
JSValue& defineFunction(const String& name, ICodeModule* iCode)
{
JSValue value(new JSFunction(iCode));
return defineProperty(name, value);
}
};
/**
* Private representation of a JavaScript array.
*/
class JSArray : public JSMap {
class JSArray : public JSObject {
JSValues elements;
public:
JSArray() : elements(1) {}
@ -248,7 +231,46 @@ namespace JSTypes {
JSException(JSValue v) : value(v) { }
JSValue value;
};
/**
* Provides a set of nested scopes.
*/
class JSNamespace : private JSObject {
protected:
JSNamespace* mParent;
public:
bool isDefined(const String& name)
{
if (hasProperty(name))
return true;
if (mParent)
return mParent->isDefined(name);
return false;
}
const JSValue& getVariable(const String& name)
{
return getProperty(name);
}
JSValue& setVariable(const String& name, const JSValue& value)
{
return setProperty(name, value);
}
JSValue& defineVariable(const String& name, const JSValue& value)
{
return setProperty(name, value);
}
// FIXME: need to copy the ICodeModule's instruction stream.
JSValue& defineFunction(const String& name, ICodeModule* iCode)
{
JSValue value(new JSFunction(iCode));
return defineVariable(name, value);
}
};
} /* namespace JSTypes */
} /* namespace JavaScript */

View File

@ -210,13 +210,13 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
case LOAD_NAME:
{
LoadName* ln = static_cast<LoadName*>(instruction);
(*registers)[dst(ln)] = mGlobal->getProperty(*src1(ln));
(*registers)[dst(ln)] = mGlobal->getVariable(*src1(ln));
}
break;
case SAVE_NAME:
{
SaveName* sn = static_cast<SaveName*>(instruction);
mGlobal->setProperty(*dst(sn), (*registers)[src1(sn)]);
mGlobal->setVariable(*dst(sn), (*registers)[src1(sn)]);
}
break;
case NEW_OBJECT:

View File

@ -35,16 +35,16 @@ namespace Interpreter {
class Context : public gc_base {
public:
explicit Context(World& world, JSObject* aGlobal)
explicit Context(World& world, JSNamespace* aGlobal)
: mWorld(world), mGlobal(aGlobal), mLinkage(0)
{
}
JSObject* getGlobalObject() { return mGlobal; }
JSNamespace* getGlobalObject() { return mGlobal; }
JSObject* setGlobalObject(JSObject* aGlobal)
JSNamespace* setGlobalObject(JSNamespace* aGlobal)
{
JSObject* t = mGlobal;
JSNamespace* t = mGlobal;
mGlobal = aGlobal;
return t;
}
@ -72,7 +72,7 @@ namespace Interpreter {
private:
World& mWorld;
JSObject* mGlobal;
JSNamespace* mGlobal;
Linkage* mLinkage;
std::vector<Listener*> mListeners;
}; /* class Context */

View File

@ -118,17 +118,20 @@ namespace JSTypes {
extern const JSValue kUndefinedValue;
/**
* Basic behavior of all JS objects, mapping a name to a value.
* This is provided mainly to avoid having an awkward implementation
* of JSObject & JSArray, which must each define its own
* gc_allocator. This is all in flux.
* Basic behavior of all JS objects, mapping a name to a value,
* with prototype-based inheritance.
*/
class JSMap : public gc_base {
class JSObject : public gc_base {
protected:
typedef std::map<String, JSValue, std::less<String>, gc_map_allocator> JSProperties;
JSProperties mProperties;
JSMap* mPrototype;
JSObject* mPrototype;
public:
bool hasProperty(const String& name)
{
return (mProperties.count(name) != 0);
}
const JSValue& getProperty(const String& name)
{
#ifdef XP_MAC
@ -152,53 +155,33 @@ namespace JSTypes {
return (mProperties[name] = value);
}
void setPrototype(JSMap* prototype)
void setPrototype(JSObject* prototype)
{
mPrototype = prototype;
}
JSMap* getPrototype()
JSObject* getPrototype()
{
return mPrototype;
}
};
/**
* Private representation of a JS function. This simply
* holds a reference to the iCode module that is the
* compiled code of the function.
*/
class JSFunction : public JSMap {
class JSFunction : public JSObject {
ICodeModule* mICode;
public:
JSFunction(ICodeModule* iCode) : mICode(iCode) {}
ICodeModule* getICode() { return mICode; }
};
/**
* Private representation of a JavaScript object.
* This will change over time, so it is treated as an opaque
* type everywhere else but here.
*/
class JSObject : public JSMap {
public:
JSValue& defineProperty(const String& name, const JSValue& value)
{
return (mProperties[name] = value);
}
// FIXME: need to copy the ICodeModule's instruction stream.
JSValue& defineFunction(const String& name, ICodeModule* iCode)
{
JSValue value(new JSFunction(iCode));
return defineProperty(name, value);
}
};
/**
* Private representation of a JavaScript array.
*/
class JSArray : public JSMap {
class JSArray : public JSObject {
JSValues elements;
public:
JSArray() : elements(1) {}
@ -248,7 +231,46 @@ namespace JSTypes {
JSException(JSValue v) : value(v) { }
JSValue value;
};
/**
* Provides a set of nested scopes.
*/
class JSNamespace : private JSObject {
protected:
JSNamespace* mParent;
public:
bool isDefined(const String& name)
{
if (hasProperty(name))
return true;
if (mParent)
return mParent->isDefined(name);
return false;
}
const JSValue& getVariable(const String& name)
{
return getProperty(name);
}
JSValue& setVariable(const String& name, const JSValue& value)
{
return setProperty(name, value);
}
JSValue& defineVariable(const String& name, const JSValue& value)
{
return setProperty(name, value);
}
// FIXME: need to copy the ICodeModule's instruction stream.
JSValue& defineFunction(const String& name, ICodeModule* iCode)
{
JSValue value(new JSFunction(iCode));
return defineVariable(name, value);
}
};
} /* namespace JSTypes */
} /* namespace JavaScript */

View File

@ -272,7 +272,7 @@ static void testICG(World &world)
static float64 testFunctionCall(World &world, float64 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
Tracer t;
cx.addListener(&t);
@ -325,7 +325,7 @@ static float64 testFunctionCall(World &world, float64 n)
static float64 testFactorial(World &world, float64 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
// generate code for factorial, and interpret it.
uint32 position = 0;
@ -390,7 +390,7 @@ static float64 testFactorial(World &world, float64 n)
static float64 testObjects(World &world, int32 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
// create some objects, put some properties, and retrieve them.
uint32 position = 0;
@ -456,7 +456,7 @@ static float64 testObjects(World &world, int32 n)
static float64 testProto(World &world, int32 n)
{
JSObject glob;
JSNamespace glob;
Context cx(world, &glob);
Tracer t;
@ -515,8 +515,8 @@ static float64 testProto(World &world, int32 n)
cx.interpret(initCode, args);
// objects now exist, do real prototype chain manipulation.
JSObject* globalObject = glob.getProperty(global).object;
globalObject->setPrototype(glob.getProperty(proto).object);
JSObject* globalObject = glob.getVariable(global).object;
globalObject->setPrototype(glob.getVariable(proto).object);
// generate call to global.increment()
ICodeGenerator callCG;
@ -533,7 +533,7 @@ static float64 testProto(World &world, int32 n)
while (n-- > 0)
(void) cx.interpret(callCode, args);
JSValue result = glob.getProperty(global).object->getProperty(counter);
JSValue result = glob.getVariable(global).object->getProperty(counter);
stdOut << "result = " << result.f64 << "\n";