This commit is contained in:
rogerl%netscape.com 2002-06-28 23:43:16 +00:00
Родитель fc4c589320
Коммит 34022f34de
11 изменённых файлов: 824 добавлений и 34 удалений

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

@ -17,7 +17,6 @@
// Copyright (C) 1998 Netscape Communications Corporation. All
// Rights Reserved.
//
// JS2 shell.
//
@ -32,12 +31,12 @@
#include <algorithm>
#include <assert.h>
#include "js2metadata.h"
#include "world.h"
#include "reader.h"
#include "parser.h"
#include "js2metadata.h"
#ifdef DEBUG
#include "tracer.h"
#include "collector.h"
@ -69,13 +68,9 @@ static void initConsole(StringPtr consoleName,
#endif
using namespace JavaScript::JS2Runtime;
JavaScript::World world;
JavaScript::Arena a;
namespace JavaScript {
namespace Shell {
@ -102,6 +97,9 @@ const bool showTokens = false;
#define INTERPRET_INPUT 1
//#define SHOW_ICODE 1
MetaData::GlobalObject glob(world);
MetaData::Environment env(new MetaData::SystemFrame(), &glob);
MetaData::JS2Metadata metadata(world);
static int readEvalPrint(FILE *in)
@ -140,6 +138,14 @@ static int readEvalPrint(FILE *in)
f.end();
stdOut << '\n';
}
metadata.setCurrentParser(&p);
MetaData::Context cxt;
cxt.strict = true;
metadata.ValidateStmtList(&cxt, &env, parsedStatements);
metadata.EvalStmtList(&env, MetaData::JS2Metadata::RunPhase, parsedStatements);
}
clear(buffer);
} catch (Exception &e) {

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

@ -52,6 +52,8 @@ static const char *const kindStrings[] = {
"Uncaught exception error", // uncaught exception error
"Semantic error", // semantic error
"User exception", // 'throw' from user code
"Definition error", // a monkey is a small cup of milk
"Bad Value error", // bad value, no biscuit
};
// Return a null-terminated string describing the exception's kind.

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

@ -56,7 +56,9 @@ namespace JavaScript
typeError,
uncaughtError,
semanticError,
userException
userException,
definitionError,
badValueError
};
Kind kind; // The exception's kind

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

