Fixes and enhancements to get class references, constructors and scripts
working from .xml input.
This commit is contained in:
Родитель
46e1348f16
Коммит
5ef03957d6
|
@ -1,51 +0,0 @@
|
|||
/* -*- 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.
|
||||
*/
|
||||
|
||||
#include "exception.h"
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
extern const char* exception_types[];
|
||||
extern const char* exception_msgs[];
|
||||
|
||||
void
|
||||
JSException::toString8 (string8 &rval)
|
||||
{
|
||||
rval = *exception_types[mType] + " Exception: " +
|
||||
*exception_msgs[mID];
|
||||
if (mSource.size() != 0)
|
||||
rval += " in " + mSource;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
/* -*- 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 exception_h___
|
||||
#define exception_h___
|
||||
#include "utilities.h"
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
enum ExceptionType {
|
||||
etUnknown = 0,
|
||||
etLexer,
|
||||
etParser,
|
||||
etRuntime,
|
||||
etCount
|
||||
};
|
||||
|
||||
enum ExceptionID {
|
||||
eidExpectBool = 0,
|
||||
eidExpectDouble,
|
||||
eidExpectInt32,
|
||||
eidExpectUInt32,
|
||||
eidExpectRegister,
|
||||
eidExpectArgList,
|
||||
eidExpectColon,
|
||||
eidExpectCloseParen,
|
||||
eidExpectBinaryOp,
|
||||
eidExpectString,
|
||||
eidExpectLabel,
|
||||
eidExpectComma,
|
||||
eidExpectNewline,
|
||||
eidExpectIdentifier,
|
||||
eidDuplicateLabel,
|
||||
eidUnknownICode,
|
||||
eidUnknownBinaryOp,
|
||||
eidUnterminatedString,
|
||||
eidCount
|
||||
};
|
||||
|
||||
class JSException {
|
||||
public:
|
||||
JSException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0, ExceptionType type = etUnknown)
|
||||
: mID(ID), mType(type), mPos(pos), mSource(source) {}
|
||||
ExceptionID mID;
|
||||
ExceptionType mType;
|
||||
string8_citer mPos;
|
||||
string8 mSource;
|
||||
|
||||
public:
|
||||
void toString8(string8 &rval);
|
||||
/*
|
||||
private:
|
||||
JSException(const JSException&);
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
class JSLexException : public JSException {
|
||||
public:
|
||||
JSLexException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = "") :
|
||||
JSException(ID, pos, source, etLexer) {}
|
||||
/*
|
||||
private:
|
||||
JSLexException (const JSLexException&);
|
||||
*/
|
||||
};
|
||||
|
||||
class JSParseException : public JSException {
|
||||
public:
|
||||
JSParseException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0) :
|
||||
JSException(ID, pos, source, etParser) {}
|
||||
/*
|
||||
private:
|
||||
JSParseException (const JSParseException&);
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* exception_h___ */
|
||||
|
||||
|
|
@ -108,6 +108,7 @@ namespace ICodeASM {
|
|||
throw JSParseException (eidExpectArgList);
|
||||
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
StringFormatter s_fmt;
|
||||
while (tl.estimate == teString || tl.estimate == teAlpha) {
|
||||
string *argName = 0;
|
||||
|
||||
|
@ -143,6 +144,15 @@ namespace ICodeASM {
|
|||
sap = &(mCx->getWorld().identifiers[argName->c_str()]);
|
||||
delete argName;
|
||||
}
|
||||
else {
|
||||
/* if an argument name was not specified, use the position
|
||||
* to build a default name.
|
||||
*/
|
||||
s_fmt << (uint32)al->size();
|
||||
sap = &(mCx->getWorld().identifiers[s_fmt.getString()]);
|
||||
s_fmt.clear();
|
||||
|
||||
}
|
||||
VM::Argument arg = VM::Argument (tr, sap);
|
||||
|
||||
al->push_back(arg);
|
||||
|
@ -176,7 +186,7 @@ namespace ICodeASM {
|
|||
|
||||
for (int i = 0; keyword_exprNodeKinds[i] != 0; ++i)
|
||||
if (cmp_nocase (*str, keyword_exprNodeKinds[i], keyword_exprNodeKinds[i] +
|
||||
strlen (keyword_exprNodeKinds[i]) + 1) == 0) {
|
||||
strlen (keyword_exprNodeKinds[i])) == 0) {
|
||||
*rval = exprNodeOps[i];
|
||||
delete str;
|
||||
return end;
|
||||
|
@ -220,11 +230,28 @@ namespace ICodeASM {
|
|||
}
|
||||
|
||||
string8_citer
|
||||
ICodeParser::parseJSClassOperand (string8_citer /*begin*/,
|
||||
string8_citer end, string ** /*rval*/)
|
||||
ICodeParser::parseJSClassOperand (string8_citer begin,
|
||||
string8_citer end, JSTypes::JSType **rval)
|
||||
{
|
||||
NOT_REACHED ("JSClasses are hard, lets go shopping.");
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw JSParseException (eidExpectString);
|
||||
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
StringAtom &typename_atom = mCx->getWorld().identifiers[str->c_str()];
|
||||
delete str;
|
||||
JSTypes::JSValue jsv =
|
||||
mCx->getGlobalObject()->getVariable(typename_atom);
|
||||
if (jsv.isType())
|
||||
*rval = jsv.type;
|
||||
else
|
||||
*rval = &(JSTypes::Any_Type);
|
||||
|
||||
return end;
|
||||
// NOT_REACHED ("JSClasses are hard, lets go shopping.");
|
||||
// return end;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
|
@ -287,7 +314,7 @@ namespace ICodeASM {
|
|||
begin = lexAlpha (tl.begin, end, &str);
|
||||
|
||||
if (cmp_nocase(*str, keyword_offset, keyword_offset +
|
||||
strlen(keyword_offset) + 1) == 0) {
|
||||
strlen(keyword_offset)) == 0) {
|
||||
delete str;
|
||||
/* got the "Offset" keyword, treat next thing as a jump offset
|
||||
* expressed as "Offset +/-N" */
|
||||
|
@ -391,7 +418,7 @@ namespace ICodeASM {
|
|||
CASE_TYPE(Bool, bool, static_cast);
|
||||
CASE_TYPE(Double, double, static_cast);
|
||||
CASE_TYPE(ICodeModule, string *, reinterpret_cast);
|
||||
CASE_TYPE(JSClass, string *, reinterpret_cast);
|
||||
CASE_TYPE(JSClass, JSTypes::JSType *, reinterpret_cast);
|
||||
CASE_TYPE(JSString, JSTypes::JSString *, reinterpret_cast);
|
||||
CASE_TYPE(JSFunction, string *, reinterpret_cast);
|
||||
CASE_TYPE(JSType, JSTypes::JSType *, reinterpret_cast);
|
||||
|
@ -491,7 +518,7 @@ namespace ICodeASM {
|
|||
for (uint i = 0; i < icodemap_size; ++i)
|
||||
if (cmp_nocase(icode_str, &icodemap[i].name[0],
|
||||
&icodemap[i].name[0] +
|
||||
strlen(icodemap[i].name) + 1) == 0)
|
||||
strlen(icodemap[i].name)) == 0)
|
||||
/* if match found, parse it's operands */
|
||||
return parseInstruction (i, firstTokenEnd, end);
|
||||
/* otherwise, choke on it */
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace ICodeASM {
|
|||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSClassOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
JSTypes::JSType **rval);
|
||||
string8_citer
|
||||
parseJSStringOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSString **rval);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "icodegenerator.h"
|
||||
#include "interpreter.h"
|
||||
#include "xmlparser.h"
|
||||
#include "exception.h"
|
||||
#include "icodeasm.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
@ -2552,8 +2553,10 @@ Formatter& operator<<(Formatter &f, string &s)
|
|||
}
|
||||
|
||||
|
||||
void ICodeGenerator::readICode(const char *fileName)
|
||||
ICodeModule *ICodeGenerator::readICode(const char *fileName)
|
||||
{
|
||||
ICodeModule *result = NULL;
|
||||
|
||||
XMLParser xp(fileName);
|
||||
XMLNode *top = xp.parseDocument();
|
||||
stdOut << *top;
|
||||
|
@ -2582,12 +2585,13 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
|
||||
mContext->getGlobalObject()->defineVariable(className, &Type_Type, JSValue(thisClass));
|
||||
|
||||
bool hasDefaultConstructor = false;
|
||||
// bool hasDefaultConstructor = false;
|
||||
XMLNodeList &elements = node->children();
|
||||
for (XMLNodeList::const_iterator j = elements.begin(); j != elements.end(); j++) {
|
||||
XMLNode *element = *j;
|
||||
bool isConstructor = (element->name().compare(widenCString("constructor")) == 0);
|
||||
|
||||
if (element->name().compare(widenCString("method")) == 0) {
|
||||
if (isConstructor || (element->name().compare(widenCString("method")) == 0)) {
|
||||
String methodName, resultTypeName;
|
||||
element->getValue(widenCString("name"), methodName);
|
||||
element->getValue(widenCString("type"), resultTypeName);
|
||||
|
@ -2631,7 +2635,12 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
NULL, /* InstructionMap *instructionMap */
|
||||
resultType,
|
||||
NotABanana); /* exception register */
|
||||
thisClass->defineMethod(methodName, new JSFunction(icm));
|
||||
if (isConstructor) {
|
||||
thisClass->defineConstructor(methodName);
|
||||
scg.setStatic(thisClass, mContext->getWorld().identifiers[methodName], scg.newFunction(icm));
|
||||
}
|
||||
else
|
||||
thisClass->defineMethod(methodName, new JSFunction(icm));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -2651,7 +2660,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
}
|
||||
}
|
||||
scg.setStatic(thisClass, mInitName, scg.newFunction(ccg.complete(&Void_Type)));
|
||||
|
||||
/*
|
||||
if (!hasDefaultConstructor) {
|
||||
TypedRegister thisValue = TypedRegister(0, thisClass);
|
||||
ArgumentList *args = new ArgumentList(0);
|
||||
|
@ -2665,6 +2674,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
thisClass->defineConstructor(className);
|
||||
scg.setStatic(thisClass, mContext->getWorld().identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
|
||||
}
|
||||
*/
|
||||
thisClass->complete();
|
||||
|
||||
if (scg.getICode()->size()) {
|
||||
|
@ -2676,7 +2686,24 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("script")) == 0) {
|
||||
// build an icode module and execute it
|
||||
String &body = node->body();
|
||||
if (body.length()) {
|
||||
std::string str(body.length(), char());
|
||||
std::transform(body.begin(), body.end(), str.begin(), narrow);
|
||||
ICodeParser icp(mContext);
|
||||
|
||||
stdOut << "(script) Calling ICodeParser with :\n" << str << "\n";
|
||||
|
||||
icp.parseSourceFromString(str);
|
||||
|
||||
result = new ICodeModule(icp.mInstructions,
|
||||
NULL, /* VariableList *variables */
|
||||
NULL, /* ParameterList *parameters */
|
||||
icp.mMaxRegister,
|
||||
NULL, /* InstructionMap *instructionMap */
|
||||
&Void_Type,
|
||||
NotABanana); /* exception register */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("instance")) == 0) {
|
||||
|
@ -2691,7 +2718,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ namespace ICG {
|
|||
}
|
||||
|
||||
ICodeModule *complete(JSType *resultType);
|
||||
void readICode(const char *fileName);
|
||||
ICodeModule *readICode(const char *fileName);
|
||||
|
||||
JSType *extractType(ExprNode *t);
|
||||
JSType *getParameterType(FunctionDefinition &function, int index);
|
||||
|
|
|
@ -162,10 +162,10 @@ ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
|
|||
return icm;
|
||||
}
|
||||
|
||||
void Context::loadClass(const char *fileName)
|
||||
ICodeModule* Context::loadClass(const char *fileName)
|
||||
{
|
||||
ICodeGenerator icg(this);
|
||||
icg.readICode(fileName); // loads it into the global object
|
||||
return icg.readICode(fileName); // loads it into the global object
|
||||
}
|
||||
|
||||
JSValues& Context::getRegisters() { return mActivation->mRegisters; }
|
||||
|
@ -604,96 +604,99 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
else {
|
||||
ICodeModule *icm = target->getICode();
|
||||
ArgumentList *args = op3(call);
|
||||
ArgumentList *callArgs = NULL;
|
||||
|
||||
// if all the parameters are positional
|
||||
// if (icm->itsParameters->mPositionalCount == icm->itsParameters->size())
|
||||
if (icm->itsParameters) {
|
||||
|
||||
// the parameter count includes 'this' and any named rest parameter
|
||||
//
|
||||
uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array
|
||||
// callArgs will be the actual args passed to the target, put into correct register order.
|
||||
// It has room for the rest parameter.
|
||||
ArgumentList *callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
// if all the parameters are positional
|
||||
// if (icm->itsParameters->mPositionalCount == icm->itsParameters->size())
|
||||
|
||||
// don't want to count the rest parameter while processing the others
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::NoRestParameter) pCount--;
|
||||
// the parameter count includes 'this' and any named rest parameter
|
||||
//
|
||||
uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array
|
||||
// callArgs will be the actual args passed to the target, put into correct register order.
|
||||
// It has room for the rest parameter.
|
||||
callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
|
||||
// don't want to count the rest parameter while processing the others
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::NoRestParameter) pCount--;
|
||||
|
||||
|
||||
uint32 i;
|
||||
JSArray *restArg = NULL;
|
||||
uint32 i;
|
||||
JSArray *restArg = NULL;
|
||||
|
||||
// first match all named arguments with their intended target locations
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
// first match all named arguments with their intended target locations
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
|
||||
const StringAtom *argName = (*args)[i].second;
|
||||
const StringAtom *argName = (*args)[i].second;
|
||||
|
||||
TypedRegister parameter = icm->itsParameters->findVariable(*argName);
|
||||
if (parameter.first == NotARegister) {
|
||||
// arg name doesn't match any parameter name, it's a candidate
|
||||
// for the rest parameter (if there is one)
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::NoRestParameter)
|
||||
throw new JSException("Named argument doesn't match parameter name in call with no rest parameter");
|
||||
else {
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::HasUnnamedRestParameter) {
|
||||
// if the name is a numeric literal >= 0, use it as an array index
|
||||
// otherwise just set the named property.
|
||||
const char16 *c = argName->data();
|
||||
const char16 *end;
|
||||
double d = stringToDouble(c, c + argName->size(), end);
|
||||
int index = -1;
|
||||
TypedRegister parameter = icm->itsParameters->findVariable(*argName);
|
||||
if (parameter.first == NotARegister) {
|
||||
// arg name doesn't match any parameter name, it's a candidate
|
||||
// for the rest parameter (if there is one)
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::NoRestParameter)
|
||||
throw new JSException("Named argument doesn't match parameter name in call with no rest parameter");
|
||||
else {
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::HasUnnamedRestParameter) {
|
||||
// if the name is a numeric literal >= 0, use it as an array index
|
||||
// otherwise just set the named property.
|
||||
const char16 *c = argName->data();
|
||||
const char16 *end;
|
||||
double d = stringToDouble(c, c + argName->size(), end);
|
||||
int index = -1;
|
||||
|
||||
if ((d != d) || (d < 0) || (d != (int)d)) { // a non-numeric or negative value
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::HasRestParameterBeforeBar)
|
||||
throw new JSException("Non-numeric or negative argument name for positional rest parameter");
|
||||
}
|
||||
else { // shift the index value down by the number of positional parameters
|
||||
index = (int)d;
|
||||
index -= icm->itsParameters->mPositionalCount;
|
||||
}
|
||||
if ((d != d) || (d < 0) || (d != (int)d)) { // a non-numeric or negative value
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::HasRestParameterBeforeBar)
|
||||
throw new JSException("Non-numeric or negative argument name for positional rest parameter");
|
||||
}
|
||||
else { // shift the index value down by the number of positional parameters
|
||||
index = (int)d;
|
||||
index -= icm->itsParameters->mPositionalCount;
|
||||
}
|
||||
|
||||
TypedRegister argument = (*args)[i].first; // this is the argument whose name didn't match
|
||||
TypedRegister argument = (*args)[i].first; // this is the argument whose name didn't match
|
||||
|
||||
if (restArg == NULL) {
|
||||
// allocate the rest argument and then subvert the register being used for the
|
||||
// argument under consideration to hold the newly created rest argument.
|
||||
restArg = new JSArray();
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
(*registers)[argument.first] = restArg;
|
||||
// The callArgs for the rest parameter position gets loaded from that slot
|
||||
(*callArgs)[pCount] = Argument(TypedRegister(argument.first, &Array_Type), NULL);
|
||||
}
|
||||
else {
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
if (restArg == NULL) {
|
||||
// allocate the rest argument and then subvert the register being used for the
|
||||
// argument under consideration to hold the newly created rest argument.
|
||||
restArg = new JSArray();
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
(*registers)[argument.first] = restArg;
|
||||
// The callArgs for the rest parameter position gets loaded from that slot
|
||||
(*callArgs)[pCount] = Argument(TypedRegister(argument.first, &Array_Type), NULL);
|
||||
}
|
||||
else {
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
}
|
||||
}
|
||||
// else just throw it away
|
||||
}
|
||||
// else just throw it away
|
||||
}
|
||||
else {
|
||||
uint32 targetIndex = parameter.first - 1; // this is the register number we're targetting
|
||||
TypedRegister targetParameter = (*callArgs)[targetIndex].first;
|
||||
if (targetParameter.first != NotARegister) // uh oh, some other argument wants this parameter
|
||||
throw new JSException("Two (or more) arguments have the same name");
|
||||
(*callArgs)[targetIndex] = (*args)[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32 targetIndex = parameter.first - 1; // this is the register number we're targetting
|
||||
TypedRegister targetParameter = (*callArgs)[targetIndex].first;
|
||||
if (targetParameter.first != NotARegister) // uh oh, some other argument wants this parameter
|
||||
throw new JSException("Two (or more) arguments have the same name");
|
||||
(*callArgs)[targetIndex] = (*args)[i];
|
||||
|
||||
|
||||
// make sure that all non-optional parameters have values
|
||||
for (i = 0; i < pCount; i++) {
|
||||
TypedRegister parameter = (*callArgs)[i].first;
|
||||
if (parameter.first == NotARegister) { // doesn't have an assigned argument
|
||||
if (!icm->itsParameters->isOptional(i + 1)) // and parameter (allowing for 'this') doesn't have an optional value
|
||||
throw new JSException("No argument supplied for non-optional parameter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// make sure that all non-optional parameters have values
|
||||
for (i = 0; i < pCount; i++) {
|
||||
TypedRegister parameter = (*callArgs)[i].first;
|
||||
if (parameter.first == NotARegister) { // doesn't have an assigned argument
|
||||
if (!icm->itsParameters->isOptional(i + 1)) // and parameter (allowing for 'this') doesn't have an optional value
|
||||
throw new JSException("No argument supplied for non-optional parameter");
|
||||
}
|
||||
}
|
||||
|
||||
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, op1(call), mICode, mCurrentClosure);
|
||||
mICode = icm;
|
||||
mActivation = new Activation(mICode->itsMaxRegister, mActivation, target->getThis(), callArgs);
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace Interpreter {
|
|||
ICodeModule* genCode(StmtNode *p, const String &fileName);
|
||||
JSValue readEvalFile(FILE* in, const String& fileName);
|
||||
|
||||
void loadClass(const char *fileName);
|
||||
ICodeModule* loadClass(const char *fileName);
|
||||
|
||||
const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, ExprNode::Kind op);
|
||||
|
||||
|
@ -142,14 +142,16 @@ namespace Interpreter {
|
|||
// copy caller's parameter list to initial registers.
|
||||
JSValues::iterator dest = mRegisters.begin();
|
||||
*dest++ = thisArg;
|
||||
const JSValues& params = caller->mRegisters;
|
||||
for (ArgumentList::const_iterator src = list->begin(),
|
||||
end = list->end(); src != end; ++src, ++dest) {
|
||||
Register r = (*src).first.first;
|
||||
if (r != NotARegister)
|
||||
*dest = params[r];
|
||||
else
|
||||
*dest = JSValue(JSValue::uninitialized_tag);
|
||||
if (list) {
|
||||
const JSValues& params = caller->mRegisters;
|
||||
for (ArgumentList::const_iterator src = list->begin(),
|
||||
end = list->end(); src != end; ++src, ++dest) {
|
||||
Register r = (*src).first.first;
|
||||
if (r != NotARegister)
|
||||
*dest = params[r];
|
||||
else
|
||||
*dest = JSValue(JSValue::uninitialized_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,9 @@ static JSValue loadxml(Context *cx, const JSValues &argv)
|
|||
JSString& fileName = *val.string;
|
||||
std::string str(fileName.length(), char());
|
||||
std::transform(fileName.begin(), fileName.end(), str.begin(), narrow);
|
||||
cx->loadClass(str.c_str());
|
||||
ICodeModule *icm = cx->loadClass(str.c_str());
|
||||
if (icm)
|
||||
result = JSValue(new JSFunction(icm));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,8 +41,8 @@ namespace JavaScript {
|
|||
void
|
||||
JSException::toString8 (string8 &rval)
|
||||
{
|
||||
rval = *exception_types[mType] + " Exception: " +
|
||||
*exception_msgs[mID];
|
||||
rval = string8(exception_types[mType]) + " Exception: " +
|
||||
string8(exception_msgs[mID]);
|
||||
if (mSource.size() != 0)
|
||||
rval += " in " + mSource;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace JavaScript {
|
|||
class JSException {
|
||||
public:
|
||||
JSException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0, ExceptionType type = etUnknown)
|
||||
string8 source = "", ExceptionType type = etUnknown)
|
||||
: mID(ID), mType(type), mPos(pos), mSource(source) {}
|
||||
ExceptionID mID;
|
||||
ExceptionType mType;
|
||||
|
@ -100,7 +100,7 @@ namespace JavaScript {
|
|||
class JSParseException : public JSException {
|
||||
public:
|
||||
JSParseException (ExceptionID ID, string8_citer pos = 0,
|
||||
string8 source = 0) :
|
||||
string8 source = "") :
|
||||
JSException(ID, pos, source, etParser) {}
|
||||
/*
|
||||
private:
|
||||
|
|
|
@ -108,6 +108,7 @@ namespace ICodeASM {
|
|||
throw JSParseException (eidExpectArgList);
|
||||
|
||||
tl = seekTokenStart (tl.begin + 1, end);
|
||||
StringFormatter s_fmt;
|
||||
while (tl.estimate == teString || tl.estimate == teAlpha) {
|
||||
string *argName = 0;
|
||||
|
||||
|
@ -143,6 +144,15 @@ namespace ICodeASM {
|
|||
sap = &(mCx->getWorld().identifiers[argName->c_str()]);
|
||||
delete argName;
|
||||
}
|
||||
else {
|
||||
/* if an argument name was not specified, use the position
|
||||
* to build a default name.
|
||||
*/
|
||||
s_fmt << (uint32)al->size();
|
||||
sap = &(mCx->getWorld().identifiers[s_fmt.getString()]);
|
||||
s_fmt.clear();
|
||||
|
||||
}
|
||||
VM::Argument arg = VM::Argument (tr, sap);
|
||||
|
||||
al->push_back(arg);
|
||||
|
@ -176,7 +186,7 @@ namespace ICodeASM {
|
|||
|
||||
for (int i = 0; keyword_exprNodeKinds[i] != 0; ++i)
|
||||
if (cmp_nocase (*str, keyword_exprNodeKinds[i], keyword_exprNodeKinds[i] +
|
||||
strlen (keyword_exprNodeKinds[i]) + 1) == 0) {
|
||||
strlen (keyword_exprNodeKinds[i])) == 0) {
|
||||
*rval = exprNodeOps[i];
|
||||
delete str;
|
||||
return end;
|
||||
|
@ -220,11 +230,28 @@ namespace ICodeASM {
|
|||
}
|
||||
|
||||
string8_citer
|
||||
ICodeParser::parseJSClassOperand (string8_citer /*begin*/,
|
||||
string8_citer end, string ** /*rval*/)
|
||||
ICodeParser::parseJSClassOperand (string8_citer begin,
|
||||
string8_citer end, JSTypes::JSType **rval)
|
||||
{
|
||||
NOT_REACHED ("JSClasses are hard, lets go shopping.");
|
||||
TokenLocation tl = seekTokenStart (begin, end);
|
||||
|
||||
if (tl.estimate != teString)
|
||||
throw JSParseException (eidExpectString);
|
||||
|
||||
string8 *str;
|
||||
end = lexString8 (tl.begin, end, &str);
|
||||
StringAtom &typename_atom = mCx->getWorld().identifiers[str->c_str()];
|
||||
delete str;
|
||||
JSTypes::JSValue jsv =
|
||||
mCx->getGlobalObject()->getVariable(typename_atom);
|
||||
if (jsv.isType())
|
||||
*rval = jsv.type;
|
||||
else
|
||||
*rval = &(JSTypes::Any_Type);
|
||||
|
||||
return end;
|
||||
// NOT_REACHED ("JSClasses are hard, lets go shopping.");
|
||||
// return end;
|
||||
}
|
||||
|
||||
string8_citer
|
||||
|
@ -287,7 +314,7 @@ namespace ICodeASM {
|
|||
begin = lexAlpha (tl.begin, end, &str);
|
||||
|
||||
if (cmp_nocase(*str, keyword_offset, keyword_offset +
|
||||
strlen(keyword_offset) + 1) == 0) {
|
||||
strlen(keyword_offset)) == 0) {
|
||||
delete str;
|
||||
/* got the "Offset" keyword, treat next thing as a jump offset
|
||||
* expressed as "Offset +/-N" */
|
||||
|
@ -391,7 +418,7 @@ namespace ICodeASM {
|
|||
CASE_TYPE(Bool, bool, static_cast);
|
||||
CASE_TYPE(Double, double, static_cast);
|
||||
CASE_TYPE(ICodeModule, string *, reinterpret_cast);
|
||||
CASE_TYPE(JSClass, string *, reinterpret_cast);
|
||||
CASE_TYPE(JSClass, JSTypes::JSType *, reinterpret_cast);
|
||||
CASE_TYPE(JSString, JSTypes::JSString *, reinterpret_cast);
|
||||
CASE_TYPE(JSFunction, string *, reinterpret_cast);
|
||||
CASE_TYPE(JSType, JSTypes::JSType *, reinterpret_cast);
|
||||
|
@ -491,7 +518,7 @@ namespace ICodeASM {
|
|||
for (uint i = 0; i < icodemap_size; ++i)
|
||||
if (cmp_nocase(icode_str, &icodemap[i].name[0],
|
||||
&icodemap[i].name[0] +
|
||||
strlen(icodemap[i].name) + 1) == 0)
|
||||
strlen(icodemap[i].name)) == 0)
|
||||
/* if match found, parse it's operands */
|
||||
return parseInstruction (i, firstTokenEnd, end);
|
||||
/* otherwise, choke on it */
|
||||
|
|
|
@ -121,7 +121,7 @@ namespace ICodeASM {
|
|||
string8 **rval);
|
||||
string8_citer
|
||||
parseJSClassOperand (string8_citer begin, string8_citer end,
|
||||
string8 **rval);
|
||||
JSTypes::JSType **rval);
|
||||
string8_citer
|
||||
parseJSStringOperand (string8_citer begin, string8_citer end,
|
||||
JSTypes::JSString **rval);
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "icodegenerator.h"
|
||||
#include "interpreter.h"
|
||||
#include "xmlparser.h"
|
||||
#include "exception.h"
|
||||
#include "icodeasm.h"
|
||||
|
||||
#include <stdexcept>
|
||||
|
@ -2552,8 +2553,10 @@ Formatter& operator<<(Formatter &f, string &s)
|
|||
}
|
||||
|
||||
|
||||
void ICodeGenerator::readICode(const char *fileName)
|
||||
ICodeModule *ICodeGenerator::readICode(const char *fileName)
|
||||
{
|
||||
ICodeModule *result = NULL;
|
||||
|
||||
XMLParser xp(fileName);
|
||||
XMLNode *top = xp.parseDocument();
|
||||
stdOut << *top;
|
||||
|
@ -2582,12 +2585,13 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
|
||||
mContext->getGlobalObject()->defineVariable(className, &Type_Type, JSValue(thisClass));
|
||||
|
||||
bool hasDefaultConstructor = false;
|
||||
// bool hasDefaultConstructor = false;
|
||||
XMLNodeList &elements = node->children();
|
||||
for (XMLNodeList::const_iterator j = elements.begin(); j != elements.end(); j++) {
|
||||
XMLNode *element = *j;
|
||||
bool isConstructor = (element->name().compare(widenCString("constructor")) == 0);
|
||||
|
||||
if (element->name().compare(widenCString("method")) == 0) {
|
||||
if (isConstructor || (element->name().compare(widenCString("method")) == 0)) {
|
||||
String methodName, resultTypeName;
|
||||
element->getValue(widenCString("name"), methodName);
|
||||
element->getValue(widenCString("type"), resultTypeName);
|
||||
|
@ -2631,7 +2635,12 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
NULL, /* InstructionMap *instructionMap */
|
||||
resultType,
|
||||
NotABanana); /* exception register */
|
||||
thisClass->defineMethod(methodName, new JSFunction(icm));
|
||||
if (isConstructor) {
|
||||
thisClass->defineConstructor(methodName);
|
||||
scg.setStatic(thisClass, mContext->getWorld().identifiers[methodName], scg.newFunction(icm));
|
||||
}
|
||||
else
|
||||
thisClass->defineMethod(methodName, new JSFunction(icm));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -2651,7 +2660,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
}
|
||||
}
|
||||
scg.setStatic(thisClass, mInitName, scg.newFunction(ccg.complete(&Void_Type)));
|
||||
|
||||
/*
|
||||
if (!hasDefaultConstructor) {
|
||||
TypedRegister thisValue = TypedRegister(0, thisClass);
|
||||
ArgumentList *args = new ArgumentList(0);
|
||||
|
@ -2665,6 +2674,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
thisClass->defineConstructor(className);
|
||||
scg.setStatic(thisClass, mContext->getWorld().identifiers[className], scg.newFunction(icg.complete(&Void_Type)));
|
||||
}
|
||||
*/
|
||||
thisClass->complete();
|
||||
|
||||
if (scg.getICode()->size()) {
|
||||
|
@ -2676,7 +2686,24 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("script")) == 0) {
|
||||
// build an icode module and execute it
|
||||
String &body = node->body();
|
||||
if (body.length()) {
|
||||
std::string str(body.length(), char());
|
||||
std::transform(body.begin(), body.end(), str.begin(), narrow);
|
||||
ICodeParser icp(mContext);
|
||||
|
||||
stdOut << "(script) Calling ICodeParser with :\n" << str << "\n";
|
||||
|
||||
icp.parseSourceFromString(str);
|
||||
|
||||
result = new ICodeModule(icp.mInstructions,
|
||||
NULL, /* VariableList *variables */
|
||||
NULL, /* ParameterList *parameters */
|
||||
icp.mMaxRegister,
|
||||
NULL, /* InstructionMap *instructionMap */
|
||||
&Void_Type,
|
||||
NotABanana); /* exception register */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node->name().compare(widenCString("instance")) == 0) {
|
||||
|
@ -2691,7 +2718,7 @@ void ICodeGenerator::readICode(const char *fileName)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -297,7 +297,7 @@ namespace ICG {
|
|||
}
|
||||
|
||||
ICodeModule *complete(JSType *resultType);
|
||||
void readICode(const char *fileName);
|
||||
ICodeModule *readICode(const char *fileName);
|
||||
|
||||
JSType *extractType(ExprNode *t);
|
||||
JSType *getParameterType(FunctionDefinition &function, int index);
|
||||
|
|
|
@ -162,10 +162,10 @@ ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
|
|||
return icm;
|
||||
}
|
||||
|
||||
void Context::loadClass(const char *fileName)
|
||||
ICodeModule* Context::loadClass(const char *fileName)
|
||||
{
|
||||
ICodeGenerator icg(this);
|
||||
icg.readICode(fileName); // loads it into the global object
|
||||
return icg.readICode(fileName); // loads it into the global object
|
||||
}
|
||||
|
||||
JSValues& Context::getRegisters() { return mActivation->mRegisters; }
|
||||
|
@ -604,96 +604,99 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args)
|
|||
else {
|
||||
ICodeModule *icm = target->getICode();
|
||||
ArgumentList *args = op3(call);
|
||||
ArgumentList *callArgs = NULL;
|
||||
|
||||
// if all the parameters are positional
|
||||
// if (icm->itsParameters->mPositionalCount == icm->itsParameters->size())
|
||||
if (icm->itsParameters) {
|
||||
|
||||
// the parameter count includes 'this' and any named rest parameter
|
||||
//
|
||||
uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array
|
||||
// callArgs will be the actual args passed to the target, put into correct register order.
|
||||
// It has room for the rest parameter.
|
||||
ArgumentList *callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
// if all the parameters are positional
|
||||
// if (icm->itsParameters->mPositionalCount == icm->itsParameters->size())
|
||||
|
||||
// don't want to count the rest parameter while processing the others
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::NoRestParameter) pCount--;
|
||||
// the parameter count includes 'this' and any named rest parameter
|
||||
//
|
||||
uint32 pCount = icm->itsParameters->size() - 1; // we won't be passing 'this' via the arg list array
|
||||
// callArgs will be the actual args passed to the target, put into correct register order.
|
||||
// It has room for the rest parameter.
|
||||
callArgs = new ArgumentList(pCount, Argument(TypedRegister(NotARegister, &Null_Type), NULL));
|
||||
|
||||
// don't want to count the rest parameter while processing the others
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::NoRestParameter) pCount--;
|
||||
|
||||
|
||||
uint32 i;
|
||||
JSArray *restArg = NULL;
|
||||
uint32 i;
|
||||
JSArray *restArg = NULL;
|
||||
|
||||
// first match all named arguments with their intended target locations
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
// first match all named arguments with their intended target locations
|
||||
for (i = 0; i < args->size(); i++) {
|
||||
|
||||
const StringAtom *argName = (*args)[i].second;
|
||||
const StringAtom *argName = (*args)[i].second;
|
||||
|
||||
TypedRegister parameter = icm->itsParameters->findVariable(*argName);
|
||||
if (parameter.first == NotARegister) {
|
||||
// arg name doesn't match any parameter name, it's a candidate
|
||||
// for the rest parameter (if there is one)
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::NoRestParameter)
|
||||
throw new JSException("Named argument doesn't match parameter name in call with no rest parameter");
|
||||
else {
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::HasUnnamedRestParameter) {
|
||||
// if the name is a numeric literal >= 0, use it as an array index
|
||||
// otherwise just set the named property.
|
||||
const char16 *c = argName->data();
|
||||
const char16 *end;
|
||||
double d = stringToDouble(c, c + argName->size(), end);
|
||||
int index = -1;
|
||||
TypedRegister parameter = icm->itsParameters->findVariable(*argName);
|
||||
if (parameter.first == NotARegister) {
|
||||
// arg name doesn't match any parameter name, it's a candidate
|
||||
// for the rest parameter (if there is one)
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::NoRestParameter)
|
||||
throw new JSException("Named argument doesn't match parameter name in call with no rest parameter");
|
||||
else {
|
||||
if (icm->itsParameters->mRestParameter != ParameterList::HasUnnamedRestParameter) {
|
||||
// if the name is a numeric literal >= 0, use it as an array index
|
||||
// otherwise just set the named property.
|
||||
const char16 *c = argName->data();
|
||||
const char16 *end;
|
||||
double d = stringToDouble(c, c + argName->size(), end);
|
||||
int index = -1;
|
||||
|
||||
if ((d != d) || (d < 0) || (d != (int)d)) { // a non-numeric or negative value
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::HasRestParameterBeforeBar)
|
||||
throw new JSException("Non-numeric or negative argument name for positional rest parameter");
|
||||
}
|
||||
else { // shift the index value down by the number of positional parameters
|
||||
index = (int)d;
|
||||
index -= icm->itsParameters->mPositionalCount;
|
||||
}
|
||||
if ((d != d) || (d < 0) || (d != (int)d)) { // a non-numeric or negative value
|
||||
if (icm->itsParameters->mRestParameter == ParameterList::HasRestParameterBeforeBar)
|
||||
throw new JSException("Non-numeric or negative argument name for positional rest parameter");
|
||||
}
|
||||
else { // shift the index value down by the number of positional parameters
|
||||
index = (int)d;
|
||||
index -= icm->itsParameters->mPositionalCount;
|
||||
}
|
||||
|
||||
TypedRegister argument = (*args)[i].first; // this is the argument whose name didn't match
|
||||
TypedRegister argument = (*args)[i].first; // this is the argument whose name didn't match
|
||||
|
||||
if (restArg == NULL) {
|
||||
// allocate the rest argument and then subvert the register being used for the
|
||||
// argument under consideration to hold the newly created rest argument.
|
||||
restArg = new JSArray();
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
(*registers)[argument.first] = restArg;
|
||||
// The callArgs for the rest parameter position gets loaded from that slot
|
||||
(*callArgs)[pCount] = Argument(TypedRegister(argument.first, &Array_Type), NULL);
|
||||
}
|
||||
else {
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
if (restArg == NULL) {
|
||||
// allocate the rest argument and then subvert the register being used for the
|
||||
// argument under consideration to hold the newly created rest argument.
|
||||
restArg = new JSArray();
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
(*registers)[argument.first] = restArg;
|
||||
// The callArgs for the rest parameter position gets loaded from that slot
|
||||
(*callArgs)[pCount] = Argument(TypedRegister(argument.first, &Array_Type), NULL);
|
||||
}
|
||||
else {
|
||||
if (index == -1)
|
||||
restArg->setProperty(*argName, (*registers)[argument.first]);
|
||||
else
|
||||
(*restArg)[uint32(index)] = (*registers)[argument.first];
|
||||
}
|
||||
}
|
||||
// else just throw it away
|
||||
}
|
||||
// else just throw it away
|
||||
}
|
||||
else {
|
||||
uint32 targetIndex = parameter.first - 1; // this is the register number we're targetting
|
||||
TypedRegister targetParameter = (*callArgs)[targetIndex].first;
|
||||
if (targetParameter.first != NotARegister) // uh oh, some other argument wants this parameter
|
||||
throw new JSException("Two (or more) arguments have the same name");
|
||||
(*callArgs)[targetIndex] = (*args)[i];
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32 targetIndex = parameter.first - 1; // this is the register number we're targetting
|
||||
TypedRegister targetParameter = (*callArgs)[targetIndex].first;
|
||||
if (targetParameter.first != NotARegister) // uh oh, some other argument wants this parameter
|
||||
throw new JSException("Two (or more) arguments have the same name");
|
||||
(*callArgs)[targetIndex] = (*args)[i];
|
||||
|
||||
|
||||
// make sure that all non-optional parameters have values
|
||||
for (i = 0; i < pCount; i++) {
|
||||
TypedRegister parameter = (*callArgs)[i].first;
|
||||
if (parameter.first == NotARegister) { // doesn't have an assigned argument
|
||||
if (!icm->itsParameters->isOptional(i + 1)) // and parameter (allowing for 'this') doesn't have an optional value
|
||||
throw new JSException("No argument supplied for non-optional parameter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// make sure that all non-optional parameters have values
|
||||
for (i = 0; i < pCount; i++) {
|
||||
TypedRegister parameter = (*callArgs)[i].first;
|
||||
if (parameter.first == NotARegister) { // doesn't have an assigned argument
|
||||
if (!icm->itsParameters->isOptional(i + 1)) // and parameter (allowing for 'this') doesn't have an optional value
|
||||
throw new JSException("No argument supplied for non-optional parameter");
|
||||
}
|
||||
}
|
||||
|
||||
mLinkage = new Linkage(mLinkage, ++mPC, mActivation, mGlobal, op1(call), mICode, mCurrentClosure);
|
||||
mICode = icm;
|
||||
mActivation = new Activation(mICode->itsMaxRegister, mActivation, target->getThis(), callArgs);
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace Interpreter {
|
|||
ICodeModule* genCode(StmtNode *p, const String &fileName);
|
||||
JSValue readEvalFile(FILE* in, const String& fileName);
|
||||
|
||||
void loadClass(const char *fileName);
|
||||
ICodeModule* loadClass(const char *fileName);
|
||||
|
||||
const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, ExprNode::Kind op);
|
||||
|
||||
|
@ -142,14 +142,16 @@ namespace Interpreter {
|
|||
// copy caller's parameter list to initial registers.
|
||||
JSValues::iterator dest = mRegisters.begin();
|
||||
*dest++ = thisArg;
|
||||
const JSValues& params = caller->mRegisters;
|
||||
for (ArgumentList::const_iterator src = list->begin(),
|
||||
end = list->end(); src != end; ++src, ++dest) {
|
||||
Register r = (*src).first.first;
|
||||
if (r != NotARegister)
|
||||
*dest = params[r];
|
||||
else
|
||||
*dest = JSValue(JSValue::uninitialized_tag);
|
||||
if (list) {
|
||||
const JSValues& params = caller->mRegisters;
|
||||
for (ArgumentList::const_iterator src = list->begin(),
|
||||
end = list->end(); src != end; ++src, ++dest) {
|
||||
Register r = (*src).first.first;
|
||||
if (r != NotARegister)
|
||||
*dest = params[r];
|
||||
else
|
||||
*dest = JSValue(JSValue::uninitialized_tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,9 @@ static JSValue loadxml(Context *cx, const JSValues &argv)
|
|||
JSString& fileName = *val.string;
|
||||
std::string str(fileName.length(), char());
|
||||
std::transform(fileName.begin(), fileName.end(), str.begin(), narrow);
|
||||
cx->loadClass(str.c_str());
|
||||
ICodeModule *icm = cx->loadClass(str.c_str());
|
||||
if (icm)
|
||||
result = JSValue(new JSFunction(icm));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче