Implemented Import -only it's not in the parser yet.

Added missing defineXXX functions.
This commit is contained in:
rogerl%netscape.com 2000-07-11 23:49:20 +00:00
parent 91343cc3f0
commit b8bd1adb30
10 changed files with 394 additions and 186 deletions

View File

@ -41,12 +41,18 @@
#include <stdexcept>
namespace JavaScript {
namespace ICG {
using namespace VM;
using namespace JSTypes;
using namespace JSClasses;
using namespace Interpreter;
inline char narrow(char16 ch) { return char(ch); }
uint32 ICodeModule::sMaxID = 0;
@ -206,7 +212,7 @@ TypedRegister ICodeGenerator::loadBoolean(bool value)
return dest;
}
TypedRegister ICodeGenerator::newObject(RegisterList */*args*/)
TypedRegister ICodeGenerator::newObject(RegisterList * /*args*/)
{
TypedRegister dest(getTempRegister(), &Any_Type);
NewObject *instr = new NewObject(dest);
@ -1117,7 +1123,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::index :
{
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
TypedRegister base = genExpr(b->op1);
TypedRegister base = genExpr(b->op1);
JSClass *clazz = dynamic_cast<JSClass*>(base.second);
if (clazz) {
// look for operator [] and invoke it
}
TypedRegister index = genExpr(b->op2);
ret = getElement(base, index);
}
@ -1698,6 +1708,22 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
}
}
break;
case StmtNode::Import:
{
ImportStmtNode *i = static_cast<ImportStmtNode *>(p);
String *fileName = i->bindings->packageName.str;
if (fileName) { /// if not, build one from the idList instead
std::string str(fileName->length(), char());
std::transform(fileName->begin(), fileName->end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
Context cx(*mWorld, mGlobal);
JSValue result = cx.readEvalFile(f, *fileName);
fclose(f);
}
}
}
break;
case StmtNode::Var:
{
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);

View File