@ -182,7 +182,9 @@ namespace JavaScript {
GenericHashEntry **bp = ht.buckets + h;
Entry *e;
while ((e = static_cast<Entry *>(*bp)) != 0 && !(e->keyHash == kh && e->data == key))
while ((e = static_cast<Entry *>(*bp)) != 0
&& !(e->keyHash == kh
&& e->data == key))
bp = &e->next;
entry = e;
backpointer = bp;

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

@ -0,0 +1,101 @@
/* -*- 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
// Turn off warnings about identifiers too long in browser information
#pragma warning(disable: 4786)
#pragma warning(disable: 4711)
#pragma warning(disable: 4710)
#endif
#include "js2metadata.h"
#include "jsstddef.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jstypes.h"
#include "jsarena.h"
#include "jsutil.h"
#include "jsprf.h"
#include "jsapi.h"
#include "jsatom.h"
#include "jscntxt.h"
#include "jsdbgapi.h"
#include "jsemit.h"
#include "jsfun.h"
#include "jsgc.h"
#include "jslock.h"
#include "jsobj.h"
#include "jsparse.h"
#include "jsscope.h"
#include "jsscript.h"
namespace JavaScript {
namespace MetaData {
JSRuntime *gJavaScriptRuntime;
JSContext *gJavaScriptContext;
JSObject *gJavaScriptGlobalObject;
JSClass gJavaScriptGlobalClass = { "MyClass", 0, JS_PropertyStub, JS_PropertyStub,
JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub,
JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub };
void JS2Metadata::initializeMonkey( )
{
gJavaScriptRuntime = JS_NewRuntime( 1000000L );
if (gJavaScriptRuntime) {
gJavaScriptContext = JS_NewContext( gJavaScriptRuntime, 8192 );
if (gJavaScriptContext) {
gJavaScriptGlobalObject = JS_NewObject(gJavaScriptContext, &gJavaScriptGlobalClass, NULL, NULL);
if (gJavaScriptGlobalObject)
JS_SetGlobalObject(gJavaScriptContext, gJavaScriptGlobalObject);
}
}
}
jsval JS2Metadata::execute(String *str)
{
jsval retval;
JS_EvaluateUCScript(gJavaScriptContext, gJavaScriptGlobalObject, str->c_str(), str->length(), "file", 1, &retval);
return retval;
}
}; // namespace MetaData
}; // namespace Javascript

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

@ -0,0 +1,426 @@
/* -*- 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
// Turn off warnings about identifiers too long in browser information
#pragma warning(disable: 4786)
#pragma warning(disable: 4711)
#pragma warning(disable: 4710)
#endif
#include <algorithm>
#include "js2metadata.h"
namespace JavaScript {
namespace MetaData {
/*
* Validate the linked list of statement nodes beginning at 'p'
*/
void JS2Metadata::ValidateStmtList(Context *cxt, Environment *env, StmtNode *p) {
while (p) {
ValidateStmt(cxt, env, p);
p = p->next;
}
}
/*
* Validate an individual statement 'p', including it's children
*/
void JS2Metadata::ValidateStmt(Context *cxt, Environment *env, StmtNode *p) {
switch (p->getKind()) {
case StmtNode::block:
case StmtNode::group:
{
BlockStmtNode *b = checked_cast<BlockStmtNode *>(p);
ValidateStmtList(cxt, env, b->statements);
}
break;
case StmtNode::label:
{
LabelStmtNode *l = checked_cast<LabelStmtNode *>(p);
ValidateStmt(cxt, env, l->stmt);
}
break;
case StmtNode::Var:
case StmtNode::Const:
{
VariableStmtNode *vs = checked_cast<VariableStmtNode *>(p);
ValidateExpression(cxt, env, vs->attributes);
EvalAttributeExpression(env, CompilePhase, vs->attributes);
VariableBinding *v = vs->bindings;
Frame *regionalFrame = env->getRegionalFrame();
while (v) {
ValidateTypeExpression(v->type);
if (cxt->strict && ((regionalFrame->kind == Frame::GlobalObject)
|| (regionalFrame->kind == Frame::Function))
&& (p->getKind() == StmtNode::Var) // !immutable
&& (vs->attributes == NULL)
&& (v->type == NULL)) {
defineHoistedVar(env, *v->name, p);
}
else {
}
v = v->next;
}
}
break;
case StmtNode::expression:
{
ExprStmtNode *e = checked_cast<ExprStmtNode *>(p);
ValidateExpression(cxt, env, e->expr);
}
break;
} // switch (p->getKind())
}
void JS2Metadata::ValidateExpression(Context *cxt, Environment *env, ExprNode *p)
{
switch (p->getKind()) {
case ExprNode::juxtapose:
break;
} // switch (p->getKind())
}
// Evaluate the attribute expression rooted at p.
// An attribute expression can only be a list of 'juxtaposed' attribute elements
Attribute *JS2Metadata::EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p)
{
switch (p->getKind()) {
case ExprNode::boolean:
if (checked_cast<BooleanExprNode *>(p)->value)
return new TrueAttribute();
else
return new FalseAttribute();
case ExprNode::juxtapose:
{
BinaryExprNode *j = checked_cast<BinaryExprNode *>(p);
Attribute *a = EvalAttributeExpression(env, phase, j->op1);
if (a && (a->kind == FalseKind))
return a;
Attribute *b = EvalAttributeExpression(env, phase, j->op2);
try {
return Attribute::combineAttributes(a, b);
}
catch (char *err) {
reportError(Exception::badValueError, err, p->pos);
}
}
break;
default:
{
// anything else (just references of one kind or another) must
// be compile-time constant values that resolve to namespaces
jsval av = EvalExpression(env, CompilePhase, p);
if (!JSVAL_IS_OBJECT(av))
reportError(Exception::badValueError, "Namespace expected in attribute", p->pos);
}
break;
} // switch (p->getKind())
return NULL;
}
// a is not false
Attribute *Attribute::combineAttributes(Attribute *a, Attribute *b)
{
if (b && (b->kind == FalseKind)) {
if (a) delete a;
return b;
}
if (!a || (a->kind == TrueKind)) {
if (a) delete a;
return b;
}
if (!b || (b->kind == TrueKind)) {
if (b) delete b;
return a;
}
if (a->kind == NamespaceKind) {
if (a == b) {
delete b;
return a;
}
Namespace *na = checked_cast<Namespace *>(a);
if (b->kind == NamespaceKind) {
Namespace *nb = checked_cast<Namespace *>(b);
CompoundAttribute *c = new CompoundAttribute();
c->addNamespace(na);
c->addNamespace(nb);
delete a;
delete b;
return (Attribute *)c;
}
else {
ASSERT(b->kind == CompoundKind);
CompoundAttribute *cb = checked_cast<CompoundAttribute *>(b);
cb->addNamespace(na);
delete a;
return b;
}
}
else {
// Both a and b are compound attributes. Ensure that they have no conflicting contents.
ASSERT((a->kind == CompoundKind) && (b->kind == CompoundKind));
CompoundAttribute *ca = checked_cast<CompoundAttribute *>(a);
CompoundAttribute *cb = checked_cast<CompoundAttribute *>(b);
if ((ca->memberMod != NoModifier) && (cb->memberMod != NoModifier) && (ca->memberMod != cb->memberMod))
throw("Illegal combination of member modifier attributes");
if ((ca->overrideMod != NoOverride) && (cb->overrideMod != NoOverride) && (ca->overrideMod != cb->overrideMod))
throw("Illegal combination of override attributes");
for (NamespaceListIterator i = cb->namespaces->begin(), end = cb->namespaces->end(); (i != end); i++)
ca->addNamespace(*i);
ca->xplicit |= cb->xplicit;
ca->dynamic |= cb->dynamic;
if (ca->memberMod == NoModifier)
ca->memberMod = cb->memberMod;
if (ca->overrideMod == NoModifier)
ca->overrideMod = cb->overrideMod;
ca->prototype |= cb->prototype;
ca->unused |= cb->unused;
delete b;
return a;
}
}
// add the namespace to our list, but only if it's not there already
void CompoundAttribute::addNamespace(Namespace *n)
{
for (NamespaceListIterator i = namespaces->begin(), end = namespaces->end(); (i != end); i++)
if (*i == n)
return;
namespaces->push_back(n);
}
jsval JS2Metadata::EvalStmt(Environment *env, Phase phase, StmtNode *p)
{
jsval retval = JSVAL_VOID;
switch (p->getKind()) {
case StmtNode::block:
case StmtNode::group:
{
BlockStmtNode *b = checked_cast<BlockStmtNode *>(p);
retval = EvalStmtList(env, phase, b->statements);
}
break;
case StmtNode::label:
{
LabelStmtNode *l = checked_cast<LabelStmtNode *>(p);
retval = EvalStmt(env, phase, l->stmt);
}
break;
case StmtNode::Var:
case StmtNode::Const:
{
VariableStmtNode *vs = checked_cast<VariableStmtNode *>(p);
VariableBinding *v = vs->bindings;
while (v) {
v = v->next;
}
}
break;
case StmtNode::expression:
{
ExprStmtNode *e = checked_cast<ExprStmtNode *>(p);
retval = EvalExpression(env, phase, e->expr);
}
break;
default:
NOT_REACHED("Not Yet Implemented");
} // switch (p->getKind())
return retval;
}
// Evaluate the expression rooted at p.
jsval JS2Metadata::EvalExpression(Environment *env, Phase phase, ExprNode *p)
{
String str;
switch (p->getKind()) {
case ExprNode::boolean:
if (checked_cast<BooleanExprNode *>(p)->value)
str += "true" ;
else
str += "false";
break;
}
return execute(&str);
}
/*
* Evaluate the linked list of statement nodes beginning at 'p'
*/
jsval JS2Metadata::EvalStmtList(Environment *env, Phase phase, StmtNode *p) {
jsval retval = JSVAL_VOID;
while (p) {
retval = EvalStmt(env, phase, p);
p = p->next;
}
return retval;
}
void JS2Metadata::ValidateTypeExpression(ExprNode *e)
{
}
// returns the most specific regional frame.
Frame *Environment::getRegionalFrame()
{
Frame *pf = firstFrame;
Frame *prev = NULL;
while (pf->kind == Frame::Block) {
prev = pf;
pf = pf->nextFrame;
}
if (pf->nextFrame && (pf->kind == Frame::Class))
pf = prev;
return pf;
}
// Define a hoisted var in the current frame (either Global or a Function)
void JS2Metadata::defineHoistedVar(Environment *env, const StringAtom &id, StmtNode *p)
{
QualifiedName qName(&publicNamespace, id);
Frame *regionalFrame = env->getRegionalFrame();
ASSERT((env->getTopFrame()->kind == Frame::GlobalObject) || (env->getTopFrame()->kind == Frame::Function));
// run through all the existing bindings, both read and write, to see if this
// variable already exists.
StaticBindingIterator b, end;
bool existing = false;
for (b = regionalFrame->staticReadBindings.lower_bound(id),
end = regionalFrame->staticReadBindings.upper_bound(id); (b != end); b++) {
if (b->second->qname == qName) {
if (b->second->content->kind != StaticMember::HoistedVariable)
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
else {
existing = true;
break;
}
}
}
for (b = regionalFrame->staticWriteBindings.lower_bound(id),
end = regionalFrame->staticWriteBindings.upper_bound(id); (b != end); b++) {
if (b->second->qname == qName) {
if (b->second->content->kind != StaticMember::HoistedVariable)
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
else {
existing = true;
break;
}
}
}
if (!existing) {
if (regionalFrame->kind == Frame::GlobalObject) {
GlobalObject *gObj = checked_cast<GlobalObject *>(regionalFrame);
DynamicPropertyIterator dp = gObj->dynamicProperties.find(id);
if (dp != gObj->dynamicProperties.end())
reportError(Exception::definitionError, "Duplicate definition {0}", p->pos, id);
}
// XXX ok to use same binding in read & write maps?
StaticBinding *sb = new StaticBinding(qName, new HoistedVar());
const StaticBindingMap::value_type e(id, sb);
// XXX ok to use same value_type in different multimaps?
regionalFrame->staticReadBindings.insert(e);
regionalFrame->staticWriteBindings.insert(e);
}
//else A hoisted binding of the same var already exists, so there is no need to create another one
}
JS2Metadata::JS2Metadata(World &world) :
publicNamespace(world.identifiers["public"])
{
initializeMonkey();
}
/*
* Throw an exception of the specified kind, indicating the position 'pos' and
* attaching the given message. If 'arg' is specified, replace {0} in the message
* with the argument value. [This is intended to be widened into a more complete
* argument handling scheme].
*/
void JS2Metadata::reportError(Exception::Kind kind, char *message, size_t pos, const char *arg)
{
const char16 *lineBegin;
const char16 *lineEnd;
String x = widenCString(message);
if (arg) {
// XXX handle multiple occurences and extend to {1} etc.
uint32 a = x.find(widenCString("{0}"));
x.replace(a, 3, widenCString(arg));
}
uint32 lineNum = mParser->lexer.reader.posToLineNum(pos);
size_t linePos = mParser->lexer.reader.getLine(lineNum, lineBegin, lineEnd);
ASSERT(lineBegin && lineEnd && linePos <= pos);
throw Exception(kind, x, mParser->lexer.reader.sourceLocation,
lineNum, pos - linePos, pos, lineBegin, lineEnd);
}
inline char narrow(char16 ch) { return char(ch); }
void JS2Metadata::reportError(Exception::Kind kind, char *message, size_t pos, const String& name)
{
std::string str(name.length(), char());
std::transform(name.begin(), name.end(), str.begin(), narrow);
reportError(kind, message, pos, str.c_str());
}
CompoundAttribute::CompoundAttribute() : Attribute(CompoundKind),
namespaces(NULL), xplicit(false), dynamic(false),
memberMod(NoModifier), overrideMod(NoOverride), prototype(false),
unused(false)
{
}
}; // namespace MetaData
}; // namespace Javascript

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

