зеркало из https://github.com/mozilla/pjs.git
Minor e3 fixes. Adding type handling for function parameters & result.
This commit is contained in:
Родитель
6d8f204fda
Коммит
31c6b3b53c
|
@ -263,6 +263,18 @@ void printLocalBindings(LocalBindingMap *lMap, ValueList *frameSlots)
|
|||
stdOut << " forbidden\n";
|
||||
}
|
||||
break;
|
||||
case Member::GetterMember:
|
||||
{
|
||||
Getter *g = checked_cast<Getter *>(m);
|
||||
stdOut << " get" << ":" << *g->type->name << "\n";
|
||||
}
|
||||
break;
|
||||
case Member::SetterMember:
|
||||
{
|
||||
Setter *s = checked_cast<Setter *>(m);
|
||||
stdOut << " set" << ":" << *s->type->name << "\n";
|
||||
}
|
||||
break;
|
||||
case Member::DynamicVariableMember:
|
||||
{
|
||||
DynamicVariable *dv = checked_cast<DynamicVariable *>(m);
|
||||
|
|
|
@ -395,7 +395,7 @@ namespace MetaData {
|
|||
if ((d == 0.0) || !JSDOUBLE_IS_FINITE(d) )
|
||||
return 0;
|
||||
d = fd::fmod(d, two32);
|
||||
d = (d >= 0) ? d : d + two32;
|
||||
d = (d >= 0) ? fd::floor(d) : fd::ceil(d) + two32;
|
||||
if (d >= two31)
|
||||
return (int32)(d - two32);
|
||||
else
|
||||
|
|
|
@ -477,6 +477,8 @@ namespace MetaData {
|
|||
d = stringToDouble(str1, strEnd, numEnd);
|
||||
if (numEnd == str1)
|
||||
return nan;
|
||||
if (skipWhiteSpace(numEnd, strEnd) != strEnd)
|
||||
return nan;
|
||||
}
|
||||
return (neg) ? -d : d;
|
||||
}
|
||||
|
|
|
@ -110,10 +110,15 @@ namespace MetaData {
|
|||
pb = fnDef->parameters;
|
||||
while (pb) {
|
||||
FrameVariable *v = new FrameVariable(compileFrame->allocateSlot(), FrameVariable::Parameter);
|
||||
if (pb->type)
|
||||
ValidateTypeExpression(cxt, env, pb->type);
|
||||
pb->member = v;
|
||||
pb->mn = defineLocalMember(env, pb->name, NULL, Attribute::NoOverride, false, ReadWriteAccess, v, pb->pos, true);
|
||||
pb = pb->next;
|
||||
}
|
||||
}
|
||||
if (fnDef->resultType)
|
||||
ValidateTypeExpression(cxt, env, fnDef->resultType);
|
||||
createDynamicProperty(result, engine->length_StringAtom, INT_TO_JS2VAL(pCount), ReadAccess, true, false);
|
||||
result->fWrap->length = pCount;
|
||||
compileFrame->isConstructor = isConstructor;
|
||||
|
@ -150,7 +155,7 @@ namespace MetaData {
|
|||
ASSERT(!(unchecked || hoisted));
|
||||
// XXX shouldn't be using validateStaticFunction
|
||||
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, false, pos);
|
||||
Getter *g = new Getter(fnInst);
|
||||
Getter *g = new Getter(fnInst->fWrap->resultType, fnInst);
|
||||
defineLocalMember(env, fnDef->name, &a->namespaces, a->overrideMod, a->xplicit, ReadAccess, g, pos, true);
|
||||
}
|
||||
break;
|
||||
|
@ -161,7 +166,7 @@ namespace MetaData {
|
|||
ASSERT(!(unchecked || hoisted));
|
||||
// XXX shouldn't be using validateStaticFunction
|
||||
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, false, pos);
|
||||
Setter *s = new Setter(fnInst);
|
||||
Setter *s = new Setter(fnInst->fWrap->resultType, fnInst);
|
||||
defineLocalMember(env, fnDef->name, &a->namespaces, a->overrideMod, a->xplicit, WriteAccess, s, pos, true);
|
||||
}
|
||||
break;
|
||||
|
@ -1297,6 +1302,20 @@ namespace MetaData {
|
|||
#ifdef DEBUG
|
||||
bCon->fName = *f->function.name;
|
||||
#endif
|
||||
VariableBinding *pb = f->function.parameters;
|
||||
while (pb) {
|
||||
FrameVariable *v = checked_cast<FrameVariable *>(pb->member);
|
||||
if (pb->type)
|
||||
v->type = EvalTypeExpression(env, CompilePhase, pb->type);
|
||||
else
|
||||
v->type = objectClass;
|
||||
pb = pb->next;
|
||||
}
|
||||
if (f->function.resultType)
|
||||
f->function.fWrap->resultType = EvalTypeExpression(env, CompilePhase, f->function.resultType);
|
||||
else
|
||||
f->function.fWrap->resultType = objectClass;
|
||||
|
||||
SetupStmt(env, phase, f->function.body);
|
||||
// XXX need to make sure that all paths lead to an exit of some kind
|
||||
bCon->emitOp(eReturnVoid, p->pos);
|
||||
|
@ -1369,7 +1388,6 @@ namespace MetaData {
|
|||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(vb->member->memberKind == Member::InstanceVariableMember);
|
||||
InstanceVariable *v = checked_cast<InstanceVariable *>(vb->member);
|
||||
JS2Class *t;
|
||||
if (vb->type)
|
||||
|
@ -3960,7 +3978,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
initBooleanObject(this);
|
||||
|
||||
/*** ECMA 3 Math Object ***/
|
||||
SimpleInstance *mathObject = new SimpleInstance(this, objectClass->prototype, objectClass);
|
||||
MAKEBUILTINCLASS(mathClass, objectClass, false, true, engine->allocStringPtr(&world.identifiers["Math"]), JS2VAL_FALSE);
|
||||
SimpleInstance *mathObject = new SimpleInstance(this, objectClass->prototype, mathClass);
|
||||
v = new Variable(objectClass, OBJECT_TO_JS2VAL(mathObject), true);
|
||||
defineLocalMember(env, &world.identifiers["Math"], NULL, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true);
|
||||
initMathObject(this, mathObject);
|
||||
|
@ -4444,6 +4463,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
GCMARKOBJECT(generalNumberClass);
|
||||
GCMARKOBJECT(integerClass);
|
||||
GCMARKOBJECT(numberClass);
|
||||
GCMARKOBJECT(mathClass);
|
||||
GCMARKOBJECT(characterClass);
|
||||
GCMARKOBJECT(stringClass);
|
||||
GCMARKOBJECT(namespaceClass);
|
||||
|
@ -4553,6 +4573,16 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static js2val class_ProtoGetter(JS2Metadata *meta, const js2val thisValue, js2val /* argv */ [], uint32 /* argc */)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(thisValue);
|
||||
ASSERT(obj->kind == ClassKind);
|
||||
JS2Class *c = checked_cast<JS2Class *>(obj);
|
||||
|
||||
return OBJECT_TO_JS2VAL(c->super);
|
||||
}
|
||||
|
||||
void JS2Metadata::initBuiltinClass(JS2Class *builtinClass, FunctionData *staticFunctions, NativeCode *construct, NativeCode *call)
|
||||
{
|
||||
|
@ -4567,10 +4597,17 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
Variable *v = new Variable(builtinClass, INT_TO_JS2VAL(1), true);
|
||||
defineLocalMember(env, engine->length_StringAtom, NULL, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false);
|
||||
|
||||
FunctionInstance *callInst = new FunctionInstance(this, functionClass->prototype, functionClass);
|
||||
callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), class_ProtoGetter, env);
|
||||
callInst->fWrap->length = 0;
|
||||
Getter *g = new Getter(objectClass, callInst);
|
||||
defineLocalMember(env, &world.identifiers["__proto__"], NULL, Attribute::NoOverride, false, ReadAccess, g, 0, true);
|
||||
|
||||
|
||||
pf = staticFunctions;
|
||||
if (pf) {
|
||||
while (pf->name) {
|
||||
FunctionInstance *callInst = new FunctionInstance(this, functionClass->prototype, functionClass);
|
||||
callInst = new FunctionInstance(this, functionClass->prototype, functionClass);
|
||||
callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, env);
|
||||
callInst->fWrap->length = pf->length;
|
||||
v = new Variable(functionClass, OBJECT_TO_JS2VAL(callInst), true);
|
||||
|
|
|
@ -488,11 +488,19 @@ public:
|
|||
|
||||
typedef enum { Local, Package, Parameter } FrameVariableKind;
|
||||
|
||||
FrameVariable(uint16 frameSlot, FrameVariableKind kind) : LocalMember(Member::FrameVariableMember), frameSlot(frameSlot), kind(kind), sealed(false) { }
|
||||
FrameVariable(uint16 frameSlot, FrameVariableKind kind)
|
||||
: LocalMember(Member::FrameVariableMember),
|
||||
frameSlot(frameSlot),
|
||||
kind(kind),
|
||||
type(NULL),
|
||||
sealed(false)
|
||||
{ }
|
||||
|
||||
uint16 frameSlot;
|
||||
FrameVariableKind kind; // the kind of frame this variable is in
|
||||
|
||||
JS2Class *type;
|
||||
|
||||
bool sealed; // true if this variable cannot be deleted using the delete operator
|
||||
virtual LocalMember *clone() { return new FrameVariable(frameSlot, kind); }
|
||||
};
|
||||
|
@ -509,7 +517,7 @@ public:
|
|||
|
||||
class Getter : public LocalMember {
|
||||
public:
|
||||
Getter(FunctionInstance *code) : LocalMember(Member::GetterMember), type(NULL), code(code) { }
|
||||
Getter(JS2Class *type, FunctionInstance *code) : LocalMember(Member::GetterMember), type(type), code(code) { }
|
||||
|
||||
JS2Class *type; // The type of the value read from this getter
|
||||
FunctionInstance *code; // calling this object does the read
|
||||
|
@ -519,7 +527,7 @@ public:
|
|||
|
||||
class Setter : public LocalMember {
|
||||
public:
|
||||
Setter(FunctionInstance *code) : LocalMember(Member::SetterMember), type(NULL), code(code) { }
|
||||
Setter(JS2Class *type, FunctionInstance *code) : LocalMember(Member::SetterMember), type(type), code(code) { }
|
||||
|
||||
JS2Class *type; // The type of the value written into the setter
|
||||
FunctionInstance *code; // calling this object does the write
|
||||
|
@ -836,9 +844,24 @@ class ParameterFrame;
|
|||
class FunctionWrapper {
|
||||
public:
|
||||
FunctionWrapper(bool unchecked, ParameterFrame *compileFrame, Environment *env)
|
||||
: bCon(new BytecodeContainer()), code(NULL), unchecked(unchecked), compileFrame(compileFrame), env(new Environment(env)), length(0) { }
|
||||
: bCon(new BytecodeContainer()),
|
||||
code(NULL),
|
||||
unchecked(unchecked),
|
||||
compileFrame(compileFrame),
|
||||
env(new Environment(env)),
|
||||
length(0),
|
||||
resultType(NULL)
|
||||
{ }
|
||||
|
||||
FunctionWrapper(bool unchecked, ParameterFrame *compileFrame, NativeCode *code, Environment *env)
|
||||
: bCon(NULL), code(code), unchecked(unchecked), compileFrame(compileFrame), env(new Environment(env)), length(0) { }
|
||||
: bCon(NULL),
|
||||
code(code),
|
||||
unchecked(unchecked),
|
||||
compileFrame(compileFrame),
|
||||
env(new Environment(env)),
|
||||
length(0),
|
||||
resultType(NULL)
|
||||
{ }
|
||||
|
||||
virtual ~FunctionWrapper() { if (bCon) delete bCon; }
|
||||
|
||||
|
@ -848,6 +871,7 @@ public:
|
|||
ParameterFrame *compileFrame;
|
||||
Environment *env;
|
||||
uint32 length;
|
||||
JS2Class *resultType;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1491,6 +1515,7 @@ public:
|
|||
JS2Class *booleanClass;
|
||||
JS2Class *generalNumberClass;
|
||||
JS2Class *numberClass;
|
||||
JS2Class *mathClass;
|
||||
JS2Class *integerClass;
|
||||
JS2Class *characterClass;
|
||||
JS2Class *stringClass;
|
||||
|
|
|
@ -756,7 +756,7 @@ static js2val String_substring(JS2Metadata *meta, const js2val thisValue, js2val
|
|||
if (argc > 1) {
|
||||
float64 farg1 = meta->toFloat64(argv[1]);
|
||||
if (JSDOUBLE_IS_NaN(farg1) || (farg1 < 0))
|
||||
end = sourceLength;
|
||||
end = 0;
|
||||
else {
|
||||
if (!JSDOUBLE_IS_FINITE(farg1))
|
||||
end = sourceLength;
|
||||
|
@ -788,14 +788,14 @@ void initStringObject(JS2Metadata *meta)
|
|||
{ "charAt", 1, String_charAt },
|
||||
{ "charCodeAt", 1, String_charCodeAt },
|
||||
{ "concat", 1, String_concat },
|
||||
{ "indexOf", 2, String_indexOf }, // XXX ECMA spec says 1, but tests want 2 XXX
|
||||
{ "lastIndexOf", 2, String_lastIndexOf }, // XXX ECMA spec says 1, but tests want 2 XXX
|
||||
{ "indexOf", 1, String_indexOf },
|
||||
{ "lastIndexOf", 1, String_lastIndexOf },
|
||||
{ "localeCompare", 1, String_localeCompare },
|
||||
{ "match", 1, String_match },
|
||||
{ "replace", 2, String_replace },
|
||||
{ "search", 1, String_search },
|
||||
{ "slice", 2, String_slice },
|
||||
{ "split", 1, String_split }, // XXX ECMA spec says 2, but tests want 1 XXX
|
||||
{ "split", 2, String_split },
|
||||
{ "substring", 2, String_substring },
|
||||
{ "toSource", 0, String_toString },
|
||||
{ "toLocaleUpperCase", 0, String_toUpperCase }, // (sic)
|
||||
|
|
Загрузка…
Ссылка в новой задаче