@ -114,6 +114,75 @@ struct Activation : public gc_base {
};
JSValue Context::readEvalFile(FILE* in, const String& fileName)
{
String buffer;
string line;
LineReader inReader(in);
JSValues emptyArgs;
JSValue result;
while (inReader.readLine(line) != 0) {
appendChars(buffer, line.data(), line.size());
try {
Arena a;
Parser p(getWorld(), a, buffer, fileName);
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';
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = genCode(parsedStatements, fileName);
if (icm) {
result = interpret(icm, emptyArgs);
delete icm;
}
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 == fileName)) {
stdOut << '\n' << e.fullMessage();
clear(buffer);
}
}
}
return result;
}
ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
{
ICodeGenerator icg(&getWorld(), getGlobalObject());
TypedRegister ret(NotARegister, &None_Type);
while (p) {
ret = icg.genStmt(p);
p = p->next;
}
icg.returnStmt(ret);
ICodeModule *icm = icg.complete();
icm->setFileName (fileName);
return icm;
}
JSValues& Context::getRegisters() { return mActivation->mRegisters; }
ICodeModule* Context::getICode() { return mActivation->mICode; }
@ -248,7 +317,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2)
return JSValue(lv.f64 < rv.f64);
}
}
static JSValue lessEqual_Default(const JSValue& r1, const JSValue& r2)
static JSValue lessOrEqual_Default(const JSValue& r1, const JSValue& r2)
{
JSValue lv = r1.toPrimitive(JSValue::Number);
JSValue rv = r2.toPrimitive(JSValue::Number);
@ -314,7 +383,7 @@ public:
typedef enum {
Add, Subtract, Multiply, Divide,
Remainder, LeftShift, RightShift, LogicalRightShift,
BitwiseOr, BitwiseXor, BitwiseAnd, Less, LessEqual,
BitwiseOr, BitwiseXor, BitwiseAnd, Less, LessOrEqual,
Equal, Identical
} BinaryOp;
@ -349,7 +418,7 @@ BinaryOperator::BinaryOp BinaryOperator::mapICodeOp(ICodeOp op) {
case XOR : return BitwiseXor;
case COMPARE_LT : return Less;
case COMPARE_LE : return LessEqual;
case COMPARE_LE : return LessOrEqual;
case COMPARE_EQ : return Equal;
case STRICT_EQ : return Identical;
default :
@ -377,7 +446,7 @@ JSBinaryOperator::JSBinaryCode defaultFunction[] = {
xor_Default,
and_Default,
less_Default,
lessEqual_Default,
lessOrEqual_Default,
equal_Default,
identical_Default
};
@ -407,34 +476,88 @@ static JSValue defineAdd(const JSValues& argv)
return kUndefinedValue;
}
#define DEFINE_OBO(NAME) \
static JSValue define##NAME(const JSValues& argv) \
{ \
ASSERT(argv[0].isType()); \
ASSERT(argv[1].isType()); \
ASSERT(argv[2].isFunction()); \
binaryOperators[BinaryOperator::##NAME].push_back( \
new BinaryOperator(argv[0].type, argv[1].type, argv[2].function)); \
return kUndefinedValue; \
} \
DEFINE_OBO(Subtract)
DEFINE_OBO(Multiply)
DEFINE_OBO(Divide)
DEFINE_OBO(Remainder)
DEFINE_OBO(LeftShift)
DEFINE_OBO(RightShift)
DEFINE_OBO(LogicalRightShift)
DEFINE_OBO(BitwiseOr)
DEFINE_OBO(BitwiseXor)
DEFINE_OBO(BitwiseAnd)
DEFINE_OBO(Less)
DEFINE_OBO(LessOrEqual)
DEFINE_OBO(Equal)
DEFINE_OBO(Identical)
void Context::initContext()
{
// if global has a parent, assume it's been initialized already.
if (mGlobal->getParent())
return;
// predefine the predefined types;
// predefine the umm, predefined types;
struct PDT {
char *name;
JSType *type;
} PDTs[] = {
{ "any", &Any_Type },
{ "Integer", &Integer_Type },
{ "Number", &Number_Type },
{ "Character", &Character_Type },
{ "String", &String_Type },
{ "Function", &Function_Type },
{ "Array", &Array_Type },
{ "Type", &Type_Type },
{ "Boolean", &Boolean_Type },
{ "Null", &Null_Type },
{ "Void", &Void_Type },
{ "none", &None_Type }
};
mGlobal->defineVariable(widenCString("any"), &Type_Type, JSValue(&Any_Type));
mGlobal->defineVariable(widenCString("Integer"), &Type_Type, JSValue(&Integer_Type));
mGlobal->defineVariable(widenCString("Number"), &Type_Type, JSValue(&Number_Type));
mGlobal->defineVariable(widenCString("Character"), &Type_Type, JSValue(&Character_Type));
mGlobal->defineVariable(widenCString("String"), &Type_Type, JSValue(&String_Type));
mGlobal->defineVariable(widenCString("Function"), &Type_Type, JSValue(&Function_Type));
mGlobal->defineVariable(widenCString("Array"), &Type_Type, JSValue(&Array_Type));
mGlobal->defineVariable(widenCString("Type"), &Type_Type, JSValue(&Type_Type));
mGlobal->defineVariable(widenCString("Boolean"), &Type_Type, JSValue(&Boolean_Type));
mGlobal->defineVariable(widenCString("Null"), &Type_Type, JSValue(&Null_Type));
mGlobal->defineVariable(widenCString("Void"), &Type_Type, JSValue(&Void_Type));
mGlobal->defineVariable(widenCString("none"), &Type_Type, JSValue(&None_Type));
for (int i = 0; i < sizeof(PDTs) / sizeof(struct PDT); i++)
mGlobal->defineVariable(widenCString(PDTs[i].name), &Type_Type, JSValue(PDTs[i].type));
// hack - the following should be available only after importing the 'Operators' package
// (hmm, how will that work - the import needs to connect the functions into this mechanism
// do we watch for the specific package name???)
StringAtom& name = mWorld.identifiers[widenCString("defineAdd")];
mGlobal->defineNativeFunction(name, defineAdd);
struct OBO {
char *name;
JSValue (*fun)(const JSValues& argv);
} OBOs[] = {
{ "defineAdd", defineAdd },
{ "defineSubtract", defineSubtract },
{ "defineMultiply", defineMultiply },
{ "defineDivide", defineDivide },
{ "defineRemainder", defineRemainder },
{ "defineLeftShift", defineLeftShift },
{ "defineRightShift", defineRightShift },
{ "defineLogicalRightShift",defineLogicalRightShift },
{ "defineBitwiseOr", defineBitwiseOr },
{ "defineBitwiseXor", defineBitwiseXor },
{ "defineBitwiseAnd", defineBitwiseAnd },
{ "defineLess", defineLess },
{ "defineLessOrEqual", defineLessOrEqual },
{ "defineEqual", defineEqual },
{ "defineIdentical", defineIdentical },
};
for (i = 0; i < sizeof(OBOs) / sizeof(struct OBO); i++)
mGlobal->defineNativeFunction(mWorld.identifiers[widenCString(OBOs[i].name)], OBOs[i].fun);
}
static const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, BinaryOperator::BinaryOp op)
@ -918,6 +1041,11 @@ using JSString throughout.
case COMPARE_EQ:
case STRICT_EQ:
{
//
// XXX if Package 'Operators' has not been seen, these operators cannot have been
// overridden, so we should use a different dispatch and execute the default
// behaviour inline instead,
//
Arithmetic* mul = static_cast<Arithmetic*>(instruction);
JSValue& dest = (*registers)[dst(mul).first];
JSValue& r1 = (*registers)[src1(mul).first];

View File

@ -77,6 +77,10 @@ namespace Interpreter {
JSValue interpret(ICodeModule* iCode, const JSValues& args);
void doCall(JSFunction *target, Instruction *pc);
ICodeModule* genCode(StmtNode *p, const String &fileName);
JSValue readEvalFile(FILE* in, const String& fileName);
private:
void broadcast(Event event);

View File

@ -145,91 +145,28 @@ static JSValue dump(const JSValues &argv)
return kUndefinedValue;
}
static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
{
ICodeGenerator icg(&cx.getWorld(), cx.getGlobalObject());
TypedRegister ret(NotARegister, &None_Type);
while (p) {
ret = icg.genStmt(p);
p = p->next;
}
icg.returnStmt(ret);
ICodeModule *icm = icg.complete();
icm->setFileName (fileName);
return icm;
}
static JSValue readEvalFile(FILE* in, const String& fileName)
{
Context cx(world, &global);
String buffer;
string line;
LineReader inReader(in);
JSValues emptyArgs;
JSValue result;
while (inReader.readLine(line) != 0) {
appendChars(buffer, line.data(), line.size());
try {
Arena a;
Parser p(world, a, buffer, fileName);
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';
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = genCode(cx, parsedStatements, fileName);
if (icm) {
result = cx.interpret(icm, emptyArgs);
delete icm;
}
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 == fileName)) {
stdOut << '\n' << e.fullMessage();
clear(buffer);
}
}
}
return result;
}
inline char narrow(char16 ch) { return char(ch); }
static JSValue load(const JSValues &argv)
{
JSValue result;
size_t n = argv.size();
if (n > 1) { // the 'this' parameter is un-interesting
if (n > 1) {
ASSERT(argv[0].isObject());
JSScope *scope = dynamic_cast<JSScope *>(argv[0].object);
ASSERT(scope);
for (size_t i = 1; i < n; ++i) {
JSValue val = argv[i].toString();
if (val.isString()) {
Context cx(world, scope);
String fileName(*val.string);
std::string str(fileName.length(), char());
std::transform(fileName.begin(), fileName.end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
result = readEvalFile(f, fileName);
result = cx.readEvalFile(f, fileName);
fclose(f);
}
}
@ -288,7 +225,7 @@ static void readEvalPrint(FILE *in, World &world)
#endif
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = genCode(cx, parsedStatements, ConsoleName);
ICodeModule* icm = cx.genCode(parsedStatements, ConsoleName);
if (icm) {
JSValue result = cx.interpret(icm, JSValues());
stdOut << "result = " << result << "\n";

View File

@ -103,7 +103,16 @@ const JSType *JSValue::getType() const
case JSValue::f64_tag:
return &Number_Type;
case JSValue::object_tag:
return &Any_Type; // XXX get type from Object
{
//
// XXX why isn't there a class for Object? XXX
//
JSClass *clazz = dynamic_cast<JSClass *>(object->getType());
if (clazz)
return clazz;
else
return &Any_Type;
}
case JSValue::array_tag:
return &Array_Type;
case JSValue::function_tag:

View File

@ -41,12 +41,18 @@
#include <stdexcept>
namespace JavaScript {
namespace ICG {
using namespace VM;
using namespace JSTypes;
using namespace JSClasses;
using namespace Interpreter;
inline char narrow(char16 ch) { return char(ch); }
uint32 ICodeModule::sMaxID = 0;
@ -206,7 +212,7 @@ TypedRegister ICodeGenerator::loadBoolean(bool value)
return dest;
}
TypedRegister ICodeGenerator::newObject(RegisterList */*args*/)
TypedRegister ICodeGenerator::newObject(RegisterList * /*args*/)
{
TypedRegister dest(getTempRegister(), &Any_Type);
NewObject *instr = new NewObject(dest);
@ -1117,7 +1123,11 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
case ExprNode::index :
{
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
TypedRegister base = genExpr(b->op1);
TypedRegister base = genExpr(b->op1);
JSClass *clazz = dynamic_cast<JSClass*>(base.second);
if (clazz) {
// look for operator [] and invoke it
}
TypedRegister index = genExpr(b->op2);
ret = getElement(base, index);
}
@ -1698,6 +1708,22 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
}
}
break;
case StmtNode::Import:
{
ImportStmtNode *i = static_cast<ImportStmtNode *>(p);
String *fileName = i->bindings->packageName.str;
if (fileName) { /// if not, build one from the idList instead
std::string str(fileName->length(), char());
std::transform(fileName->begin(), fileName->end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
Context cx(*mWorld, mGlobal);
JSValue result = cx.readEvalFile(f, *fileName);
fclose(f);
}
}
}
break;
case StmtNode::Var:
{
VariableStmtNode *vs = static_cast<VariableStmtNode *>(p);

View File

@ -114,6 +114,75 @@ struct Activation : public gc_base {
};
JSValue Context::readEvalFile(FILE* in, const String& fileName)
{
String buffer;
string line;
LineReader inReader(in);
JSValues emptyArgs;
JSValue result;
while (inReader.readLine(line) != 0) {
appendChars(buffer, line.data(), line.size());
try {
Arena a;
Parser p(getWorld(), a, buffer, fileName);
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';
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = genCode(parsedStatements, fileName);
if (icm) {
result = interpret(icm, emptyArgs);
delete icm;
}
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 == fileName)) {
stdOut << '\n' << e.fullMessage();
clear(buffer);
}
}
}
return result;
}
ICodeModule* Context::genCode(StmtNode *p, const String &fileName)
{
ICodeGenerator icg(&getWorld(), getGlobalObject());
TypedRegister ret(NotARegister, &None_Type);
while (p) {
ret = icg.genStmt(p);
p = p->next;
}
icg.returnStmt(ret);
ICodeModule *icm = icg.complete();
icm->setFileName (fileName);
return icm;
}
JSValues& Context::getRegisters() { return mActivation->mRegisters; }
ICodeModule* Context::getICode() { return mActivation->mICode; }
@ -248,7 +317,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2)
return JSValue(lv.f64 < rv.f64);
}
}
static JSValue lessEqual_Default(const JSValue& r1, const JSValue& r2)
static JSValue lessOrEqual_Default(const JSValue& r1, const JSValue& r2)
{
JSValue lv = r1.toPrimitive(JSValue::Number);
JSValue rv = r2.toPrimitive(JSValue::Number);
@ -314,7 +383,7 @@ public:
typedef enum {
Add, Subtract, Multiply, Divide,
Remainder, LeftShift, RightShift, LogicalRightShift,
BitwiseOr, BitwiseXor, BitwiseAnd, Less, LessEqual,
BitwiseOr, BitwiseXor, BitwiseAnd, Less, LessOrEqual,
Equal, Identical
} BinaryOp;
@ -349,7 +418,7 @@ BinaryOperator::BinaryOp BinaryOperator::mapICodeOp(ICodeOp op) {
case XOR : return BitwiseXor;
case COMPARE_LT : return Less;
case COMPARE_LE : return LessEqual;
case COMPARE_LE : return LessOrEqual;
case COMPARE_EQ : return Equal;
case STRICT_EQ : return Identical;
default :
@ -377,7 +446,7 @@ JSBinaryOperator::JSBinaryCode defaultFunction[] = {
xor_Default,
and_Default,
less_Default,
lessEqual_Default,
lessOrEqual_Default,
equal_Default,
identical_Default
};
@ -407,34 +476,88 @@ static JSValue defineAdd(const JSValues& argv)
return kUndefinedValue;
}
#define DEFINE_OBO(NAME) \
static JSValue define##NAME(const JSValues& argv) \
{ \
ASSERT(argv[0].isType()); \
ASSERT(argv[1].isType()); \
ASSERT(argv[2].isFunction()); \
binaryOperators[BinaryOperator::##NAME].push_back( \
new BinaryOperator(argv[0].type, argv[1].type, argv[2].function)); \
return kUndefinedValue; \
} \
DEFINE_OBO(Subtract)
DEFINE_OBO(Multiply)
DEFINE_OBO(Divide)
DEFINE_OBO(Remainder)
DEFINE_OBO(LeftShift)
DEFINE_OBO(RightShift)
DEFINE_OBO(LogicalRightShift)
DEFINE_OBO(BitwiseOr)
DEFINE_OBO(BitwiseXor)
DEFINE_OBO(BitwiseAnd)
DEFINE_OBO(Less)
DEFINE_OBO(LessOrEqual)
DEFINE_OBO(Equal)
DEFINE_OBO(Identical)
void Context::initContext()
{
// if global has a parent, assume it's been initialized already.
if (mGlobal->getParent())
return;
// predefine the predefined types;
// predefine the umm, predefined types;
struct PDT {
char *name;
JSType *type;
} PDTs[] = {
{ "any", &Any_Type },
{ "Integer", &Integer_Type },
{ "Number", &Number_Type },
{ "Character", &Character_Type },
{ "String", &String_Type },
{ "Function", &Function_Type },
{ "Array", &Array_Type },
{ "Type", &Type_Type },
{ "Boolean", &Boolean_Type },
{ "Null", &Null_Type },
{ "Void", &Void_Type },
{ "none", &None_Type }
};
mGlobal->defineVariable(widenCString("any"), &Type_Type, JSValue(&Any_Type));
mGlobal->defineVariable(widenCString("Integer"), &Type_Type, JSValue(&Integer_Type));
mGlobal->defineVariable(widenCString("Number"), &Type_Type, JSValue(&Number_Type));
mGlobal->defineVariable(widenCString("Character"), &Type_Type, JSValue(&Character_Type));
mGlobal->defineVariable(widenCString("String"), &Type_Type, JSValue(&String_Type));
mGlobal->defineVariable(widenCString("Function"), &Type_Type, JSValue(&Function_Type));
mGlobal->defineVariable(widenCString("Array"), &Type_Type, JSValue(&Array_Type));
mGlobal->defineVariable(widenCString("Type"), &Type_Type, JSValue(&Type_Type));
mGlobal->defineVariable(widenCString("Boolean"), &Type_Type, JSValue(&Boolean_Type));
mGlobal->defineVariable(widenCString("Null"), &Type_Type, JSValue(&Null_Type));
mGlobal->defineVariable(widenCString("Void"), &Type_Type, JSValue(&Void_Type));
mGlobal->defineVariable(widenCString("none"), &Type_Type, JSValue(&None_Type));
for (int i = 0; i < sizeof(PDTs) / sizeof(struct PDT); i++)
mGlobal->defineVariable(widenCString(PDTs[i].name), &Type_Type, JSValue(PDTs[i].type));
// hack - the following should be available only after importing the 'Operators' package
// (hmm, how will that work - the import needs to connect the functions into this mechanism
// do we watch for the specific package name???)
StringAtom& name = mWorld.identifiers[widenCString("defineAdd")];
mGlobal->defineNativeFunction(name, defineAdd);
struct OBO {
char *name;
JSValue (*fun)(const JSValues& argv);
} OBOs[] = {
{ "defineAdd", defineAdd },
{ "defineSubtract", defineSubtract },
{ "defineMultiply", defineMultiply },
{ "defineDivide", defineDivide },
{ "defineRemainder", defineRemainder },
{ "defineLeftShift", defineLeftShift },
{ "defineRightShift", defineRightShift },
{ "defineLogicalRightShift",defineLogicalRightShift },
{ "defineBitwiseOr", defineBitwiseOr },
{ "defineBitwiseXor", defineBitwiseXor },
{ "defineBitwiseAnd", defineBitwiseAnd },
{ "defineLess", defineLess },
{ "defineLessOrEqual", defineLessOrEqual },
{ "defineEqual", defineEqual },
{ "defineIdentical", defineIdentical },
};
for (i = 0; i < sizeof(OBOs) / sizeof(struct OBO); i++)
mGlobal->defineNativeFunction(mWorld.identifiers[widenCString(OBOs[i].name)], OBOs[i].fun);
}
static const JSValue findBinaryOverride(JSValue &operand1, JSValue &operand2, BinaryOperator::BinaryOp op)
@ -918,6 +1041,11 @@ using JSString throughout.
case COMPARE_EQ:
case STRICT_EQ:
{
//
// XXX if Package 'Operators' has not been seen, these operators cannot have been
// overridden, so we should use a different dispatch and execute the default
// behaviour inline instead,
//
Arithmetic* mul = static_cast<Arithmetic*>(instruction);
JSValue& dest = (*registers)[dst(mul).first];
JSValue& r1 = (*registers)[src1(mul).first];

View File

@ -77,6 +77,10 @@ namespace Interpreter {
JSValue interpret(ICodeModule* iCode, const JSValues& args);
void doCall(JSFunction *target, Instruction *pc);
ICodeModule* genCode(StmtNode *p, const String &fileName);
JSValue readEvalFile(FILE* in, const String& fileName);
private:
void broadcast(Event event);

View File

@ -103,7 +103,16 @@ const JSType *JSValue::getType() const
case JSValue::f64_tag:
return &Number_Type;
case JSValue::object_tag:
return &Any_Type; // XXX get type from Object
{
//
// XXX why isn't there a class for Object? XXX
//
JSClass *clazz = dynamic_cast<JSClass *>(object->getType());
if (clazz)
return clazz;
else
return &Any_Type;
}
case JSValue::array_tag:
return &Array_Type;
case JSValue::function_tag:

View File

@ -145,91 +145,28 @@ static JSValue dump(const JSValues &argv)
return kUndefinedValue;
}
static ICodeModule* genCode(Context &cx, StmtNode *p, const String &fileName)
{
ICodeGenerator icg(&cx.getWorld(), cx.getGlobalObject());
TypedRegister ret(NotARegister, &None_Type);
while (p) {
ret = icg.genStmt(p);
p = p->next;
}
icg.returnStmt(ret);
ICodeModule *icm = icg.complete();
icm->setFileName (fileName);
return icm;
}
static JSValue readEvalFile(FILE* in, const String& fileName)
{
Context cx(world, &global);
String buffer;
string line;
LineReader inReader(in);
JSValues emptyArgs;
JSValue result;
while (inReader.readLine(line) != 0) {
appendChars(buffer, line.data(), line.size());
try {
Arena a;
Parser p(world, a, buffer, fileName);
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';
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = genCode(cx, parsedStatements, fileName);
if (icm) {
result = cx.interpret(icm, emptyArgs);
delete icm;
}
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 == fileName)) {
stdOut << '\n' << e.fullMessage();
clear(buffer);
}
}
}
return result;
}
inline char narrow(char16 ch) { return char(ch); }
static JSValue load(const JSValues &argv)
{
JSValue result;
size_t n = argv.size();
if (n > 1) { // the 'this' parameter is un-interesting
if (n > 1) {
ASSERT(argv[0].isObject());
JSScope *scope = dynamic_cast<JSScope *>(argv[0].object);
ASSERT(scope);
for (size_t i = 1; i < n; ++i) {
JSValue val = argv[i].toString();
if (val.isString()) {
Context cx(world, scope);
String fileName(*val.string);
std::string str(fileName.length(), char());
std::transform(fileName.begin(), fileName.end(), str.begin(), narrow);
FILE* f = fopen(str.c_str(), "r");
if (f) {
result = readEvalFile(f, fileName);
result = cx.readEvalFile(f, fileName);
fclose(f);
}
}
@ -288,7 +225,7 @@ static void readEvalPrint(FILE *in, World &world)
#endif
// Generate code for parsedStatements, which is a linked
// list of zero or more statements
ICodeModule* icm = genCode(cx, parsedStatements, ConsoleName);
ICodeModule* icm = cx.genCode(parsedStatements, ConsoleName);
if (icm) {
JSValue result = cx.interpret(icm, JSValues());
stdOut << "result = " << result << "\n";