diff dmdscript_tango/dobject.d @ 0:55c2951c07be

initial, files origin, premoved tree
author saaadel
date Sun, 24 Jan 2010 12:34:47 +0200
parents
children 8363a4bf6a8f
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmdscript_tango/dobject.d	Sun Jan 24 12:34:47 2010 +0200
@@ -0,0 +1,693 @@
+
+/* 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.dobject;
+
+import std.string;
+import std.c.stdarg;
+import std.c.string;
+
+import dmdscript.script;
+import dmdscript.value;
+import dmdscript.dfunction;
+import dmdscript.property;
+import dmdscript.threadcontext;
+import dmdscript.iterator;
+import dmdscript.identifier;
+import dmdscript.errmsgs;
+import dmdscript.text;
+import dmdscript.program;
+
+import dmdscript.dboolean;
+import dmdscript.dstring;
+import dmdscript.dnumber;
+import dmdscript.darray;
+import dmdscript.dmath;
+import dmdscript.ddate;
+import dmdscript.dregexp;
+import dmdscript.derror;
+import dmdscript.dnative;
+
+import dmdscript.protoerror;
+int* pfoo = &dmdscript.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);
+}