Removed FUNCTION instruction, other class related junk.

This commit is contained in:
rogerl%netscape.com 2000-06-23 22:53:09 +00:00
parent d3a41654d3
commit 89515e83dc
20 changed files with 64 additions and 192 deletions

View File

@ -1245,12 +1245,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
superclass = static_cast<JSClass*>(superclassValue.object);
}
JSClass* thisClass = new JSClass(mGlobal, nameExpr->name, superclass);
JSValue thisValue(thisClass); thisValue.tag = JSValue::object_tag;
// is it ok for a partially defined class to appear in global scope? this is needed
// to handle recursive types, such as linked list nodes.
mGlobal->defineVariable(nameExpr->name, thisValue);
mGlobal->defineVariable(nameExpr->name, JSValue(thisClass));
if (classStmt->body) {
bool hasMethods = false;
ICodeGenerator fcg(mWorld, thisClass->getScope());
StmtNode* s = classStmt->body->statements;
while (s) {
@ -1282,7 +1280,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
fcg.preprocess(s);
fcg.genStmt(s);
hasMethods = true;
}
break;
default:
@ -1290,13 +1287,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
}
s = s->next;
}
if (hasMethods) {
// run the code which defines the functions in the class's scope.
using Interpreter::Context;
Context cx(*mWorld, thisClass->getScope());
fcg.returnStmt(TypedRegister(NotARegister, &None_Type));
cx.interpret(fcg.complete(), JSValues());
}
}
}
break;
@ -1316,7 +1306,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
//stdOut << icg;
ICodeModule *icm = icg.complete();
if (f->function.name->getKind() == ExprNode::identifier)
defFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
mGlobal->defineFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
}
break;
case StmtNode::Var:
@ -1530,7 +1520,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
LabelStmtNode *l = static_cast<LabelStmtNode *>(p);
// ok, there's got to be a cleverer way of doing this...
if (currentLabelSet != NULL) {
if (currentLabelSet == NULL) {
currentLabelSet = new LabelSet();
currentLabelSet->push_back(&l->name);
genStmt(l->stmt, currentLabelSet);

View File

@ -158,9 +158,6 @@ namespace ICG {
void endWith()
{ iCode->push_back(new Without()); }
void defFunction(const StringAtom& name, ICodeModule *code)
{ iCode->push_back(new FunctionDef(name, code)); }
void resetStatement() { resetTopRegister(); }
void setRegisterForVariable(const StringAtom& name, TypedRegister r)

View File

@ -483,13 +483,6 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
assert(mPC != endPC);
Instruction* instruction = *mPC;
switch (instruction->op()) {
case FUNCTION:
{
FunctionDef* fnDef = static_cast<FunctionDef*>(instruction);
mGlobal->defineFunction(fnDef->name, fnDef->code);
}
break;
case METHOD_CALL:
{
MethodCall* call = static_cast<MethodCall*>(instruction);
@ -499,7 +492,6 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSValue prop;
if (op2(call).first == NotARegister) {
base = mGlobal->getReference(prop, *((*registers)[op3(call).first].string));
}
else {
base = (*registers)[op2(call).first];
@ -650,7 +642,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
{
GetProp* gp = static_cast<GetProp*>(instruction);
JSValue& value = (*registers)[src1(gp).first];
if (value.tag == JSValue::object_tag) {
if (value.isObject()) {
JSObject* object = value.object;
(*registers)[dst(gp).first] = object->getProperty(*src2(gp));
}
@ -661,7 +653,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
{
SetProp* sp = static_cast<SetProp*>(instruction);
JSValue& value = (*registers)[dst(sp).first];
if (value.tag == JSValue::object_tag) {
if (value.isObject()) {
JSObject* object = value.object;
object->setProperty(*src1(sp), (*registers)[src2(sp).first]);
}

View File

@ -265,7 +265,6 @@ void testCompile()
Arena a;
Parser p(world, a, testScript, widenCString("testCompile"));
StmtNode *parsedStatements = p.parseProgram();
JSScope glob;
ICodeGenerator icg(&world, &glob);
icg.isScript();
StmtNode *s = parsedStatements;

View File

@ -70,20 +70,18 @@ namespace JSClasses {
*/
class JSClass : public JSType {
protected:
String mName;
JSClass* mSuperClass;
JSScope* mScope;
uint32 mSlotCount;
std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> mSlots;
public:
JSClass(JSScope* scope, const String& name, JSClass* superClass = 0)
: JSType(superClass), mName(name), mSuperClass(superClass), mSlotCount(0)
: JSType(name, superClass), mSuperClass(superClass), mSlotCount(0)
{
mScope = new JSScope(scope);
setProperty(widenCString("methods"), JSValue(mScope));
}
const String& getName() { return mName; }
JSClass* getSuperClass() { return mSuperClass; }
JSScope* getScope() { return mScope; }

View File

@ -47,18 +47,18 @@ const JSValue kTrue = JSValue(true);
const JSValue kFalse = JSValue(false);
const JSValue kNull = JSValue((JSObject*)NULL);
const JSType Any_Type = JSType(NULL);
const JSType Integer_Type = JSType(&Any_Type);
const JSType Number_Type = JSType(&Integer_Type);
const JSType Character_Type = JSType(&Any_Type);
const JSType String_Type = JSType(&Character_Type);
const JSType Function_Type = JSType(&Any_Type);
const JSType Array_Type = JSType(&Any_Type);
const JSType Type_Type = JSType(&Any_Type);
const JSType Boolean_Type = JSType(&Any_Type);
const JSType Null_Type = JSType(&Any_Type);
const JSType Void_Type = JSType(&Any_Type);
const JSType None_Type = JSType(&Any_Type);
const JSType Any_Type = JSType(widenCString("any"), NULL);
const JSType Integer_Type = JSType(widenCString("Integer"), &Any_Type);
const JSType Number_Type = JSType(widenCString("Number"), &Integer_Type);
const JSType Character_Type = JSType(widenCString("Character"), &Any_Type);
const JSType String_Type = JSType(widenCString("String"), &Character_Type);
const JSType Function_Type = JSType(widenCString("Function"), &Any_Type);
const JSType Array_Type = JSType(widenCString("Array"), &Any_Type);
const JSType Type_Type = JSType(widenCString("Type"), &Any_Type);
const JSType Boolean_Type = JSType(widenCString("Boolean"), &Any_Type);
const JSType Null_Type = JSType(widenCString("Null"), &Any_Type);
const JSType Void_Type = JSType(widenCString("void"), &Any_Type);
const JSType None_Type = JSType(widenCString("none"), &Any_Type);
#ifdef IS_LITTLE_ENDIAN
@ -204,32 +204,7 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
f << "undefined";
break;
case JSValue::type_tag:
if (value.type == &Any_Type) // yuck (see yuck comment below)
f << "Any_Type";
else if (value.type == &Integer_Type)
f << "Integer_Type";
else if (value.type == &Number_Type)
f << "Number_Type";
else if (value.type == &Character_Type)
f << "Character_Type";
else if (value.type == &String_Type)
f << "String_Type";
else if (value.type == &Function_Type)
f << "Function_Type";
else if (value.type == &Array_Type)
f << "Array_Type";
else if (value.type == &Type_Type)
f << "Type_Type";
else if (value.type == &Boolean_Type)
f << "Boolean_Type";
else if (value.type == &Null_Type)
f << "Null_Type";
else if (value.type == &Void_Type)
f << "Void_Type";
else if (value.type == &None_Type)
f << "None_Type";
else
f << "Unknown_Type";
f << value.type->getName();
break;
default:
NOT_REACHED("Bad tag");
@ -532,9 +507,9 @@ int32 JSType::distance(const JSType *other) const
{
if (other == this)
return 0;
if (baseType == NULL)
if (mBaseType == NULL)
return NoRelation;
int32 baseDistance = baseType->distance(other);
int32 baseDistance = mBaseType->distance(other);
if (baseDistance != NoRelation)
++baseDistance;
return baseDistance;

View File

@ -120,7 +120,7 @@ namespace JSTypes {
const JSType*& operator=(const JSType* type) { return (tag = type_tag, this->type = type); }
bool isFunction() const { return (tag == function_tag); }
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag)); }
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag) || (tag == type_tag)); }
bool isString() const { return (tag == string_tag); }
bool isBoolean() const { return (tag == boolean_tag); }
bool isNumber() const { return (tag == f64_tag) || (tag == integer_tag); }
@ -440,12 +440,16 @@ namespace JSTypes {
};
class JSType : public JSObject {
protected:
String mName;
const JSType *mBaseType;
public:
JSType(const JSType *baseType) : baseType(baseType) { }
const JSType *baseType;
JSType(const String &name, const JSType *baseType) : mName(name), mBaseType(baseType) { }
enum { NoRelation = 0x7FFFFFFF };
const String& getName() const { return mName; }
int32 distance(const JSType *other) const;
};

View File

@ -276,10 +276,6 @@ $ops{"WITHOUT"} =
super => "Instruction",
rem => "without this object",
};
$ops{"FUNCTION"} =
{
rem => "Defines a function",
};
#
# nasty perl code, you probably don't need to muck around below this line

View File

@ -69,7 +69,6 @@ namespace VM {
DEBUGGER, /* drop to the debugger */
DIVIDE, /* dest, source1, source2 */
ELEM_XCR, /* dest, base, index, value */
FUNCTION, /* Defines a function */
GET_ELEMENT, /* dest, base, index */
GET_PROP, /* dest, object, prop name */
INSTANCEOF, /* dest, source1, source2 */
@ -134,7 +133,6 @@ namespace VM {
"DEBUGGER ",
"DIVIDE ",
"ELEM_XCR ",
"FUNCTION ",
"GET_ELEMENT ",
"GET_PROP ",
"INSTANCEOF ",
@ -208,23 +206,6 @@ namespace VM {
};
class FunctionDef : public Instruction
{
public:
const StringAtom &name;
ICG::ICodeModule *code;
virtual Formatter& print(Formatter& f)
{
f << opcodeNames[mOpcode] << "\t" << name;
return f;
}
FunctionDef(const StringAtom& name, ICG::ICodeModule *code)
: Instruction(FUNCTION), name(name), code(code) { }
};
/********************************************************************/
enum { NotARegister = 0xFFFFFFFF };

View File

@ -183,6 +183,10 @@ SOURCE=..\interpreter.h
# End Source File
# Begin Source File
SOURCE=..\jsclasses.h
# End Source File
# Begin Source File
SOURCE=..\JSScope.h
# End Source File
# Begin Source File

View File

@ -1245,12 +1245,10 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
superclass = static_cast<JSClass*>(superclassValue.object);
}
JSClass* thisClass = new JSClass(mGlobal, nameExpr->name, superclass);
JSValue thisValue(thisClass); thisValue.tag = JSValue::object_tag;
// is it ok for a partially defined class to appear in global scope? this is needed
// to handle recursive types, such as linked list nodes.
mGlobal->defineVariable(nameExpr->name, thisValue);
mGlobal->defineVariable(nameExpr->name, JSValue(thisClass));
if (classStmt->body) {
bool hasMethods = false;
ICodeGenerator fcg(mWorld, thisClass->getScope());
StmtNode* s = classStmt->body->statements;
while (s) {
@ -1282,7 +1280,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
fcg.preprocess(s);
fcg.genStmt(s);
hasMethods = true;
}
break;
default:
@ -1290,13 +1287,6 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
}
s = s->next;
}
if (hasMethods) {
// run the code which defines the functions in the class's scope.
using Interpreter::Context;
Context cx(*mWorld, thisClass->getScope());
fcg.returnStmt(TypedRegister(NotARegister, &None_Type));
cx.interpret(fcg.complete(), JSValues());
}
}
}
break;
@ -1316,7 +1306,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
//stdOut << icg;
ICodeModule *icm = icg.complete();
if (f->function.name->getKind() == ExprNode::identifier)
defFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
mGlobal->defineFunction((static_cast<IdentifierExprNode *>(f->function.name))->name, icm);
}
break;
case StmtNode::Var:
@ -1530,7 +1520,7 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
{
LabelStmtNode *l = static_cast<LabelStmtNode *>(p);
// ok, there's got to be a cleverer way of doing this...
if (currentLabelSet != NULL) {
if (currentLabelSet == NULL) {
currentLabelSet = new LabelSet();
currentLabelSet->push_back(&l->name);
genStmt(l->stmt, currentLabelSet);

View File

@ -158,9 +158,6 @@ namespace ICG {
void endWith()
{ iCode->push_back(new Without()); }
void defFunction(const StringAtom& name, ICodeModule *code)
{ iCode->push_back(new FunctionDef(name, code)); }
void resetStatement() { resetTopRegister(); }
void setRegisterForVariable(const StringAtom& name, TypedRegister r)

View File

@ -483,13 +483,6 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
assert(mPC != endPC);
Instruction* instruction = *mPC;
switch (instruction->op()) {
case FUNCTION:
{
FunctionDef* fnDef = static_cast<FunctionDef*>(instruction);
mGlobal->defineFunction(fnDef->name, fnDef->code);
}
break;
case METHOD_CALL:
{
MethodCall* call = static_cast<MethodCall*>(instruction);
@ -499,7 +492,6 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
JSValue prop;
if (op2(call).first == NotARegister) {
base = mGlobal->getReference(prop, *((*registers)[op3(call).first].string));
}
else {
base = (*registers)[op2(call).first];
@ -650,7 +642,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
{
GetProp* gp = static_cast<GetProp*>(instruction);
JSValue& value = (*registers)[src1(gp).first];
if (value.tag == JSValue::object_tag) {
if (value.isObject()) {
JSObject* object = value.object;
(*registers)[dst(gp).first] = object->getProperty(*src2(gp));
}
@ -661,7 +653,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
{
SetProp* sp = static_cast<SetProp*>(instruction);
JSValue& value = (*registers)[dst(sp).first];
if (value.tag == JSValue::object_tag) {
if (value.isObject()) {
JSObject* object = value.object;
object->setProperty(*src1(sp), (*registers)[src2(sp).first]);
}

View File

@ -70,20 +70,18 @@ namespace JSClasses {
*/
class JSClass : public JSType {
protected:
String mName;
JSClass* mSuperClass;
JSScope* mScope;
uint32 mSlotCount;
std::map<String, JSSlot, std::less<const String>, gc_slot_allocator> mSlots;
public:
JSClass(JSScope* scope, const String& name, JSClass* superClass = 0)
: JSType(superClass), mName(name), mSuperClass(superClass), mSlotCount(0)
: JSType(name, superClass), mSuperClass(superClass), mSlotCount(0)
{
mScope = new JSScope(scope);
setProperty(widenCString("methods"), JSValue(mScope));
}
const String& getName() { return mName; }
JSClass* getSuperClass() { return mSuperClass; }
JSScope* getScope() { return mScope; }

View File

@ -47,18 +47,18 @@ const JSValue kTrue = JSValue(true);
const JSValue kFalse = JSValue(false);
const JSValue kNull = JSValue((JSObject*)NULL);
const JSType Any_Type = JSType(NULL);
const JSType Integer_Type = JSType(&Any_Type);
const JSType Number_Type = JSType(&Integer_Type);
const JSType Character_Type = JSType(&Any_Type);
const JSType String_Type = JSType(&Character_Type);
const JSType Function_Type = JSType(&Any_Type);
const JSType Array_Type = JSType(&Any_Type);
const JSType Type_Type = JSType(&Any_Type);
const JSType Boolean_Type = JSType(&Any_Type);
const JSType Null_Type = JSType(&Any_Type);
const JSType Void_Type = JSType(&Any_Type);
const JSType None_Type = JSType(&Any_Type);
const JSType Any_Type = JSType(widenCString("any"), NULL);
const JSType Integer_Type = JSType(widenCString("Integer"), &Any_Type);
const JSType Number_Type = JSType(widenCString("Number"), &Integer_Type);
const JSType Character_Type = JSType(widenCString("Character"), &Any_Type);
const JSType String_Type = JSType(widenCString("String"), &Character_Type);
const JSType Function_Type = JSType(widenCString("Function"), &Any_Type);
const JSType Array_Type = JSType(widenCString("Array"), &Any_Type);
const JSType Type_Type = JSType(widenCString("Type"), &Any_Type);
const JSType Boolean_Type = JSType(widenCString("Boolean"), &Any_Type);
const JSType Null_Type = JSType(widenCString("Null"), &Any_Type);
const JSType Void_Type = JSType(widenCString("void"), &Any_Type);
const JSType None_Type = JSType(widenCString("none"), &Any_Type);
#ifdef IS_LITTLE_ENDIAN
@ -204,32 +204,7 @@ Formatter& operator<<(Formatter& f, const JSValue& value)
f << "undefined";
break;
case JSValue::type_tag:
if (value.type == &Any_Type) // yuck (see yuck comment below)
f << "Any_Type";
else if (value.type == &Integer_Type)
f << "Integer_Type";
else if (value.type == &Number_Type)
f << "Number_Type";
else if (value.type == &Character_Type)
f << "Character_Type";
else if (value.type == &String_Type)
f << "String_Type";
else if (value.type == &Function_Type)
f << "Function_Type";
else if (value.type == &Array_Type)
f << "Array_Type";
else if (value.type == &Type_Type)
f << "Type_Type";
else if (value.type == &Boolean_Type)
f << "Boolean_Type";
else if (value.type == &Null_Type)
f << "Null_Type";
else if (value.type == &Void_Type)
f << "Void_Type";
else if (value.type == &None_Type)
f << "None_Type";
else
f << "Unknown_Type";
f << value.type->getName();
break;
default:
NOT_REACHED("Bad tag");
@ -532,9 +507,9 @@ int32 JSType::distance(const JSType *other) const
{
if (other == this)
return 0;
if (baseType == NULL)
if (mBaseType == NULL)
return NoRelation;
int32 baseDistance = baseType->distance(other);
int32 baseDistance = mBaseType->distance(other);
if (baseDistance != NoRelation)
++baseDistance;
return baseDistance;

View File

@ -120,7 +120,7 @@ namespace JSTypes {
const JSType*& operator=(const JSType* type) { return (tag = type_tag, this->type = type); }
bool isFunction() const { return (tag == function_tag); }
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag)); }
bool isObject() const { return ((tag == object_tag) || (tag == function_tag) || (tag == array_tag) || (tag == type_tag)); }
bool isString() const { return (tag == string_tag); }
bool isBoolean() const { return (tag == boolean_tag); }
bool isNumber() const { return (tag == f64_tag) || (tag == integer_tag); }
@ -440,12 +440,16 @@ namespace JSTypes {
};
class JSType : public JSObject {
protected:
String mName;
const JSType *mBaseType;
public:
JSType(const JSType *baseType) : baseType(baseType) { }
const JSType *baseType;
JSType(const String &name, const JSType *baseType) : mName(name), mBaseType(baseType) { }
enum { NoRelation = 0x7FFFFFFF };
const String& getName() const { return mName; }
int32 distance(const JSType *other) const;
};

View File

@ -69,7 +69,6 @@ namespace VM {
DEBUGGER, /* drop to the debugger */
DIVIDE, /* dest, source1, source2 */
ELEM_XCR, /* dest, base, index, value */
FUNCTION, /* Defines a function */
GET_ELEMENT, /* dest, base, index */
GET_PROP, /* dest, object, prop name */
INSTANCEOF, /* dest, source1, source2 */
@ -134,7 +133,6 @@ namespace VM {
"DEBUGGER ",
"DIVIDE ",
"ELEM_XCR ",
"FUNCTION ",
"GET_ELEMENT ",
"GET_PROP ",
"INSTANCEOF ",
@ -208,23 +206,6 @@ namespace VM {
};
class FunctionDef : public Instruction
{
public:
const StringAtom &name;
ICG::ICodeModule *code;
virtual Formatter& print(Formatter& f)
{
f << opcodeNames[mOpcode] << "\t" << name;
return f;
}
FunctionDef(const StringAtom& name, ICG::ICodeModule *code)
: Instruction(FUNCTION), name(name), code(code) { }
};
/********************************************************************/
enum { NotARegister = 0xFFFFFFFF };

View File

@ -183,6 +183,10 @@ SOURCE=..\interpreter.h
# End Source File
# Begin Source File
SOURCE=..\jsclasses.h
# End Source File
# Begin Source File
SOURCE=..\JSScope.h
# End Source File
# Begin Source File

View File

@ -265,7 +265,6 @@ void testCompile()
Arena a;
Parser p(world, a, testScript, widenCString("testCompile"));
StmtNode *parsedStatements = p.parseProgram();
JSScope glob;
ICodeGenerator icg(&world, &glob);
icg.isScript();
StmtNode *s = parsedStatements;

View File

@ -276,10 +276,6 @@ $ops{"WITHOUT"} =
super => "Instruction",
rem => "without this object",
};
$ops{"FUNCTION"} =
{
rem => "Defines a function",
};
#
# nasty perl code, you probably don't need to muck around below this line