@ -32,10 +32,13 @@
* file under either the NPL or the GPL.
*/
#include "jsapi.h"
#include "world.h"
#include "utilities.h"
#include "parser.h"
#include <map>
namespace JavaScript {
namespace MetaData {
@ -43,7 +46,10 @@ namespace MetaData {
// forward definitions:
class JS2Class;
typedef uint32 js2val;
class StaticBinding;
class Environment;
class Context;
typedef jsval js2val;
typedef void (Invokable)();
typedef Invokable Callor;
@ -56,16 +62,39 @@ class JS2Object {
public:
};
class Namespace {
class Attribute {
public:
enum AttributeKind { TrueKind, FalseKind, NamespaceKind, CompoundKind } kind;
enum MemberModifier { NoModifier, Static, Constructor, Operator, Abstract, Virtual, Final};
enum OverrideModifier { NoOverride, DoOverride, DontOverride, OverrideUndefined };
Attribute(AttributeKind kind) : kind(kind) { }
static Attribute *combineAttributes(Attribute *a, Attribute *b);
#ifdef DEBUG
virtual void uselessVirtual() { } // want the checked_cast stuff to work, so need a virtual function
#endif
};
// A Namespace (is also an attribute)
class Namespace : public Attribute {
public:
Namespace(StringAtom &name) : Attribute(NamespaceKind), name(name) { }
StringAtom &name; // The namespace's name used by toString
};
class QualifiedName {
public:
Namespace nameSpace; // The namespace qualifier
StringAtom &id; // The name
QualifiedName(Namespace *nameSpace, const StringAtom &id) : nameSpace(nameSpace), id(id) { }
bool operator ==(const QualifiedName &b) { return (nameSpace == b.nameSpace) && (id == b.id); }
Namespace *nameSpace; // The namespace qualifier
const StringAtom &id; // The name
};
@ -92,21 +121,25 @@ class Signature {
bool returnType; // The type of this function's result
};
// A static member is either forbidden, a variable, a hoisted variable, a constructor method, or an accessor:
class StaticMember {
public:
enum StaticMemberKind { Forbidden, Variable, HoistedVariable, ConstructorMethod, Accessor } kind;
};
class Variable : public StaticMember {
public:
JS2Class *type; // Type of values that may be stored in this variable
Object_Uninit_Future value; // This variable's current value; future if the variable has not been declared yet;
js2val value; // This variable's current value; future if the variable has not been declared yet;
// uninitialised if the variable must be written before it can be read
bool immutable; // true if this variable's value may not be changed once set
};
class HoistedVar : public StaticMember {
public:
HoistedVar() : value(JSVAL_VOID), hasFunctionInitializer(false) { }
js2val value; // This variable's current value
bool hasFunctionInitializer; // true if this variable was created by a function statement
};
class StaticMethod : public StaticMember {
@ -124,12 +157,20 @@ public:
};
// DYNAMICPROPERTY record describes one dynamic property of one (prototype or class) instance.
typedef std::map<String, js2val> DynamicPropertyMap;
typedef DynamicPropertyMap::iterator DynamicPropertyIterator;
// A STATICBINDING describes the member to which one qualified name is bound in a frame. Multiple
// qualified names may be bound to the same member in a frame, but a qualified name may not be
// bound to multiple members in a frame (except when one binding is for reading only and
// the other binding is for writing only).
class StaticBinding {
public:
StaticBinding(QualifiedName &qname, StaticMember *content) : qname(qname), content(content), xplicit(false) { }
QualifiedName qname; // The qualified name bound by this binding
StaticMember content; // The member to which this qualified name was bound
StaticMember *content; // The member to which this qualified name was bound
bool xplicit; // true if this binding should not be imported into the global scope by an import statement
};
@ -161,24 +202,41 @@ public:
class InstanceBinding {
public:
QualifiedName qname; // The qualified name bound by this binding
QualifiedName qname; // The qualified name bound by this binding
InstanceMember *content; // The member to which this qualified name was bound
};
class StaticBindingMap {
public:
};
// A StaticBindingMap maps names to a list of StaticBindings. Each StaticBinding in the list
// will have the same QualifiedName.name, but (potentially) different QualifiedName.namespace values
typedef std::multimap<String, StaticBinding *> StaticBindingMap;
typedef StaticBindingMap::iterator StaticBindingIterator;
class InstanceBindingMap {
public:
};
class JS2Class {
// A frame contains bindings defined at a particular scope in a program. A frame is either the top-level system frame,
// a global object, a package, a function frame, a class, or a block frame
class Frame {
public:
enum Plurality { Singular, Plural };
enum FrameKind { GlobalObject, Package, Function, Class, Block };
StaticBindingMap staticReadBindings; // Map of qualified names to readable static members defined in this frame
StaticBindingMap staticWriteBindings; // Map of qualified names to writable static members defined in this frame
FrameKind kind; // [rather than use RTTI (in general)]
Frame *nextFrame;
#ifdef DEBUG
virtual void uselessVirtual() { } // want the checked_cast stuff to work, so need a virtual function
#endif
};
class JS2Class : public Frame {
public:
StaticBindingMap staticReadBindings; // Map of qualified names to readable static members defined in this class
StaticBindingMap staticWriteBindings; // Map of qualified names to writable static members defined in this class
InstanceBindingMap instanceReadBindings; // Map of qualified names to readable instance members defined in this class
InstanceBindingMap instanceWriteBindings; // Map of qualified names to writable instance members defined in this class
@ -189,7 +247,7 @@ public:
JS2Class *super; // This class's immediate superclass or null if none
JS2Object *prototype; // An object that serves as this class's prototype for compatibility with ECMAScript 3; may be null
Namespace privateNamespace; // This class's private namespace
Namespace *privateNamespace; // This class's private namespace
bool dynamic; // true if this class or any of its ancestors was defined with the dynamic attribute
bool primitive; // true if this class was defined with the primitive attribute
@ -200,8 +258,49 @@ public:
};
class GlobalObject : public Frame {
public:
GlobalObject(World &world) : internalNamespace(new Namespace(world.identifiers["internal"])) { }
Namespace *internalNamespace; // This global object's internal namespace
DynamicPropertyMap dynamicProperties; // A set of this global object's dynamic properties
};
// A SLOT record describes the value of one fixed property of one instance.
class Slot {
public:
InstanceVariable *id; // The instance variable whose value this slot carries
js2val value; // This fixed property's current value; uninitialised if the fixed property is an uninitialised constant
};
// Instances of non-dynamic classes are represented as FIXEDINSTANCE records. These instances can contain only fixed properties.
class FixedInstance {
public:
JS2Class *type; // This instance's type
Invokable *call; // A procedure to call when this instance is used in a call expression
Invokable *construct; // A procedure to call when this instance is used in a new expression
Environment *env; // The environment to pass to the call or construct procedure
StringAtom &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
};
// Instances of dynamic classes are represented as DYNAMICINSTANCE records. These instances can contain fixed and dynamic properties.
class DynamicInstance {
public:
JS2Class *type; // This instance's type
Invokable *call; // A procedure to call when this instance is used in a call expression
Invokable *construct; // A procedure to call when this instance is used in a new expression
Environment *env; // The environment to pass to the call or construct procedure
StringAtom &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
};
// MULTINAME is the semantic domain of sets of qualified names. Multinames are used internally in property lookup.
class Multiname {
public:
};
class LexicalReference {
// A LEXICALREFERENCE tuple has the fields below and represents an lvalue that refers to a variable with one
@ -227,6 +326,21 @@ public:
// example above)
};
class NamedArgument {
public:
StringAtom &name; // This argument's name
js2val value; // This argument's value
};
// An ARGUMENTLIST describes the arguments (other than this) passed to a function.
class ArgumentList {
public:
JS2Object *positional; // Ordered list of positional arguments
NamedArgument *named; // Set of named arguments
};
class BracketReference {
// A BRACKETREFERENCE tuple has the fields below and represents an lvalue that refers to the result of
// applying the [] operator to the base object with the given arguments. BRACKETREFERENCE tuples arise from evaluating
@ -239,6 +353,115 @@ public:
};
// The top-level frame containing predefined constants, functions, and classes.
class SystemFrame : public Frame {
public:
};
// Frames holding bindings for invoked functions
class FunctionFrame : public Frame {
public:
Plurality plurality;
JS2Object *thisObject; // The value of this; none if this function doesn't define this;
// XXX // inaccessible if this function defines this but the value is not
// available because this function hasn't been called yet
bool prototype; // true if this function is not an instance method but defines this anyway
};
class BlockFrame : public Frame {
public:
Plurality plurality;
};
// Environments contain the bindings that are visible from a given point in the source code. An ENVIRONMENT is
// a list of two or more frames. Each frame corresponds to a scope. More specific frames are listed first
// -each frame's scope is directly contained in the following frame's scope. The last frame is always the
// SYSTEMFRAME. The next-to-last frame is always a PACKAGE or GLOBAL frame.
class Environment {
public:
Environment(SystemFrame *systemFrame, Frame *nextToLast) : firstFrame(nextToLast) { nextToLast->nextFrame = systemFrame; }
Frame *getRegionalFrame();
Frame *getTopFrame() { return firstFrame; }
private:
Frame *firstFrame;
};
typedef std::vector<Namespace *> NamespaceList;
typedef NamespaceList::iterator NamespaceListIterator;
// A CONTEXT carries static information about a particular point in the source program.
class Context {
public:
bool strict; // true if strict mode is in effect
Namespace *openNamespaces; // The set of namespaces that are open at this point.
// The public namespace is always a member of this set.
};
// The 'true' attribute
class TrueAttribute : public Attribute {
public:
TrueAttribute() : Attribute(TrueKind) { }
};
// The 'false' attribute
class FalseAttribute : public Attribute {
public:
FalseAttribute() : Attribute(FalseKind) { }
};
// Compound attribute objects are all values obtained from combining zero or more syntactic attributes
// that are not Booleans or single namespaces.
class CompoundAttribute : public Attribute {
public:
CompoundAttribute();
void addNamespace(Namespace *n);
NamespaceList *namespaces; // The set of namespaces contained in this attribute
bool xplicit; // true if the explicit attribute has been given
bool dynamic; // true if the dynamic attribute has been given
MemberModifier memberMod; // if one of these attributes has been given; none if not.
OverrideModifier overrideMod; // if the override attribute with one of these arguments was given;
// true if the attribute override without arguments was given; none if the override attribute was not given.
bool prototype; // true if the prototype attribute has been given
bool unused; // true if the unused attribute has been given
};
class JS2Metadata {
public:
enum Phase { CompilePhase, RunPhase };
JS2Metadata(World &world);
void setCurrentParser(Parser *parser) { mParser = parser; }
void ValidateTypeExpression(ExprNode *e);
void ValidateStmtList(Context *cxt, Environment *env, StmtNode *p);
void ValidateStmt(Context *cxt, Environment *env, StmtNode *p);
void defineHoistedVar(Environment *env, const StringAtom &id, StmtNode *p);
void ValidateExpression(Context *cxt, Environment *env, ExprNode *p);
jsval EvalExpression(Environment *env, Phase phase, ExprNode *p);
Attribute *EvalAttributeExpression(Environment *env, Phase phase, ExprNode *p);
jsval EvalStmtList(Environment *env, Phase phase, StmtNode *p);
jsval EvalStmt(Environment *env, Phase phase, StmtNode *p);
void reportError(Exception::Kind kind, char *message, size_t pos, const char *arg = NULL);
void reportError(Exception::Kind kind, char *message, size_t pos, const String& name);
void initializeMonkey();
jsval execute(String *str);
// The one and only 'public' namespace
Namespace publicNamespace; // XXX is this the right place for this ???
Parser *mParser; // used for error reporting
};
}; // namespace MetaData

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

@ -36,13 +36,19 @@
#include <cfloat>
#include "numerics.h"
#include "parser.h"
//#include "js2runtime.h"
#ifdef DIKDIK
#include "js2runtime.h"
#endif
#include "fdlibm_ns.h"
namespace JS = JavaScript;
using namespace JS;
#ifdef DIKDIK
using namespace JS::JS2Runtime;
#endif
//
// Portable double-precision floating point to string and back conversions

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

@ -96,7 +96,6 @@ typedef float float32;
#define IS_LITTLE_ENDIAN
#endif
// basicAlignment is the maximum alignment required by any native type. An
// object aligned to a multiple of basicAlignment can hold any native type.
// malloc should return a pointer whose lgBasicAlignment least significant bits

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

@ -39,17 +39,18 @@ RSC=rc.exe
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\..\js\src" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib js32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "Epimetheus - Win32 Debug"
@ -62,17 +63,18 @@ LINK32=link.exe
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "..\..\..\..\js\src" /D "_DEBUG" /D "DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "XP_PC" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 js32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"..\..\..\..\js\src\debug"
!ENDIF
@ -101,6 +103,14 @@ SOURCE=..\..\hash.cpp
# End Source File
# Begin Source File
SOURCE=..\..\js2eval.cpp
# End Source File
# Begin Source File
SOURCE=..\..\js2metadata.cpp
# End Source File
# Begin Source File
SOURCE=..\..\lexer.cpp
# End Source File
# Begin Source File
@ -153,6 +163,14 @@ SOURCE=..\..\hash.h
# End Source File
# Begin Source File
SOURCE=..\..\js2metadata.h
# End Source File
# Begin Source File
SOURCE=..\..\js2value.h
# End Source File
# Begin Source File
SOURCE=..\..\lexer.h
# End Source File
# Begin Source File

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

@ -72,9 +72,11 @@ namespace JavaScript {
StringAtom &operator[](const char *s) {return operator[](widenCString(s));}
};
#ifdef DIKDIK
namespace JS2Runtime {
class Context;
}
#endif
class World {
public:
@ -82,6 +84,7 @@ namespace JavaScript {
World();
#ifdef DIKDIK
std::vector<JS2Runtime::Context *> contextList;
/* Random number generator state, used by jsmath.c. */
@ -91,6 +94,8 @@ namespace JavaScript {
int64 rngMask;
int64 rngSeed;
float64 rngDscale;
#endif
};
}
#endif