Added boolean class, fixing bugs.

This commit is contained in:
rogerl%netscape.com 2003-01-03 00:49:29 +00:00
Родитель 26e1214c77
Коммит c668cc5500
5 изменённых файлов: 173 добавлений и 12 удалений

122
js2/src/js2boolean.cpp Normal file
Просмотреть файл

@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is the JavaScript 2 Prototype.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
* provisions of the GPL are applicable instead of those above.
* If you wish to allow use of your version of this file only
* under the terms of the GPL and not to allow others to use your
* version of this file under the NPL, indicate your decision by
* deleting the provisions above and replace them with the notice
* and other provisions required by the GPL. If you do not delete
* the provisions above, a recipient may use your version of this
* file under either the NPL or the GPL.
*/
#ifdef _WIN32
#include "msvc_pragma.h"
#endif
#include <algorithm>
#include <list>
#include <map>
#include <stack>
#include "world.h"
#include "utilities.h"
#include "js2value.h"
#include "numerics.h"
#include "reader.h"
#include "parser.h"
#include "regexp.h"
#include "js2engine.h"
#include "bytecodecontainer.h"
#include "js2metadata.h"
namespace JavaScript {
namespace MetaData {
static js2val Boolean_Constructor(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc)
{
js2val thatValue = OBJECT_TO_JS2VAL(new BooleanInstance(meta->booleanClass));
BooleanInstance *boolInst = checked_cast<BooleanInstance *>(JS2VAL_TO_OBJECT(thatValue));
if (argc > 0)
boolInst->mValue = meta->toBoolean(argv[0]);
else
boolInst->mValue = false;
return thatValue;
}
static js2val Boolean_toString(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
{
if (meta->objectType(thisValue) != meta->booleanClass)
meta->reportError(Exception::typeError, "Boolean.toString called on something other than a boolean thing", meta->engine->errorPos());
BooleanInstance *boolInst = checked_cast<BooleanInstance *>(JS2VAL_TO_OBJECT(thisValue));
return (boolInst->mValue) ? meta->engine->allocString(meta->engine->true_StringAtom) : meta->engine->allocString(meta->engine->false_StringAtom);
}
void initBooleanObject(JS2Metadata *meta)
{
meta->booleanClass->construct = Boolean_Constructor;
typedef struct {
char *name;
uint16 length;
NativeCode *code;
} PrototypeFunction;
PrototypeFunction prototypeFunctions[] =
{
{ "toString", 0, Boolean_toString },
// { "valueOf", 0, Boolean_valueOf },
{ NULL }
};
NamespaceList publicNamespaceList;
publicNamespaceList.push_back(meta->publicNamespace);
PrototypeFunction *pf = &prototypeFunctions[0];
while (pf->name) {
CallableInstance *fInst = new CallableInstance(meta->functionClass);
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
/*
XXX not prototype object function properties, like ECMA3, but members of the Date class
meta->writeDynamicProperty(meta->dateClass->prototype, new Multiname(meta->world.identifiers[pf->name], meta->publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase);
*/
/*
XXX not static members, since those can't be accessed from the instance
Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(fInst), true);
meta->defineStaticMember(&meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
*/
InstanceMember *m = new InstanceMethod(fInst);
meta->defineInstanceMember(meta->booleanClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
pf++;
}
}
}
}

Просмотреть файл

@ -110,6 +110,11 @@ namespace MetaData {
}
catch (Exception &jsx) {
if (mTryStack.size() > 0) {
// The handler for this exception is on the top of the try stack.
// It specifies the activation that was active when the try block
// was entered. We unwind the activation stack, looking for the
// one that matches the handler's. The bytecode container, pc and
// sp are all reset appropriately, and execution continues.
HandlerData *hndlr = (HandlerData *)mTryStack.top();
ActivationFrame *curAct = (activationStackEmpty()) ? NULL : (activationStackTop - 1);
@ -122,6 +127,10 @@ namespace MetaData {
if (prev->pc == NULL) {
// Yikes! the exception is getting thrown across a re-invocation
// of the interpreter loop.
// (pc == NULL) is the flag on an activation to indicate that the
// interpreter loop was re-invoked (probably a 'load' or 'eval' is
// in process). In this case we simply re-throw the exception and let
// the prior invocation deal with it.
throw jsx;
}
curAct = --activationStackTop;

Просмотреть файл

@ -68,6 +68,7 @@ namespace MetaData {
Arena a;
Pragma::Flags flags = Pragma::es4;
Parser p(world, a, flags, str, fileName);
CompilationData *oldData = NULL;
try {
StmtNode *parsedStatements = p.parseProgram();
ASSERT(p.lexer.peek(true).hasKind(Token::end));
@ -84,16 +85,18 @@ namespace MetaData {
stdOut << '\n';
}
if (parsedStatements) {
CompilationData *oldData = startCompilationUnit(NULL, str, fileName);
oldData = startCompilationUnit(NULL, str, fileName);
ValidateStmtList(parsedStatements);
result = ExecuteStmtList(RunPhase, parsedStatements);
restoreCompilationUnit(oldData);
}
}
catch (Exception &x) {
// ASSERT(false);
if (oldData)
restoreCompilationUnit(oldData);
throw x;
}
if (oldData)
restoreCompilationUnit(oldData);
return result;
}
@ -2973,6 +2976,14 @@ doUnary:
return BOOLEAN_TO_JS2VAL(JSDOUBLE_IS_NaN(d));
}
static js2val GlobalObject_eval(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc)
{
if (!JS2VAL_IS_STRING(argv[0]))
return argv[0];
return meta->readEvalString(*meta->toString(argv[0]), widenCString("Eval Source"));
}
// XXX need length value
void JS2Metadata::addGlobalObjectFunction(char *name, NativeCode *code)
{
CallableInstance *fInst = new CallableInstance(functionClass);
@ -3015,7 +3026,7 @@ doUnary:
// A 'forbidden' member, used to mark hidden bindings
forbiddenMember = new StaticMember(Member::Forbidden);
forbiddenMember = new StaticMember(Member::Forbidden, true);
// needed for class instance variables etc...
NamespaceList publicNamespaceList;
@ -3041,6 +3052,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
writeDynamicProperty(glob, new Multiname(&world.identifiers["Infinity"], publicNamespace), true, engine->posInfValue, RunPhase);
// Function properties of the global object
addGlobalObjectFunction("isNaN", GlobalObject_isNaN);
addGlobalObjectFunction("eval", GlobalObject_eval);
/*** ECMA 3 Object Class ***/
@ -3075,6 +3087,11 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
defineStaticMember(env, &world.identifiers["Number"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
initNumberObject(this);
/*** ECMA 3 Boolean Class ***/
v = new Variable(classClass, OBJECT_TO_JS2VAL(booleanClass), true);
defineStaticMember(env, &world.identifiers["Boolean"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
initBooleanObject(this);
/*** ECMA 3 Math Class ***/
MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, &world.identifiers["Math"]);
v = new Variable(classClass, OBJECT_TO_JS2VAL(mathClass), true);
@ -4198,6 +4215,7 @@ deleteClassProperty:
bConList.pop_back();
bCon = oldData->bCon;
engine->bCon = bCon;
delete oldData;
}
@ -4345,7 +4363,7 @@ deleteClassProperty:
// call(NULL),
// construct(NULL),
// env(NULL),
typeofString(type->getName()),
// typeofString(type->getName()),
slots(new Slot[type->slotCount]),
dynamicProperties(type->dynamic ? new DynamicPropertyMap() : NULL)
{
@ -4390,7 +4408,7 @@ deleteClassProperty:
SimpleInstance::SimpleInstance(JS2Class *type)
: JS2Object(SimpleInstanceKind),
type(type),
typeofString(type->getName()),
// typeofString(type->getName()),
slots(new Slot[type->slotCount]),
dynamicProperties(type->dynamic ? new DynamicPropertyMap() : NULL)
{

Просмотреть файл

@ -65,6 +65,7 @@ extern void initArrayObject(JS2Metadata *meta);
extern void initRegExpObject(JS2Metadata *meta);
extern void initNumberObject(JS2Metadata *meta);
extern void initErrorObject(JS2Metadata *meta);
extern void initBooleanObject(JS2Metadata *meta);
extern js2val Error_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
extern js2val EvalError_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
@ -281,7 +282,8 @@ public:
// A static member is either forbidden, a variable, a hoisted variable, a constructor method, or an accessor:
class StaticMember : public Member {
public:
StaticMember(MemberKind kind) : Member(kind) { }
StaticMember(MemberKind kind) : Member(kind), forbidden(false) { }
StaticMember(MemberKind kind, bool forbidden) : Member(kind), forbidden(forbidden) { }
StaticMember *cloneContent; // Used during cloning operation to prevent cloning of duplicates (i.e. once
// a clone exists for this member it's recorded here and used for any other
@ -289,7 +291,8 @@ public:
// Also used thereafter by 'assignArguments' to initialize the singular
// variable instantations in a parameter frame.
virtual StaticMember *clone() { ASSERT(false); return NULL; }
virtual StaticMember *clone() { if (forbidden) return this; ASSERT(false); return NULL; }
bool forbidden;
};
#define FUTURE_TYPE ((JS2Class *)(-1))
@ -533,7 +536,7 @@ public:
SimpleInstance(JS2Class *type);
JS2Class *type; // This instance's type
const String *typeofString; // A string to return if typeof is invoked on this instance
// const String *typeofString; // A string to return if typeof is invoked on this instance
Slot *slots; // A set of slots that hold this instance's fixed property values
DynamicPropertyMap *dynamicProperties; // A set of this instance's dynamic properties, or NULL if this is a fixed instance
@ -553,7 +556,7 @@ public:
// Environment *env; // The environment to pass to the call or construct procedure
FunctionWrapper *fWrap;
const String *typeofString; // A string to return if typeof is invoked on this instance
// const String *typeofString; // A string to return if typeof is invoked on this instance
Slot *slots; // A set of slots that hold this instance's fixed property values
DynamicPropertyMap *dynamicProperties; // A set of this instance's dynamic properties, or NULL if this is a fixed instance
virtual void markChildren();
@ -609,6 +612,15 @@ public:
float64 mValue;
};
// Boolean instances are Callable instances created by the Boolean class, they have an extra field
// that contains the bool data
class BooleanInstance : public CallableInstance {
public:
BooleanInstance(JS2Class *type) : CallableInstance(type), mValue(false) { }
bool mValue;
};
// Array instances are Callable instances created by the Array class, they
// maintain the value of the 'length' property when 'indexable' elements
// are added.

Просмотреть файл

@ -252,10 +252,10 @@
a = STRING_TO_JS2VAL(object_StringAtom);
break;
case SimpleInstanceKind:
a = STRING_TO_JS2VAL(checked_cast<SimpleInstance *>(obj)->typeofString);
a = STRING_TO_JS2VAL(checked_cast<SimpleInstance *>(obj)->type->getName());
break;
case CallableInstanceKind:
a = STRING_TO_JS2VAL(checked_cast<CallableInstance *>(obj)->typeofString);
a = STRING_TO_JS2VAL(checked_cast<CallableInstance *>(obj)->type->getName());
break;
}
}