Mercurial > projects > dmdscript-tango
view dmdscript_tango/dobject.d @ 3:8363a4bf6a8f
rename package: dmdscript to dmdscript_tango
author | saaadel |
---|---|
date | Sun, 24 Jan 2010 18:33:05 +0200 |
parents | 55c2951c07be |
children |
line wrap: on
line source
/* Digital Mars DMDScript source code. * Copyright (c) 2000-2002 by Chromium Communications * D version Copyright (c) 2004-2006 by Digital Mars * All Rights Reserved * written by Walter Bright * www.digitalmars.com * Use at your own risk. There is no warranty, express or implied. * License for redistribution is by the GNU General Public License in gpl.txt. * * A binary, non-exclusive license for commercial use can be * purchased from www.digitalmars.com/dscript/buy.html. * * DMDScript is implemented in the D Programming Language, * www.digitalmars.com/d/ * * For a C++ implementation of DMDScript, including COM support, * see www.digitalmars.com/dscript/cppscript.html. */ module dmdscript_tango.dobject; import std.string; import std.c.stdarg; import std.c.string; import dmdscript_tango.script; import dmdscript_tango.value; import dmdscript_tango.dfunction; import dmdscript_tango.property; import dmdscript_tango.threadcontext; import dmdscript_tango.iterator; import dmdscript_tango.identifier; import dmdscript_tango.textgen.errmsgs; import dmdscript_tango.text; import dmdscript_tango.program; import dmdscript_tango.dboolean; import dmdscript_tango.dstring; import dmdscript_tango.dnumber; import dmdscript_tango.darray; import dmdscript_tango.dmath; import dmdscript_tango.ddate; import dmdscript_tango.dregexp; import dmdscript_tango.derror; import dmdscript_tango.dnative; import dmdscript_tango.protoerror; int* pfoo = &dmdscript_tango.protoerror.foo; // link it in //debug = LOG; /************************** Dobject_constructor *************************/ class Dobject_constructor : Dfunction { this(ThreadContext *tc) { super(1, tc.Dfunction_prototype); if (tc.Dobject_prototype) Put(TEXT_prototype, tc.Dobject_prototype, DontEnum | DontDelete | ReadOnly); } void *Construct(CallContext *cc, Value *ret, Value[] arglist) { Dobject o; Value* v; // ECMA 15.2.2 if (arglist.length == 0) { o = new Dobject(Dobject.getPrototype()); } else { v = &arglist[0]; if (v.isPrimitive()) { if (v.isUndefinedOrNull()) { o = new Dobject(Dobject.getPrototype()); } else o = v.toObject(); } else o = v.toObject(); } //printf("constructed object o=%p, v=%p,'%s'\n", o, v,v.getType()); ret.putVobject(o); return null; } void *Call(CallContext *cc, Dobject othis, Value* ret, Value[] arglist) { Dobject o; void *result; // ECMA 15.2.1 if (arglist.length == 0) { result = Construct(cc, ret, arglist); } else { Value* v; v = &arglist[0]; if (v.isUndefinedOrNull()) result = Construct(cc, ret, arglist); else { o = v.toObject(); ret.putVobject(o); result = null; } } return result; } } /* ===================== Dobject_prototype_toString ================ */ void* Dobject_prototype_toString(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { d_string s; d_string string; //debug (LOG) writef("Dobject.prototype.toString(ret = %x)\n", ret); s = othis.classname; /+ // Should we do [object] or [object Object]? if (s == TEXT_Object) string = TEXT_bobjectb; else +/ string = std.string.format("[object %s]", s); ret.putVstring(string); return null; } /* ===================== Dobject_prototype_toLocaleString ================ */ void* Dobject_prototype_toLocaleString(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.2.4.3 // "This function returns the result of calling toString()." Value* v; //writef("Dobject.prototype.toLocaleString(ret = %x)\n", ret); v = othis.Get(TEXT_toString); if (v && !v.isPrimitive()) // if it's an Object { void *a; Dobject o; o = v.object; a = o.Call(cc, othis, ret, arglist); if (a) // if exception was thrown return a; } return null; } /* ===================== Dobject_prototype_valueOf ================ */ void* Dobject_prototype_valueOf(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { ret.putVobject(othis); return null; } /* ===================== Dobject_prototype_toSource ================ */ void* Dobject_prototype_toSource(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { tchar[] buf; int any; //writef("Dobject.prototype.toSource(this = %p, ret = %p)\n", this, ret); buf = "{"; any = 0; foreach (Value key, Property p; *othis.proptable) { if (!(p.attributes & (DontEnum | Deleted))) { if (any) buf ~= ','; any = 1; buf ~= key.toString(); buf ~= ':'; buf ~= p.value.toSource(); } } buf ~= '}'; ret.putVstring(buf); return null; } /* ===================== Dobject_prototype_hasOwnProperty ================ */ void* Dobject_prototype_hasOwnProperty(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.2.4.5 Value* v; v = arglist.length ? &arglist[0] : &vundefined; ret.putVboolean(othis.proptable.hasownproperty(v, 0)); return null; } /* ===================== Dobject_prototype_isPrototypeOf ================ */ void* Dobject_prototype_isPrototypeOf(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.2.4.6 d_boolean result = false; Value* v; Dobject o; v = arglist.length ? &arglist[0] : &vundefined; if (!v.isPrimitive()) { o = v.toObject(); for (;;) { o = o.internal_prototype; if (!o) break; if (o == othis) { result = true; break; } } } ret.putVboolean(result); return null; } /* ===================== Dobject_prototype_propertyIsEnumerable ================ */ void* Dobject_prototype_propertyIsEnumerable(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist) { // ECMA v3 15.2.4.7 Value* v; v = arglist.length ? &arglist[0] : &vundefined; ret.putVboolean(othis.proptable.hasownproperty(v, 1)); return null; } /* ===================== Dobject_prototype ========================= */ class Dobject_prototype : Dobject { this(ThreadContext *tc) { super(null); } } /* ====================== Dobject ======================= */ class Dobject { PropTable* proptable; Dobject internal_prototype; d_string classname; Value value; const uint DOBJECT_SIGNATURE = 0xAA31EE31; uint signature; invariant { assert(signature == DOBJECT_SIGNATURE); } this(Dobject prototype) { //writef("new Dobject = %x, prototype = %x, line = %d, file = '%s'\n", this, prototype, GC.line, ascii2unicode(GC.file)); //writef("Dobject(prototype = %p)\n", prototype); proptable = new PropTable; internal_prototype = prototype; if (prototype) proptable.previous = prototype.proptable; classname = TEXT_Object; value.putVobject(this); signature = DOBJECT_SIGNATURE; } Dobject Prototype() { return internal_prototype; } Value* Get(d_string PropertyName) { return Get(PropertyName, Value.calcHash(PropertyName)); } Value* Get(Identifier* id) { Value* v; //writefln("Dobject.Get(this = %x, '%s', hash = %x)", cast(uint)cast(void*)this, PropertyName, hash); //writef("\tinternal_prototype = %p\n", this.internal_prototype); //writef("\tDfunction.getPrototype() = %p\n", Dfunction.getPrototype()); v = proptable.get(&id.value, id.value.hash); //if (v) writef("found it %p\n", v.object); return v; } Value* Get(d_string PropertyName, uint hash) { Value* v; //writefln("Dobject.Get(this = %x, '%s', hash = %x)", cast(uint)cast(void*)this, PropertyName, hash); //writef("\tinternal_prototype = %p\n", this.internal_prototype); //writef("\tDfunction.getPrototype() = %p\n", Dfunction.getPrototype()); v = proptable.get(PropertyName, hash); //if (v) writef("found it %p\n", v.object); return v; } Value* Get(d_uint32 index) { Value* v; v = proptable.get(index); // if (!v) // v = &vundefined; return v; } Value* Get(d_uint32 index, Value* vindex) { return proptable.get(vindex, Value.calcHash(index)); } Value* Put(d_string PropertyName, Value* value, uint attributes) { // ECMA 8.6.2.2 //writef("Dobject.Put(this = %p)\n", this); proptable.put(PropertyName, value, attributes); return null; } Value* Put(Identifier* key, Value* value, uint attributes) { // ECMA 8.6.2.2 //writef("Dobject.Put(this = %p)\n", this); proptable.put(&key.value, key.value.hash, value, attributes); return null; } Value* Put(d_string PropertyName, Dobject o, uint attributes) { // ECMA 8.6.2.2 Value v; v.putVobject(o); proptable.put(PropertyName, &v, attributes); return null; } Value* Put(d_string PropertyName, d_number n, uint attributes) { // ECMA 8.6.2.2 Value v; v.putVnumber(n); proptable.put(PropertyName, &v, attributes); return null; } Value* Put(d_string PropertyName, d_string s, uint attributes) { // ECMA 8.6.2.2 Value v; v.putVstring(s); proptable.put(PropertyName, &v, attributes); return null; } Value* Put(d_uint32 index, Value* vindex, Value* value, uint attributes) { // ECMA 8.6.2.2 proptable.put(vindex, Value.calcHash(index), value, attributes); return null; } Value* Put(d_uint32 index, Value* value, uint attributes) { // ECMA 8.6.2.2 proptable.put(index, value, attributes); return null; } Value* PutDefault(Value* value) { // Not ECMA, Microsoft extension //writef("Dobject.PutDefault(this = %p)\n", this); ErrInfo errinfo; return RuntimeError(&errinfo, ERR_NO_DEFAULT_PUT); } Value* put_Value(Value* ret, Value[] arglist) { // Not ECMA, Microsoft extension //writef("Dobject.put_Value(this = %p)\n", this); ErrInfo errinfo; return RuntimeError(&errinfo, ERR_FUNCTION_NOT_LVALUE); } int CanPut(d_string PropertyName) { // ECMA 8.6.2.3 return proptable.canput(PropertyName); } int HasProperty(d_string PropertyName) { // ECMA 8.6.2.4 return proptable.hasproperty(PropertyName); } /*********************************** * Return: * TRUE not found or successful delete * FALSE property is marked with DontDelete attribute */ int Delete(d_string PropertyName) { // ECMA 8.6.2.5 //writef("Dobject.Delete('%ls')\n", d_string_ptr(PropertyName)); return proptable.del(PropertyName); } int Delete(d_uint32 index) { // ECMA 8.6.2.5 return proptable.del(index); } int implementsDelete() { // ECMA 8.6.2 says every object implements [[Delete]], // but ECMA 11.4.1 says that some objects may not. // Assume the former is correct. return true; } void *DefaultValue(Value* ret, tchar[] Hint) { Dobject o; Value* v; static d_string*[2] table = [ &TEXT_toString, &TEXT_valueOf ]; int i = 0; // initializer necessary for /W4 // ECMA 8.6.2.6 //writef("Dobject.DefaultValue(ret = %x, Hint = '%s')\n", cast(uint)ret, Hint); if (Hint == TypeString || (Hint == null && this.isDdate())) { i = 0; } else if (Hint == TypeNumber || Hint == null) { i = 1; } else assert(0); for (int j = 0; j < 2; j++) { d_string htab = *table[i]; //writefln("\ti = %d, htab = '%s'", i, htab); v = Get(htab, Value.calcHash(htab)); //writefln("\tv = %x", cast(uint)v); if (v && !v.isPrimitive()) // if it's an Object { void *a; CallContext *cc; //writefln("\tfound default value"); o = v.object; cc = Program.getProgram().callcontext; a = o.Call(cc, this, ret, null); if (a) // if exception was thrown return a; if (ret.isPrimitive()) return null; } i ^= 1; } ret.putVstring(classname); return null; //ErrInfo errinfo; //return RuntimeError(&errinfo, DTEXT("no Default Value for object")); } void *Construct(CallContext *cc, Value *ret, Value[] arglist) { ErrInfo errinfo; return RuntimeError(&errinfo, errmsgtbl[ERR_S_NO_CONSTRUCT], classname); } void *Call(CallContext *cc, Dobject othis, Value* ret, Value[] arglist) { ErrInfo errinfo; return RuntimeError(&errinfo, errmsgtbl[ERR_S_NO_CALL], classname); } void *HasInstance(Value* ret, Value* v) { // ECMA v3 8.6.2 ErrInfo errinfo; return RuntimeError(&errinfo, errmsgtbl[ERR_S_NO_INSTANCE], classname); } d_string getTypeof() { // ECMA 11.4.3 return TEXT_object; } int isClass(d_string classname) { return this.classname == classname; } int isDarray() { return isClass(TEXT_Array); } int isDdate() { return isClass(TEXT_Date); } int isDregexp() { return isClass(TEXT_RegExp); } int isDarguments() { return false; } int isCatch() { return false; } int isFinally() { return false; } void getErrInfo(ErrInfo *perrinfo, int linnum) { ErrInfo errinfo; Value v; v.putVobject(this); errinfo.message = v.toString(); if (perrinfo) *perrinfo = errinfo; } static Value* RuntimeError(ErrInfo *perrinfo, int msgnum) { return RuntimeError(perrinfo, errmsgtbl[msgnum]); } static Value* RuntimeError(ErrInfo *perrinfo, ...) { Dobject o; perrinfo.message = null; void putc(dchar c) { std.utf.encode(perrinfo.message, c); } std.format.doFormat(&putc, _arguments, _argptr); o = new typeerror.D0(perrinfo); Value* v = new Value; v.putVobject(o); return v; } static Value* RangeError(ErrInfo *perrinfo, int msgnum) { return RangeError(perrinfo, errmsgtbl[msgnum]); } static Value* RangeError(ErrInfo *perrinfo, ...) { Dobject o; perrinfo.message = null; void putc(dchar c) { std.utf.encode(perrinfo.message, c); } std.format.doFormat(&putc, _arguments, _argptr); o = new rangeerror.D0(perrinfo); Value* v = new Value; v.putVobject(o); return v; } Value* putIterator(Value* v) { Iterator* i = new Iterator; i.ctor(this); v.putViterator(i); return null; } static Dfunction getConstructor() { ThreadContext *tc = ThreadContext.getThreadContext(); assert(tc); return tc.Dobject_constructor; } static Dobject getPrototype() { ThreadContext *tc = ThreadContext.getThreadContext(); assert(tc); return tc.Dobject_prototype; } static void init(ThreadContext *tc) { tc.Dobject_prototype = new Dobject_prototype(tc); Dfunction.init(tc); tc.Dobject_constructor = new Dobject_constructor(tc); Dobject op = tc.Dobject_prototype; Dobject f = tc.Dfunction_prototype; op.Put(TEXT_constructor, tc.Dobject_constructor, DontEnum); static NativeFunctionData nfd[] = [ { &TEXT_toString, &Dobject_prototype_toString, 0 }, { &TEXT_toLocaleString, &Dobject_prototype_toLocaleString, 0 }, { &TEXT_toSource, &Dobject_prototype_toSource, 0 }, { &TEXT_valueOf, &Dobject_prototype_valueOf, 0 }, { &TEXT_hasOwnProperty, &Dobject_prototype_hasOwnProperty, 1 }, { &TEXT_isPrototypeOf, &Dobject_prototype_isPrototypeOf, 0 }, { &TEXT_propertyIsEnumerable, &Dobject_prototype_propertyIsEnumerable, 0 }, ]; DnativeFunction.init(op, nfd, DontEnum); } } /********************************************* * Initialize the built-in's. */ void dobject_init(ThreadContext *tc) { //writef("dobject_init(tc = %x)\n", cast(uint)tc); if (tc.Dobject_prototype) return; // already initialized for this thread version (none) { writef("sizeof(Dobject) = %d\n", sizeof(Dobject)); writef("sizeof(PropTable) = %d\n", sizeof(PropTable)); writef("offsetof(proptable) = %d\n", offsetof(Dobject, proptable)); writef("offsetof(internal_prototype) = %d\n", offsetof(Dobject, internal_prototype)); writef("offsetof(classname) = %d\n", offsetof(Dobject, classname)); writef("offsetof(value) = %d\n", offsetof(Dobject, value)); } Dobject.init(tc); Dboolean.init(tc); Dstring.init(tc); Dnumber.init(tc); Darray.init(tc); Dmath.init(tc); Ddate.init(tc); Dregexp.init(tc); Derror.init(tc); // Call registered initializer for each object type foreach (void function(ThreadContext*) fpinit; ThreadContext.initTable) (*fpinit)(tc); } void dobject_term(ThreadContext *tc) { //writef("dobject_term(program = %x)\n", tc.program); memset(&tc.program, 0, ThreadContext.sizeof - Thread.sizeof); }