diff --git a/mozilla/js2/src/bytecodegen.cpp b/mozilla/js2/src/bytecodegen.cpp new file mode 100644 index 00000000000..6869361e505 --- /dev/null +++ b/mozilla/js2/src/bytecodegen.cpp @@ -0,0 +1,225 @@ +/* -*- 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 oqr + * 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) +#endif + +#include "parser.h" +#include "js2runtime.h" +#include "bytecodegen.h" + +namespace JavaScript { +namespace ByteCode { + + using namespace JS2Runtime; + + void ByteCodeGen::addByte(char v) + { + if (mBufferTop == mBufferMax) { + uint32 bufSize = mBufferMax - mBuffer; + ByteCodeOp *newBuffer = new ByteCodeOp[bufSize + BufferIncrement]; + if (mBuffer) { + memcpy(newBuffer, mBuffer, bufSize); + delete mBuffer; + } + mBuffer = newBuffer; + mBufferTop = mBuffer + bufSize; + mBufferMax = mBuffer + bufSize + BufferIncrement; + } + *mBufferTop++ = (ByteCodeOp)v; + } + + ByteCodeModule *ByteCodeGen::genCodeForStatement(StmtNode *p) + { + switch (p->getKind()) { + case StmtNode::expression: + { + ExprStmtNode *e = static_cast(p); + genExpr(e->expr); + } + break; + } + return NULL; + } + /* + static bool isStaticName(JSClass *c, const StringAtom &name, Reference &ref) + { + do { + bool isConstructor = false; + if (c->hasStatic(name, ref.mType, isConstructor)) { + ref.mClass = c; + ref.mKind = (isConstructor) ? Constructor : Static; + return true; + } + c = c->getSuperClass(); + } while (c); + return false; + } + + bool ICodeGenerator::getVariableByName(const StringAtom &name, Reference &ref) + { + TypedRegister v; + v = variableList->findVariable(name); + if (v.first == NotARegister) + v = parameterList->findVariable(name); + if (v.first != NotARegister) { + ref.mKind = Var; + ref.mBase = v; + ref.mType = v.second; + return true; + } + return false; + } + + bool ICodeGenerator::scanForVariable(const StringAtom &name, Reference &ref) + { + if (getVariableByName(name, ref)) + return true; + + uint32 count = 0; + ICodeGenerator *upper = mContainingFunction; + while (upper) { + if (upper->getVariableByName(name, ref)) { + ref.mKind = ClosureVar; + ref.mSlotIndex = ref.mBase.first; + ref.mBase = getClosure(count); + return true; + } + count++; + upper = upper->mContainingFunction; + } + return false; + } + + // find 'name' (unqualified) in the current context. + // for local variable, returns v.first = register number + // for slot/method, returns slotIndex and sets base appropriately + // (note closure vars also get handled this way) + // v.second is set to the type regardless + bool ByteCodeGen::resolveIdentifier(const StringAtom &name, Reference &ref, Access access) + { + if (!mIsWithinWith) { + if (scanForVariable(name, ref)) + return true; + else { + if (mClass) { // we're compiling a method of a class + // look for static references first + if (isStaticName(mClass, name, ref, access)) { + return true; + } + // then instance methods (if we're in a instance member function) + if (!isStaticMethod()) { + if (isSlotName(mClass, name, ref, access)) { + return true; + } + } + } + // last chance - if it's a generic name in the global scope, try to get a type for it + ref.mKind = Name; + ref.mType = mContext->getGlobalObject()->getType(name); + return true; + } + } + // all bet's off, generic name & type + ref.mKind = Name; + ref.mType = &Object_Type; + return true; + } + + genReference(ExprNode *p) + { + switch (p->getKind()) { + case ExprNode::identifer: + { + + } +*/ + + // a ByteCodeGen has a static scope chain (a JSScope is a JSType with a parent link) + + + void ByteCodeGen::genExpr(ExprNode *p) + { + switch (p->getKind()) { + case ExprNode::True: + addByte(LoadConstantTrueOp); + break; + case ExprNode::False: + addByte(LoadConstantFalseOp); + break; + case ExprNode::Null: + addByte(LoadConstantNullOp); + break; + case ExprNode::add: + { + BinaryExprNode *b = static_cast(p); + genExpr(b->op1); + genExpr(b->op2); + addByte(DoOperatorOp); + addByte(Plus); + } + break; + case ExprNode::identifier: + { + const StringAtom &name = static_cast(p)->name; + Reference *ref = mScopeChain.getName(name, Read); + ASSERT(ref); + ref->emitCodeSequence(); + } + break; + case ExprNode::New: + { + InvokeExprNode *i = static_cast(p); + + genExpr(i->op); + addByte(GetTypeOp); + + ExprPairList *p = i->pairs; + while (p) { + genExpr(p->value); + p = p->next; + } + addByte(NewObjectOp); + + + } + break; + } + } + +} +} + diff --git a/mozilla/js2/src/bytecodegen.h b/mozilla/js2/src/bytecodegen.h new file mode 100644 index 00000000000..ad72b65b3a8 --- /dev/null +++ b/mozilla/js2/src/bytecodegen.h @@ -0,0 +1,151 @@ +/* -*- 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 oqr + * 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. + */ + +#ifndef bytecodegen_h___ +#define bytecodegen_h___ + +#ifdef _WIN32 + // Turn off warnings about identifiers too long in browser information +#pragma warning(disable: 4786) +#endif + + +#include +#include + +#include "systemtypes.h" +#include "strings.h" + +namespace JavaScript { +namespace ByteCode { + + + using namespace JS2Runtime; + + typedef enum { + + LoadConstantTrueOp, // --> + LoadConstantFalseOp, // --> + LoadConstantNullOp, // --> + + InvokeOp, // --> + + GetTypeOp, // --> + + DoOperatorOp, // --> + + PushNullOp, // --> + PushIntOp, // --> + PushNumOp, // --> + PushStringOp, // --> + PushTypeOp, // + + ReturnOp, // --> + + NewObjectOp, // --> + + + JcondOp, // --> + JumpOp, // + + + + // for instance members + GetFieldOp, // --> + SetFieldOp, // --> + + // for instance methods + GetMethodOp, // --> + + // for local variables in the immediate scope + GetLocalVarOp, // --> + SetLocalVarOp, // --> + + // for local variables in the nth closure scope + GetClosureVarOp, // , --> + SetClosureVarOp, // , --> + + // for all other names + GetNameOp, // --> + SetNameOp, // --> + + + } ByteCodeOp; + + + class ByteCodeModule { + public: + ByteCodeOp *mCodeBase; + uint32 mLength; + + }; + + #define BufferIncrement (32) + + class ByteCodeGen { + public: + ByteCodeModule *genCodeForStatement(StmtNode *p); + void genExpr(ExprNode *p); + + + void addByte(char v); + void addPointer(void *v) { } + void addLong(uint32 i) { } + + String mStringPoolContents; + typedef std::map > StringPool; + StringPool mStringPool; + + void addStringRef(const String &str) + { + StringPool::iterator i = mStringPool.find(str); + if (i != mStringPool.end()) + addLong(i->second); + else { + addLong(mStringPoolContents.size()); + mStringPoolContents += str; + } + } + + ScopeChain mScopeChain; + + ByteCodeOp *mBuffer; + ByteCodeOp *mBufferTop; + ByteCodeOp *mBufferMax; + }; + + +} +} + +#endif bytecodegen_h___ \ No newline at end of file diff --git a/mozilla/js2/src/js2runtime.cpp b/mozilla/js2/src/js2runtime.cpp new file mode 100644 index 00000000000..07d46c79aaa --- /dev/null +++ b/mozilla/js2/src/js2runtime.cpp @@ -0,0 +1,704 @@ +/* -*- 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 oqr + * 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) +#endif + +#include "parser.h" +#include "numerics.h" +#include "js2runtime.h" +#include "bytecodegen.h" + +namespace JavaScript { +namespace JS2Runtime { + +using namespace ByteCode; + +JSType *Object_Type = new JSType(NULL); +JSType *Number_Type = new JSType(Object_Type); + +static bool hasAttribute(const IdentifierList* identifiers, Token::Kind tokenKind) +{ + while (identifiers) { + if (identifiers->name.tokenKind == tokenKind) + return true; + identifiers = identifiers->next; + } + return false; +} + +static bool hasAttribute(const IdentifierList* identifiers, StringAtom &name) +{ + while (identifiers) { + if (identifiers->name == name) + return true; + identifiers = identifiers->next; + } + return false; +} + +JSType *Context::findType(const StringAtom& typeName) +{ + const JSValue type = getGlobalObject()->getProperty(typeName); + if (type.isType()) + return type.type; + return Object_Type; +} + +JSType *Context::extractType(ExprNode *t) +{ + JSType *type = Object_Type; + if (t && (t->getKind() == ExprNode::identifier)) { + IdentifierExprNode* typeExpr = static_cast(t); + type = findType(typeExpr->name); + } + return type; +} + +JSValue defaultGetterImp(JSValueList args) +{ + // arg[0] is this + // arg[1] is slot + ASSERT(args[0].isObject()); + JSInstance *inst = static_cast(args[0].object); + ASSERT(args[1].isSlot()); + Slot *slot = args[1].slot; + return inst->mInstanceValues[slot->mIndex]; +} +JSValue defaultSetterImp(JSValueList args) +{ + // arg[0] is this + // arg[1] is slot + // arg[2] is new value + ASSERT(args[0].isObject()); + JSInstance *inst = static_cast(args[0].object); + ASSERT(args[1].isSlot()); + Slot *slot = args[1].slot; + inst->mInstanceValues[slot->mIndex] = args[2]; + return args[2]; +} +JSValue methodGetterImp(JSValueList args) +{ + // arg[0] is this + // arg[1] is slot + ASSERT(args[0].isObject()); + JSType *cl = args[0].object->getType(); + ASSERT(args[1].isSlot()); + Slot *slot = args[1].slot; + return JSValue(cl->mMethods[slot->mIndex]); +} +JSFunction *Context::defaultGetter = new JSFunction(defaultGetterImp); +JSFunction *Context::defaultSetter = new JSFunction(defaultSetterImp); +JSFunction *Context::methodGetter = new JSFunction(methodGetterImp); + +JS2Runtime::Operator simpleLookup[ExprNode::kindsEnd] = { + JS2Runtime::None, // none, + JS2Runtime::None, // identifier, + JS2Runtime::None, // number, + JS2Runtime::None, // string, + JS2Runtime::None, // regExp + JS2Runtime::None, // Null, + JS2Runtime::None, // True, + JS2Runtime::None, // False, + JS2Runtime::None, // This, + JS2Runtime::None, // Super, + JS2Runtime::None, // parentheses, + JS2Runtime::None, // numUnit, + JS2Runtime::None, // exprUnit, + JS2Runtime::None, // qualify, + JS2Runtime::None, // objectLiteral, + JS2Runtime::None, // arrayLiteral, + JS2Runtime::None, // functionLiteral, + JS2Runtime::None, // call, + JS2Runtime::None, // New, + JS2Runtime::None, // index, + JS2Runtime::None, // dot, + JS2Runtime::None, // dotClass, + JS2Runtime::None, // dotParen, + JS2Runtime::None, // at, + JS2Runtime::None, // Delete, + JS2Runtime::None, // Typeof, + JS2Runtime::None, // Eval, + JS2Runtime::None, // preIncrement, + JS2Runtime::None, // preDecrement, + JS2Runtime::None, // postIncrement, + JS2Runtime::None, // postDecrement, + JS2Runtime::None, // plus, + JS2Runtime::None, // minus, + JS2Runtime::Complement, // complement, + JS2Runtime::None, // logicalNot, + JS2Runtime::None, // add, + JS2Runtime::None, // subtract, + JS2Runtime::Multiply, // multiply, + JS2Runtime::Divide, // divide, + JS2Runtime::Remainder, // modulo, + JS2Runtime::ShiftLeft, // leftShift, + JS2Runtime::ShiftRight, // rightShift, + JS2Runtime::UShiftRight, // logicalRightShift, + JS2Runtime::BitAnd, // bitwiseAnd, + JS2Runtime::BitXor, // bitwiseXor, + JS2Runtime::BitOr, // bitwiseOr, + JS2Runtime::None, // logicalAnd, + JS2Runtime::None, // logicalXor, + JS2Runtime::None, // logicalOr, + JS2Runtime::Equal, // equal, + JS2Runtime::None, // notEqual, + JS2Runtime::Less, // lessThan, + JS2Runtime::LessEqual, // lessThanOrEqual, + JS2Runtime::None, // greaterThan, + JS2Runtime::None, // greaterThanOrEqual, + JS2Runtime::SpittingImage, // identical, + JS2Runtime::None, // notIdentical, + JS2Runtime::In, // In, + JS2Runtime::None, // Instanceof, + JS2Runtime::None, // assignment, + JS2Runtime::None, // addEquals, + JS2Runtime::None, // subtractEquals, + JS2Runtime::None, // multiplyEquals, + JS2Runtime::None, // divideEquals, + JS2Runtime::None, // moduloEquals, + JS2Runtime::None, // leftShiftEquals, + JS2Runtime::None, // rightShiftEquals, + JS2Runtime::None, // logicalRightShiftEquals, + JS2Runtime::None, // bitwiseAndEquals, + JS2Runtime::None, // bitwiseXorEquals, + JS2Runtime::None, // bitwiseOrEquals, + JS2Runtime::None, // logicalAndEquals, + JS2Runtime::None, // logicalXorEquals, + JS2Runtime::None, // logicalOrEquals, + JS2Runtime::None, // conditional, + JS2Runtime::None, // comma, +}; + + +JS2Runtime::Operator Context::getOperator(uint32 parameterCount, String &name) +{ + Lexer operatorLexer(getWorld(), name, widenCString("Operator name"), 0); // XXX get source and line number from function ??? + const Token &t = operatorLexer.get(false); // XXX what's correct for preferRegExp parameter ??? + + JS2Runtime::Operator op = simpleLookup[t.getKind()]; + if (op != JS2Runtime::None) + return op; + else { + switch (t.getKind()) { + default: + NOT_REACHED("Illegal operator name"); + + case Token::plus: + if (parameterCount == 1) + return JS2Runtime::Posate; + else + return JS2Runtime::Plus; + case Token::minus: + if (parameterCount == 1) + return JS2Runtime::Negate; + else + return JS2Runtime::Minus; + + case Token::openParenthesis: + return JS2Runtime::Call; + + case Token::New: + if (parameterCount > 1) + return JS2Runtime::NewArgs; + else + return JS2Runtime::New; + + case Token::openBracket: + { + const Token &t2 = operatorLexer.get(false); + ASSERT(t2.getKind() == Token::closeBracket); + const Token &t3 = operatorLexer.get(false); + if (t3.getKind() == Token::equal) + return JS2Runtime::IndexEqual; + else + return JS2Runtime::Index; + } + + case Token::Delete: + return JS2Runtime::DeleteIndex; + } + } + return JS2Runtime::None; +} + +JSType *Context::getParameterType(FunctionDefinition &function, int index) +{ + VariableBinding *v = function.parameters; + while (v) { + if (index-- == 0) + return extractType(v->type); + else + v = v->next; + } + return NULL; +} + +uint32 Context::getParameterCount(FunctionDefinition &function) +{ + uint32 count = 0; + VariableBinding *v = function.parameters; + while (v) { + count++; + v = v->next; + } + return count; +} + + +ByteCodeModule *Context::genCode(StmtNode *p, String sourceName) +{ + ByteCodeGen bcg; + return bcg.genCodeForStatement(p); +} + +bool Context::executeOperator(Operator op, JSType *t1, JSType *t2) +{ + return false; +} + +JSValue Context::interpret(ByteCodeModule *bcm, JSValueList args) +{ + ByteCodeOp *pc = bcm->mCodeBase; + ByteCodeOp *endPC = bcm->mCodeBase + bcm->mLength; + + std::stack stack; + +// XXX !!! BOGUS !!! XXX +#define MaxLocals (32) + JSValue *locals = new JSValue[MaxLocals]; + + while (pc != endPC) { + switch (*pc) { + case DoOperatorOp: + { + Operator op = (Operator)(*pc++); + JSValue v1 = stack.top(); + stack.pop(); + JSValue v2 = stack.top(); + stack.pop(); + if (executeOperator(op, v1.getType(), v2.getType())) { + // need to invoke + } + } + break; + case NewObjectOp: + { + JSValue v = stack.top(); + stack.pop(); + ASSERT(v.isType()); + JSType *type = v.type; + stack.push(JSValue(type->newInstance())); + } + break; + case GetLocalVarOp: + { + uint32 i = *((uint32 *)pc); + pc += sizeof(uint32); + stack.push(locals[i]); + } + break; + case SetLocalVarOp: + { + uint32 i = *((uint32 *)pc); + pc += sizeof(uint32); + locals[i] = stack.top(); + stack.pop(); + } + break; + } + } + return kUndefinedValue; +} + +void Context::buildRuntime(StmtNode *p) +{ +// mScopeChain.addScope(mGlobalObject); + buildRuntimeForStmt(p); +} + +void Context::buildRuntimeForStmt(StmtNode *p) +{ + switch (p->getKind()) { + case StmtNode::Var: + { + // enter the variable into the current scope object + VariableStmtNode *vs = static_cast(p); + VariableBinding *v = vs->bindings; + while (v) { + if (v->name && (v->name->getKind() == ExprNode::identifier)) { + IdentifierExprNode *i = static_cast(v->name); + JSType *type = extractType(v->type); +// mScopeChain.defineVariable(i->name, type, defaultGetter, defaultSetter); + if (v->initializer) { + // assign value from v->initializer to the variable just defined + } + } + v = v->next; + } + } + break; + case StmtNode::Class: + { + // build a new type object and it's static component + // enter the class name into the global object + + // construct the vtable, instance & static slotmaps + + ClassStmtNode *classStmt = static_cast(p); + ASSERT(classStmt->name->getKind() == ExprNode::identifier); // XXX need to handle qualified names!!! + + IdentifierExprNode* nameExpr = static_cast(classStmt->name); + JSType *superclass = 0; + if (classStmt->superclass) { + ASSERT(classStmt->superclass->getKind() == ExprNode::identifier); // XXX + IdentifierExprNode *superclassExpr = static_cast(classStmt->superclass); + + JSValue superclassValue = getGlobalObject()->getProperty(superclassExpr->name); + + + ASSERT(superclassValue.isType() && !superclassValue.isNull()); + superclass = static_cast(superclassValue.type); + } + JSType* thisClass = new JSType(superclass); + + // 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. + getGlobalObject()->setProperty(nameExpr->name, JSValue(thisClass)); + +/* + Declare all the methods & fields +*/ + bool needsInstanceInitializer = false; + if (classStmt->body) { + StmtNode* s = classStmt->body->statements; + while (s) { + switch (s->getKind()) { + case StmtNode::Const: + case StmtNode::Var: + { + VariableStmtNode *vs = static_cast(s); + bool isStatic = hasAttribute(vs->attributes, Token::Static); + VariableBinding *v = vs->bindings; + while (v) { + if (v->name) { + ASSERT(v->name->getKind() == ExprNode::identifier); // XXX + IdentifierExprNode* idExpr = static_cast(v->name); + JSType *type = extractType(v->type); + if (isStatic) + thisClass->defineStaticVariable(idExpr->name, type, + defaultGetter, + defaultSetter); + else { + if (hasAttribute(vs->attributes, VirtualKeyWord)) + thisClass->defineVariable(idExpr->name, type, + defaultGetter, + defaultSetter); + else + thisClass->defineVariable(idExpr->name, type, + defaultGetter, + defaultSetter); + if (v->initializer) + needsInstanceInitializer = true; + } + } + v = v->next; + } + } + break; + case StmtNode::Function: + { + FunctionStmtNode *f = static_cast(s); + bool isStatic = hasAttribute(f->attributes, Token::Static); + bool isConstructor = hasAttribute(f->attributes, ConstructorKeyWord); + bool isOperator = hasAttribute(f->attributes, OperatorKeyWord); + if (isOperator) { + ASSERT(f->function.name->getKind() == ExprNode::string); + Operator op = getOperator(getParameterCount(f->function), + (static_cast(f->function.name))->str); + defineOperator(op, getParameterType(f->function, 0), + getParameterType(f->function, 1), NULL); + } + else + if (f->function.name->getKind() == ExprNode::identifier) { + const StringAtom& name = (static_cast(f->function.name))->name; + if (isConstructor) + thisClass->defineConstructor(name, NULL, methodGetter); + else + if (isStatic) + thisClass->defineStaticMethod(name, NULL, methodGetter); + else { + switch (f->function.prefix) { +/* + case FunctionName::Get: + thisClass->setGetter(name, NULL, mContext->extractType(f->function.resultType)); + break; + case FunctionName::Set: + thisClass->setSetter(name, NULL, mContext->extractType(f->function.resultType)); + break; +*/ + case FunctionName::normal: + thisClass->defineMethod(name, NULL, methodGetter); + break; + default: + NOT_REACHED("unexpected prefix"); + break; + } + } + } + } + break; + default: + NOT_REACHED("unimplemented class member statement"); + break; + } + s = s->next; + } + } +// if (needsInstanceInitializer) +// thisClass->defineStatic(mInitName, &Function_Type); + + } + break; + case StmtNode::Function: + { + } + break; + } + +} + + + + + +bool JSValue::isNaN() const +{ + ASSERT(isNumber()); + switch (tag) { + case f64_tag: + return JSDOUBLE_IS_NaN(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isNegativeInfinity() const +{ + ASSERT(isNumber()); + switch (tag) { + case f64_tag: + return (f64 < 0) && JSDOUBLE_IS_INFINITE(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isPositiveInfinity() const +{ + ASSERT(isNumber()); + switch (tag) { + case f64_tag: + return (f64 > 0) && JSDOUBLE_IS_INFINITE(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isNegativeZero() const +{ + ASSERT(isNumber()); + switch (tag) { + case f64_tag: + return JSDOUBLE_IS_NEGZERO(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isPositiveZero() const +{ + ASSERT(isNumber()); + switch (tag) { + case f64_tag: + return (f64 == 0.0) && !JSDOUBLE_IS_NEGZERO(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +int JSValue::operator==(const JSValue& value) const +{ + if (this->tag == value.tag) { +# define CASE(T) case T##_tag: return (this->T == value.T) + switch (tag) { + CASE(f64); + CASE(object); + CASE(boolean); + #undef CASE + // question: are all undefined values equal to one another? + case undefined_tag: return 1; + default: + NOT_REACHED("Broken compiler?"); + } + } + return 0; +} + + +Formatter& operator<<(Formatter& f, const JSValue& value) +{ + switch (value.tag) { + case JSValue::f64_tag: + f << value.f64; + break; + case JSValue::object_tag: + printFormat(f, "Object @ 0x%08X\n", value.object); + f << *value.object; + break; + case JSValue::type_tag: + printFormat(f, "Type @ 0x%08X\n", value.type); + f << *value.type; + break; + case JSValue::boolean_tag: + f << ((value.boolean) ? "true" : "false"); + break; + case JSValue::undefined_tag: + f << "undefined"; + break; + case JSValue::null_tag: + f << "null"; + break; + default: + NOT_REACHED("Bad tag"); + } + return f; +} + + + + void AccessorReference::emitCodeSequence(ByteCodeGen *bcg) + { + bcg->addByte(InvokeOp); + bcg->addPointer(mFunction); + } + + void LocalVarReference::emitCodeSequence(ByteCodeGen *bcg) + { + if (mAccess == Read) + bcg->addByte(GetLocalVarOp); + else + bcg->addByte(SetLocalVarOp); + bcg->addLong(mIndex); + } + + void ClosureVarReference::emitCodeSequence(ByteCodeGen *bcg) + { + if (mAccess == Read) + bcg->addByte(GetClosureVarOp); + else + bcg->addByte(SetClosureVarOp); + bcg->addLong(mDepth); + bcg->addLong(mIndex); + } + + void FieldReference::emitCodeSequence(ByteCodeGen *bcg) + { + if (mAccess == Read) + bcg->addByte(GetFieldOp); + else + bcg->addByte(SetFieldOp); + bcg->addLong(mIndex); + } + + void MethodReference::emitCodeSequence(ByteCodeGen *bcg) + { + bcg->addByte(GetMethodOp); + bcg->addLong(mIndex); + } + + void NameReference::emitCodeSequence(ByteCodeGen *bcg) + { + if (mAccess == Read) + bcg->addByte(GetNameOp); + else + bcg->addByte(SetNameOp); + bcg->addStringRef(mName); + } + + + + + + +Formatter& operator<<(Formatter& f, const JSObject& obj) +{ + obj.printProperties(f); + return f; +} +Formatter& operator<<(Formatter& f, const JSType& obj) +{ + printFormat(f, "super @ 0x%08X\n", obj.mSuperType); + obj.printProperties(f); + obj.printSlotsNStuff(f); + return f; +} +Formatter& operator<<(Formatter& f, const Access& slot) +{ + switch (slot) { + case Read : f << "Read\n"; break; + case Write : f << "Write\n"; break; + } + return f; +} +Formatter& operator<<(Formatter& f, const Slot& slot) +{ + f << "index = " << slot.mIndex << "\n"; + printFormat(f, "code @ 0x%08X\n", slot.mAccessor); + return f; +} + + + + +} +} + diff --git a/mozilla/js2/src/js2runtime.h b/mozilla/js2/src/js2runtime.h new file mode 100644 index 00000000000..2fdc21e3206 --- /dev/null +++ b/mozilla/js2/src/js2runtime.h @@ -0,0 +1,663 @@ +/* -*- 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 oqr + * 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. + */ + +#ifndef js2runtime_h___ +#define js2runtime_h___ + +#ifdef _WIN32 + // Turn off warnings about identifiers too long in browser information +#pragma warning(disable: 4786) +#endif + + +#include +#include +#include + +#include "systemtypes.h" +#include "strings.h" +#include "formatter.h" + +namespace JavaScript { + namespace ByteCode { + class ByteCodeGen; + class ByteCodeModule; + } +namespace JS2Runtime { + + using namespace ByteCode; + +#ifdef IS_LITTLE_ENDIAN +#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) +#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) +#else +#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0]) +#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) +#endif + +#define JSDOUBLE_HI32_SIGNBIT 0x80000000 +#define JSDOUBLE_HI32_EXPMASK 0x7ff00000 +#define JSDOUBLE_HI32_MANTMASK 0x000fffff + +#define JSDOUBLE_IS_NaN(x) \ + ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \ + (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK))) + +#define JSDOUBLE_IS_INFINITE(x) \ + ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \ + !JSDOUBLE_LO32(x)) + +#define JSDOUBLE_IS_FINITE(x) \ + ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK) + +#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \ + JSDOUBLE_LO32(d) == 0) + + + class JSObject; + class JSFunction; + class JSType; + class Slot; + + + extern JSType *Object_Type; // the base type for all types + extern JSType *Number_Type; + + + class JSValue { + public: + union { + float64 f64; + JSObject *object; + JSFunction *function; + JSType *type; + bool boolean; + Slot *slot; + }; + + typedef enum { + f64_tag, + object_tag, + function_tag, + type_tag, + slot_tag, + boolean_tag, + undefined_tag, + null_tag, + } Tag; + Tag tag; + + JSValue() : f64(0.0), tag(undefined_tag) {} + explicit JSValue(float64 f64) : f64(f64), tag(f64_tag) {} + explicit JSValue(JSObject *object) : object(object), tag(object_tag) {} + explicit JSValue(JSFunction *function) : function(function), tag(function_tag) {} + explicit JSValue(JSType *type) : type(type), tag(type_tag) {} + explicit JSValue(Slot *slot) : slot(slot), tag(slot_tag) {} + explicit JSValue(bool boolean) : boolean(boolean), tag(boolean_tag) {} + explicit JSValue(Tag tag) : tag(tag) {} + + float64& operator=(float64 f64) { return (tag = f64_tag, this->f64 = f64); } + JSObject*& operator=(JSObject* object) { return (tag = object_tag, this->object = object); } + JSType*& operator=(JSType* type) { return (tag = type_tag, this->type = type); } + Slot*& operator=(Slot* slot) { return (tag = slot_tag, this->slot = slot); } + JSFunction*& operator=(JSFunction* slot) { return (tag = function_tag, this->function = function); } + bool& operator=(bool boolean) { return (tag = boolean_tag, this->boolean = boolean); } + + bool isObject() const { return (tag == object_tag); } + bool isNumber() const { return (tag == f64_tag); } + bool isBool() const { return (tag == boolean_tag); } + bool isType() const { return (tag == type_tag); } + bool isSlot() const { return (tag == slot_tag); } + bool isFunction() const { return (tag == function_tag); } + + bool isUndefined() const { return (tag == undefined_tag); } + bool isNull() const { return (tag == null_tag); } + bool isNaN() const; + bool isNegativeInfinity() const; + bool isPositiveInfinity() const; + bool isNegativeZero() const; + bool isPositiveZero() const; + + JSType *getType(); + + int operator==(const JSValue& value) const; + }; + Formatter& operator<<(Formatter& f, const JSValue& value); + + extern const JSValue kUndefinedValue; + extern const JSValue kNaNValue; + extern const JSValue kTrueValue; + extern const JSValue kFalseValue; + extern const JSValue kNullValue; + extern const JSValue kNegativeZero; + extern const JSValue kPositiveZero; + extern const JSValue kNegativeInfinity; + extern const JSValue kPositiveInfinity; + + typedef std::vector JSValueList; + typedef std::map > ValueMap; + + + + typedef enum { + None, + Posate, + Negate, + Complement, + Increment, + Decrement, + Const, + Call, + New, + NewArgs, + Index, + IndexEqual, + DeleteIndex, + Plus, + Minus, + Multiply, + Divide, + Remainder, + ShiftLeft, + ShiftRight, + UShiftRight, + Less, + LessEqual, + In, + Equal, + SpittingImage, + BitAnd, + BitXor, + BitOr, + OperatorCount + } Operator; + + + + class JSFunction { + typedef JSValue (NativeCode)(JSValueList); + public: + JSFunction(NativeCode *code) : mCode(code) { } + NativeCode *mCode; + }; + + + + + + +#define PROPERTY_VALUE(it) (it->second) +#define PROPERTY_NAME(it) (it->first) + + class JSObject { + public: + // The generic Javascript object. Every JS2 object is one of these + JSType *mType; + ValueMap mProperties; // simple map from to + + JSObject(JSType *type = Object_Type) : mType(type) { } + + + JSType *getType() { return mType; } + + void setProperty(const String &name, JSValue v) + { + mProperties[name] = v; + } + + bool hasProperty(const String &name) + { + return (mProperties.find(name) != mProperties.end()); + } + + JSValue getProperty(const String &name) + { + ValueMap::iterator i = mProperties.find(name); + if (i == mProperties.end()) + return kUndefinedValue; + else + return PROPERTY_VALUE(i); + } + + void printProperties(Formatter &f) const + { + for (ValueMap::const_iterator i = mProperties.begin(), end = mProperties.end(); (i != end); i++) + { + f << "[" << PROPERTY_NAME(i) << "] " << PROPERTY_VALUE(i) << "\n"; + } + } + + + }; + + Formatter& operator<<(Formatter& f, const JSObject& obj); + + + + + inline JSType *JSValue::getType() { + switch (tag) { + case f64_tag: return Number_Type; + case object_tag: return object->getType(); + default: NOT_REACHED("bad type"); return NULL; + } + } + + + + + + + + class Slot { + public: + Slot() : mIndex(-1), mAccessor(NULL) { } + Slot(JSFunction *f, uint32 i) : mIndex(i), mAccessor(f) { } + uint32 mIndex; // default getters & setters use this to address the mInstanceValues array + JSFunction *mAccessor; + }; + Formatter& operator<<(Formatter& f, const Slot& slot); + + typedef enum { Read, Write } Access; + Formatter& operator<<(Formatter& f, const Access& acc); + + typedef std::pair NameAccessPair; + typedef std::map > SlotMap; + +#define SLOT_NAME(it) (it->first.first) +#define SLOT_ACCESS(it) (it->first.second) +#define SLOT(it) (it->second) + + + + + + + + + + + + + class Reference { + public: + virtual void emitCodeSequence() { } + }; + + class AccessorReference : public Reference { + public: + AccessorReference(JSFunction *f) : mFunction(f) { } + JSFunction *mFunction; + void emitCodeSequence(ByteCodeGen *bcg); + }; + class LocalVarReference : public Reference { + public: + LocalVarReference(uint32 index, Access acc) : mAccess(acc), mIndex(index) { } + Access mAccess; + uint32 mIndex; + void emitCodeSequence(ByteCodeGen *bcg); + }; + class ClosureVarReference : public LocalVarReference { + public: + ClosureVarReference(uint32 depth, uint32 index, Access acc) + : LocalVarReference(index, acc), mDepth(depth) { } + uint32 mDepth; + void emitCodeSequence(ByteCodeGen *bcg); + }; + class FieldReference : public Reference { + public: + FieldReference(uint32 index, Access acc) : mAccess(acc), mIndex(index) { } + Access mAccess; + uint32 mIndex; + void emitCodeSequence(ByteCodeGen *bcg); + }; + class MethodReference : public Reference { + public: + MethodReference(uint32 index) : mIndex(index) { } + uint32 mIndex; + void emitCodeSequence(ByteCodeGen *bcg); + }; + class NameReference : public Reference { + public: + NameReference(const String& name, Access acc) : mAccess(acc), mName(name) { } + Access mAccess; + const String& mName; + void emitCodeSequence(ByteCodeGen *bcg); + + }; + + + + + + + + + typedef std::vector MethodList; + + class JSType : public JSObject { + public: + + JSType(JSObject *super) : mSuperType(super), + mStatics(NULL), + mVariableCount(0) + { + } + + void createStaticComponent() + { + mStatics = new JSType(NULL); + } + + JSObject *newInstance(); + + + // static helpers + + void defineStaticMethod(const String& name, JSFunction *f, JSFunction *methodGetter) + { + mStatics->defineMethod(name, f, methodGetter); + } + + void defineStaticVariable(const String& name, + JSType *type, + JSFunction *defaultGetter, + JSFunction *defaultSetter) + { + mStatics->defineVariable(name, type, defaultGetter, defaultSetter); + } + + bool hasStatic(const String& name, Access acc) + { + return mStatics->hasName(name, acc); + } + + Slot *getStatic(const String& name, Access acc) + { + return mStatics->getName(name, acc); + } + + // + + void defineConstructor(const String& name, JSFunction *f, JSFunction *methodGetter) + { + defineMethod(name, f, methodGetter); + } + + void defineMethod(const String& name, JSFunction *f, JSFunction *methodGetter) + { + NameAccessPair nap(name, Read); + uint32 index = mMethods.size(); + mMethods.push_back(f); + mSlotMap[nap] = new Slot(methodGetter, index); + } + + + void defineVariable(const String& name, + JSType *type, + JSFunction *defaultGetter, + JSFunction *defaultSetter) + { + NameAccessPair read_nap(name, Read); + mSlotMap[read_nap] = new Slot(defaultGetter, mVariableCount); + + NameAccessPair write_nap(name, Write); + mSlotMap[write_nap] = new Slot(defaultSetter, mVariableCount); + ++mVariableCount; + } + + + Slot *getName(const String& name, Access acc) + { + NameAccessPair nap(name, acc); + ASSERT(mSlotMap.find(nap) != mSlotMap.end()); + return mSlotMap[nap]; + } + + bool hasName(const String& name, Access acc) + { + NameAccessPair nap(name, acc); + return (mSlotMap.find(nap) != mSlotMap.end()); + } + + virtual Reference *genReference(const String& name, Access acc, uint32 depth) + { + Slot *slot = getName(name, acc); + ASSERT(slot); + if (slot->mAccessor) + return new MethodReference(slot->mIndex); + + return new FieldReference(slot->mIndex, acc); + } + + + JSObject *mSuperType; + + uint32 mVariableCount; + JSType *mStatics; // or null if this is the static component + + SlotMap mSlotMap; // maps & to slot + MethodList mMethods; + + void printSlotsNStuff(Formatter& f) const + { + f << "var. count = " << mVariableCount << "\n"; + f << "method count = " << (uint32)(mMethods.size()) << "\n"; + + for (SlotMap::const_iterator i = mSlotMap.begin(), end = mSlotMap.end(); (i != end); i++) + { + f << SLOT_NAME(i) << " " + << SLOT_ACCESS(i) << " = " + << *SLOT(i); + } + } + + }; + Formatter& operator<<(Formatter& f, const JSType& obj); + + + + + + + + + + + + + class JSInstance : public JSObject { + public: + JSInstance(JSType *type) : JSObject(type), mInstanceValues(NULL) + { + if (mType->mVariableCount) + mInstanceValues = new JSValue[mType->mVariableCount]; + } + + JSValue *mInstanceValues; + }; + + inline JSObject *JSType::newInstance() + { + return new JSInstance(this); + } + + + + + + + + + class Activation : public JSType { + public: + Reference *genReference(const String& name, Access acc, uint32 depth) + { + Slot *slot = getName(name, acc); + ASSERT(slot); + if (slot->mAccessor) + return new AccessorReference(slot->mAccessor); + + if (depth) + return new ClosureVarReference(depth, slot->mIndex, acc); + + return new LocalVarReference(slot->mIndex, acc); + } + }; + + + + + + + + + class ScopeChain { + public: + + std::vector mScopeStack; + typedef std::vector::reverse_iterator ScopeScanner; + + + void addScope(JSType *s) + { + mScopeStack.push_back(s); + } + + void popScope() + { + mScopeStack.pop_back(); + } + + void defineVariable(const String& name, + JSType *type, + JSFunction *defaultGetter, + JSFunction *defaultSetter) + { + JSType *top = mScopeStack.back(); + top->defineVariable(name, type, defaultGetter, defaultSetter); + } + + Reference *getName(const String& name, Access acc) + { + uint32 depth = 0; + for (ScopeScanner s = mScopeStack.rbegin(), end = mScopeStack.rend(); (s != end); s++, depth++) + { + if ((*s)->hasName(name, acc)) { + return (*s)->genReference(name, acc, depth); + } + } + return new NameReference(name, acc); + } + + + }; + + + + + + + + class Context { + public: + + Context(JSObject *global, World &world) + : mGlobal(global), + mWorld(world), + VirtualKeyWord(mWorld.identifiers["virtual"]), + ConstructorKeyWord(mWorld.identifiers["constructor"]), + OperatorKeyWord(mWorld.identifiers["operator"]) + { + } + + void defineOperator(Operator op, JSType *t1, JSType *t2, JSFunction *imp) + { + } + bool executeOperator(Operator op, JSType *t1, JSType *t2); + + JSObject *mGlobal; + World &mWorld; + + StringAtom& VirtualKeyWord; + StringAtom& ConstructorKeyWord; + StringAtom& OperatorKeyWord; + + + JSObject *getGlobalObject() { return mGlobal; } + World &getWorld() { return mWorld; } + + + void buildRuntime(StmtNode *p); + void buildRuntimeForStmt(StmtNode *p); + + + ByteCodeModule *genCode(StmtNode *p, String sourceName); + JSValue interpret(ByteCodeModule *bcm, JSValueList args); + + + // the default accessors used to access instance (& static) variables & methods + static JSFunction *defaultGetter; + static JSFunction *defaultSetter; + static JSFunction *methodGetter; + + + /* utility routines */ + + // Extract the operator from the string literal function name + // - requires the paramter count in order to distinguish + // between unary and binary operators. + Operator getOperator(uint32 parameterCount, String &name); + + // Get the type of the nth parameter. + JSType *getParameterType(FunctionDefinition &function, int index); + + // Get the number of parameters. + uint32 getParameterCount(FunctionDefinition &function); + + // Lookup a name as a type in the global object + JSType *findType(const StringAtom& typeName); + + // Get a type from an ExprNode + JSType *extractType(ExprNode *t); + + + + + + }; + +} +} + +#endif //js2runtime_h___ \ No newline at end of file diff --git a/mozilla/js2/src/numerics.cpp b/mozilla/js2/src/numerics.cpp index 0495072a43c..de5d079e798 100644 --- a/mozilla/js2/src/numerics.cpp +++ b/mozilla/js2/src/numerics.cpp @@ -35,11 +35,12 @@ #include #include #include "numerics.h" -#include "jstypes.h" +#include "parser.h" +#include "js2runtime.h" namespace JavaScript { - using namespace JSTypes; + using namespace JS2Runtime; // // Portable double-precision floating point to string and back conversions @@ -243,15 +244,15 @@ namespace JavaScript // had to move these here since they depend upon the values // initialized above, and we can't guarantee order other than // lexically in a single file. - const JSValue JSTypes::kUndefinedValue; - const JSValue JSTypes::kNaNValue = JSValue(nan); - const JSValue JSTypes::kTrueValue = JSValue(true); - const JSValue JSTypes::kFalseValue = JSValue(false); - const JSValue JSTypes::kNullValue = JSValue(JSValue::null_tag); - const JSValue JSTypes::kNegativeZero = JSValue(-0.0); - const JSValue JSTypes::kPositiveZero = JSValue(0.0); - const JSValue JSTypes::kNegativeInfinity = JSValue(negativeInfinity); - const JSValue JSTypes::kPositiveInfinity = JSValue(positiveInfinity); + const JSValue JS2Runtime::kUndefinedValue; + const JSValue JS2Runtime::kNaNValue = JSValue(nan); + const JSValue JS2Runtime::kTrueValue = JSValue(true); + const JSValue JS2Runtime::kFalseValue = JSValue(false); + const JSValue JS2Runtime::kNullValue = JSValue(JSValue::null_tag); + const JSValue JS2Runtime::kNegativeZero = JSValue(-0.0); + const JSValue JS2Runtime::kPositiveZero = JSValue(0.0); + const JSValue JS2Runtime::kNegativeInfinity = JSValue(negativeInfinity); + const JSValue JS2Runtime::kPositiveInfinity = JSValue(positiveInfinity); // // Portable double-precision floating point to string and back conversions diff --git a/mozilla/js2/src/winbuild/dikdik.dsp b/mozilla/js2/src/winbuild/dikdik.dsp new file mode 100644 index 00000000000..87c5decf8f9 --- /dev/null +++ b/mozilla/js2/src/winbuild/dikdik.dsp @@ -0,0 +1,224 @@ +# Microsoft Developer Studio Project File - Name="DikDik" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=DikDik - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "DikDik.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "DikDik.mak" CFG="DikDik - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DikDik - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "DikDik - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "DikDik - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /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 +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "DikDik - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DikDik___Win32_Debug" +# PROP BASE Intermediate_Dir "DikDik___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DikDik___Win32_Debug" +# PROP Intermediate_Dir "DikDik___Win32_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /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 +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "DikDik - Win32 Release" +# Name "DikDik - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\bytecodegen.cpp +# End Source File +# Begin Source File + +SOURCE=..\exception.cpp +# End Source File +# Begin Source File + +SOURCE=..\formatter.cpp +# End Source File +# Begin Source File + +SOURCE=..\hash.cpp +# End Source File +# Begin Source File + +SOURCE=..\js2runtime.cpp +# End Source File +# Begin Source File + +SOURCE=..\lexer.cpp +# End Source File +# Begin Source File + +SOURCE=..\mem.cpp +# End Source File +# Begin Source File + +SOURCE=..\numerics.cpp +# End Source File +# Begin Source File + +SOURCE=..\parser.cpp +# End Source File +# Begin Source File + +SOURCE=..\reader.cpp +# End Source File +# Begin Source File + +SOURCE=..\strings.cpp +# End Source File +# Begin Source File + +SOURCE=..\token.cpp +# End Source File +# Begin Source File + +SOURCE=..\utilities.cpp +# End Source File +# Begin Source File + +SOURCE=..\world.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\algo.h +# End Source File +# Begin Source File + +SOURCE=..\bytecodegen.h +# End Source File +# Begin Source File + +SOURCE=..\ds.h +# End Source File +# Begin Source File + +SOURCE=..\exception.h +# End Source File +# Begin Source File + +SOURCE=..\formatter.h +# End Source File +# Begin Source File + +SOURCE=..\hash.h +# End Source File +# Begin Source File + +SOURCE=..\js2runtime.h +# End Source File +# Begin Source File + +SOURCE=..\lexer.h +# End Source File +# Begin Source File + +SOURCE=..\mem.h +# End Source File +# Begin Source File + +SOURCE=..\nodefactory.h +# End Source File +# Begin Source File + +SOURCE=..\numerics.h +# End Source File +# Begin Source File + +SOURCE=..\parser.h +# End Source File +# Begin Source File + +SOURCE=..\reader.h +# End Source File +# Begin Source File + +SOURCE=..\stlcfg.h +# End Source File +# Begin Source File + +SOURCE=..\strings.h +# End Source File +# Begin Source File + +SOURCE=..\systemtypes.h +# End Source File +# Begin Source File + +SOURCE=..\token.h +# End Source File +# Begin Source File + +SOURCE=..\utilities.h +# End Source File +# Begin Source File + +SOURCE=..\world.h +# End Source File +# End Group +# End Target +# End Project diff --git a/mozilla/js2/src/winbuild/dikdik.dsw b/mozilla/js2/src/winbuild/dikdik.dsw new file mode 100644 index 00000000000..05cf3e00233 --- /dev/null +++ b/mozilla/js2/src/winbuild/dikdik.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "DikDik"=.\DikDik.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "DikDik_shell"=.\DikDik_shell.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name DikDik + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mozilla/js2/tests/cpp/DikDik_Shell.cpp b/mozilla/js2/tests/cpp/DikDik_Shell.cpp new file mode 100644 index 00000000000..10df2e2dfb5 --- /dev/null +++ b/mozilla/js2/tests/cpp/DikDik_Shell.cpp @@ -0,0 +1,184 @@ +// -*- 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 oqr +// 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. + + +// +// JS2 shell. +// + +#ifdef _WIN32 + // Turn off warnings about identifiers too long in browser information + #pragma warning(disable: 4786) +#endif + + +#include +#include + +#include "world.h" +#include "reader.h" +#include "parser.h" +#include "js2runtime.h" +#include "bytecodegen.h" + +#if defined(XP_MAC) && !defined(XP_MAC_MPW) +#include +#include + +static char *mac_argv[] = {"js2", 0}; + +static void initConsole(StringPtr consoleName, + const char* startupMessage, + int &argc, char **&argv) +{ + SIOUXSettings.autocloseonquit = false; + SIOUXSettings.asktosaveonclose = false; + SIOUXSetTitle(consoleName); + + // Set up a buffer for stderr (otherwise it's a pig). + static char buffer[BUFSIZ]; + setvbuf(stderr, buffer, _IOLBF, BUFSIZ); + + JavaScript::stdOut << startupMessage; + + argc = 1; + argv = mac_argv; +} + +#endif + +namespace JavaScript { +namespace Shell { + +// using namespace JS2Runtime; + + +// Interactively read a line from the input stream in and put it into +// s. Return false if reached the end of input before reading anything. +static bool promptLine(LineReader &inReader, string &s, const char *prompt) +{ + if (prompt) { + stdOut << prompt; + #ifdef XP_MAC_MPW + // Print a CR after the prompt because MPW grabs the entire + // line when entering an interactive command. + stdOut << '\n'; + #endif + } + return inReader.readLine(s) != 0; +} + +World world; + +/* "filename" of the console */ +const String ConsoleName = widenCString(""); +const bool showTokens = false; + +#define INTERPRET_INPUT 0 + +static void readEvalPrint(FILE *in, World &world) +{ + String buffer; + string line; + LineReader inReader(in); + + JSObject globalObject; + Context cx(&globalObject, world); + + while (promptLine(inReader, line, buffer.empty() ? "dd> " : "> ")) { + appendChars(buffer, line.data(), line.size()); + try { + Arena a; + Parser p(world, a, buffer, ConsoleName); + + if (showTokens) { + Lexer &l = p.lexer; + while (true) { + const Token &t = l.get(true); + if (t.hasKind(Token::end)) + break; + stdOut << ' '; + t.print(stdOut, true); + } + stdOut << '\n'; + } else { + StmtNode *parsedStatements = p.parseProgram(); + ASSERT(p.lexer.peek(true).hasKind(Token::end)); + { + PrettyPrinter f(stdOut, 30); + { + PrettyPrinter::Block b(f, 2); + f << "Program ="; + f.linearBreak(1); + StmtNode::printStatements(f, parsedStatements); + } + f.end(); + } + stdOut << '\n'; +#ifdef INTERPRET_INPUT + // Generate code for parsedStatements, which is a linked + // list of zero or more statements + cx.buildRuntime(parsedStatements); + stdOut << globalObject; + JS2Runtime::ByteCodeModule* bcm = cx.genCode(parsedStatements, ConsoleName); + if (bcm) { +#ifdef SHOW_ICODE + stdOut << *bcm; +#endif + JSValue result = cx.interpret(bcm, JSValueList()); + stdOut << "result = " << result << "\n"; + delete bcm; + } +#endif + } + clear(buffer); + } catch (Exception &e) { + /* If we got a syntax error on the end of input, + * then wait for a continuation + * of input rather than printing the error message. */ + if (!(e.hasKind(Exception::syntaxError) && + e.lineNum && e.pos == buffer.size() && + e.sourceFile == ConsoleName)) { + stdOut << '\n' << e.fullMessage(); + clear(buffer); + } + } + } + stdOut << '\n'; +} + +} /* namespace Shell */ +} /* namespace JavaScript */ + + +#if defined(XP_MAC) && !defined(XP_MAC_MPW) +int main(int argc, char **argv) +{ + initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv); +#else +int main(int , char **) +{ +#endif + + using namespace JavaScript; + using namespace Shell; + + readEvalPrint(stdin, world); + return 0; +} diff --git a/mozilla/js2/tests/cpp/winbuild/DikDik_shell.dsp b/mozilla/js2/tests/cpp/winbuild/DikDik_shell.dsp new file mode 100644 index 00000000000..fb267bfc418 --- /dev/null +++ b/mozilla/js2/tests/cpp/winbuild/DikDik_shell.dsp @@ -0,0 +1,115 @@ +# Microsoft Developer Studio Project File - Name="DikDik_shell" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=DikDik_shell - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "DikDik_shell.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "DikDik_shell.mak" CFG="DikDik_shell - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "DikDik_shell - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "DikDik_shell - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "DikDik_shell - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# 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 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 + +!ELSEIF "$(CFG)" == "DikDik_shell - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DikDik_shell___Win32_Debug" +# PROP BASE Intermediate_Dir "DikDik_shell___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DikDik_shell___Win32_Debug" +# PROP Intermediate_Dir "DikDik_shell___Win32_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 /I "../../src" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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 + +!ENDIF + +# Begin Target + +# Name "DikDik_shell - Win32 Release" +# Name "DikDik_shell - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\DikDik_Shell.cpp + +!IF "$(CFG)" == "DikDik_shell - Win32 Release" + +!ELSEIF "$(CFG)" == "DikDik_shell - Win32 Debug" + +# ADD CPP /I "../../../src" +# SUBTRACT CPP /I "../../src" + +!ENDIF + +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\..\src\winbuild\DikDik___Win32_Debug\DikDik.lib +# End Source File +# End Target +# End Project