0
|
1
|
|
2 /* Digital Mars DMDScript source code.
|
|
3 * Copyright (c) 2000-2002 by Chromium Communications
|
|
4 * D version Copyright (c) 2004-2006 by Digital Mars
|
|
5 * All Rights Reserved
|
|
6 * written by Walter Bright
|
|
7 * www.digitalmars.com
|
|
8 * Use at your own risk. There is no warranty, express or implied.
|
|
9 * License for redistribution is by the GNU General Public License in gpl.txt.
|
|
10 *
|
|
11 * A binary, non-exclusive license for commercial use can be
|
|
12 * purchased from www.digitalmars.com/dscript/buy.html.
|
|
13 *
|
|
14 * DMDScript is implemented in the D Programming Language,
|
|
15 * www.digitalmars.com/d/
|
|
16 *
|
|
17 * For a C++ implementation of DMDScript, including COM support,
|
|
18 * see www.digitalmars.com/dscript/cppscript.html.
|
|
19 */
|
|
20
|
|
21
|
|
22 module dmdscript.ddeclaredfunction;
|
|
23
|
|
24 import std.stdio;
|
|
25 import std.c.stdlib;
|
|
26
|
|
27 import dmdscript.script;
|
|
28 import dmdscript.dobject;
|
|
29 import dmdscript.dfunction;
|
|
30 import dmdscript.darguments;
|
|
31 import dmdscript.opcodes;
|
|
32 import dmdscript.ir;
|
|
33 import dmdscript.identifier;
|
|
34 import dmdscript.value;
|
|
35 import dmdscript.functiondefinition;
|
|
36 import dmdscript.text;
|
|
37 import dmdscript.property;
|
|
38
|
|
39 /* ========================== DdeclaredFunction ================== */
|
|
40
|
|
41 class DdeclaredFunction : Dfunction
|
|
42 {
|
|
43 FunctionDefinition fd;
|
|
44
|
|
45 this(FunctionDefinition fd)
|
|
46 {
|
|
47 super(fd.parameters.length, Dfunction.getPrototype());
|
|
48 assert(Dfunction.getPrototype());
|
|
49 assert(internal_prototype);
|
|
50 this.fd = fd;
|
|
51
|
|
52 Dobject o;
|
|
53
|
|
54 // ECMA 3 13.2
|
|
55 o = new Dobject(Dobject.getPrototype()); // step 9
|
|
56 Put(TEXT_prototype, o, DontEnum); // step 11
|
|
57 o.Put(TEXT_constructor, this, DontEnum); // step 10
|
|
58 }
|
|
59
|
|
60 void *Call(CallContext *cc, Dobject othis, Value* ret, Value[] arglist)
|
|
61 {
|
|
62 // 1. Create activation object per ECMA 10.1.6
|
|
63 // 2. Instantiate function variables as properties of
|
|
64 // activation object
|
|
65 // 3. The 'this' value is the activation object
|
|
66
|
|
67 Dobject actobj; // activation object
|
|
68 Darguments args;
|
|
69 Value[] locals;
|
|
70 uint i;
|
|
71 void *result;
|
|
72
|
|
73 //writefln("DdeclaredFunction.Call() '%s'", toString());
|
|
74 //writefln("this.scopex.length = %d", this.scopex.length);
|
|
75 //writefln("\tinstantiate(this = %x, fd = %x)", cast(uint)cast(void*)this, cast(uint)cast(void*)fd);
|
|
76
|
|
77 // if it's an empty function, just return
|
|
78 if (fd.code[0].opcode == IRret)
|
|
79 {
|
|
80 return null;
|
|
81 }
|
|
82
|
|
83 // Generate the activation object
|
|
84 // ECMA v3 10.1.6
|
|
85 actobj = new Dobject(null);
|
|
86
|
|
87 // Instantiate the parameters
|
|
88 {
|
|
89 uint a = 0;
|
|
90 foreach (Identifier* p; fd.parameters)
|
|
91 {
|
|
92 Value* v = (a < arglist.length) ? &arglist[a++] : &vundefined;
|
|
93 actobj.Put(p.toString(), v, DontDelete);
|
|
94 }
|
|
95 }
|
|
96
|
|
97 // Generate the Arguments Object
|
|
98 // ECMA v3 10.1.8
|
|
99 args = new Darguments(cc.caller, this, actobj, fd.parameters, arglist);
|
|
100
|
|
101 actobj.Put(TEXT_arguments, args, DontDelete);
|
|
102
|
|
103 // The following is not specified by ECMA, but seems to be supported
|
|
104 // by jscript. The url www.grannymail.com has the following code
|
|
105 // which looks broken to me but works in jscript:
|
|
106 //
|
|
107 // function MakeArray() {
|
|
108 // this.length = MakeArray.arguments.length
|
|
109 // for (var i = 0; i < this.length; i++)
|
|
110 // this[i+1] = arguments[i]
|
|
111 // }
|
|
112 // var cardpic = new MakeArray("LL","AP","BA","MB","FH","AW","CW","CV","DZ");
|
|
113 Put(TEXT_arguments, args, DontDelete); // make grannymail bug work
|
|
114
|
|
115 auto scoperootsave = cc.scoperoot;
|
|
116
|
|
117 /* If calling a nested function, need to increase scoperoot
|
|
118 */
|
|
119 if (fd.enclosingFunction == cc.callerf)
|
|
120 { assert(cc.scoperoot < cc.scopex.length);
|
|
121 cc.scoperoot++;
|
|
122 }
|
|
123 else
|
|
124 {
|
|
125 auto df = cast(DdeclaredFunction)cc.caller;
|
|
126 if (df && !fd.isanonymous)
|
|
127 {
|
|
128 version (none)
|
|
129 {
|
|
130 writefln("current nestDepth = %d, calling %d, cc.scopex.length = %d",
|
|
131 df.fd.nestDepth,
|
|
132 fd.nestDepth,
|
|
133 cc.scopex.length);
|
|
134 }
|
|
135 int diff = df.fd.nestDepth - fd.nestDepth;
|
|
136 if (diff > 0)
|
|
137 { if (diff >= cc.scoperoot)
|
|
138 writefln("diff %s cc.scoperoot %s", diff, cc.scoperoot);
|
|
139 else
|
|
140 cc.scoperoot -= diff;
|
|
141 assert(cc.scoperoot >= 1);
|
|
142 }
|
|
143 }
|
|
144 }
|
|
145
|
|
146 Dobject[] scopesave = cc.scopex;
|
|
147
|
|
148 Dobject[] scopex;
|
|
149 //scopex = cc.scopex[0 .. cc.scoperoot].dup;
|
|
150 scopex = this.scopex.dup;
|
|
151 if (scopex.length == 0)
|
|
152 { this.scopex = cc.scopex[0 .. cc.scoperoot];
|
|
153 scopex = this.scopex.dup;
|
|
154 }
|
|
155 scopex ~= actobj;
|
|
156
|
|
157 fd.instantiate(scopex, actobj, DontDelete);
|
|
158
|
|
159 cc.scopex = scopex;
|
|
160 Dobject variablesave = cc.variable;
|
|
161 cc.variable = actobj;
|
|
162 auto callersave = cc.caller;
|
|
163 cc.caller = this;
|
|
164 auto callerfsave = cc.callerf;
|
|
165 cc.callerf = fd;
|
|
166
|
|
167 Value[] p1;
|
|
168 Value* v;
|
|
169 if (fd.nlocals < 128)
|
|
170 v = cast(Value*) alloca(fd.nlocals * Value.sizeof);
|
|
171 if (v)
|
|
172 locals = v[0 .. fd.nlocals];
|
|
173 else
|
|
174 {
|
|
175 p1 = new Value[fd.nlocals];
|
|
176 locals = p1;
|
|
177 }
|
|
178
|
|
179 result = IR.call(cc, othis, fd.code, ret, locals.ptr);
|
|
180
|
|
181 delete p1;
|
|
182
|
|
183 cc.callerf = callerfsave;
|
|
184 cc.caller = callersave;
|
|
185 cc.variable = variablesave;
|
|
186 cc.scopex = scopesave;
|
|
187 cc.scoperoot = scoperootsave;
|
|
188
|
|
189 // Remove the arguments object
|
|
190 //Value* v;
|
|
191 //v=Get(TEXT_arguments);
|
|
192 //writef("1v = %x, %s, v.object = %x\n", v, v.getType(), v.object);
|
|
193 Put(TEXT_arguments, &vundefined, 0);
|
|
194 //actobj.Put(TEXT_arguments, &vundefined, 0);
|
|
195
|
|
196 version (none)
|
|
197 {
|
|
198 writef("args = %x, actobj = %x\n", args, actobj);
|
|
199 v=Get(TEXT_arguments);
|
|
200 writef("2v = %x, %s, v.object = %x\n", v, v.getType(), v.object);
|
|
201 v.object = null;
|
|
202
|
|
203 {
|
|
204 uint *p = cast(uint *)0x40a49a80;
|
|
205 uint i;
|
|
206 for (i = 0; i < 16; i++)
|
|
207 {
|
|
208 writef("p[%x] = %x\n", &p[i], p[i]);
|
|
209 }
|
|
210 }
|
|
211 }
|
|
212
|
|
213 return result;
|
|
214 }
|
|
215
|
|
216 void *Construct(CallContext *cc, Value *ret, Value[] arglist)
|
|
217 {
|
|
218 // ECMA 3 13.2.2
|
|
219 Dobject othis;
|
|
220 Dobject proto;
|
|
221 Value* v;
|
|
222 void *result;
|
|
223
|
|
224 v = Get(TEXT_prototype);
|
|
225 if (v.isPrimitive())
|
|
226 proto = Dobject.getPrototype();
|
|
227 else
|
|
228 proto = v.toObject();
|
|
229 othis = new Dobject(proto);
|
|
230 result = Call(cc, othis, ret, arglist);
|
|
231 if (!result)
|
|
232 {
|
|
233 if (ret.isPrimitive())
|
|
234 ret.putVobject(othis);
|
|
235 }
|
|
236 return result;
|
|
237 }
|
|
238
|
|
239 d_string toString()
|
|
240 {
|
|
241 d_string s;
|
|
242
|
|
243 //writef("DdeclaredFunction.toString()\n");
|
|
244 fd.toBuffer(s);
|
|
245 return s;
|
|
246 }
|
|
247 }
|
|
248
|
|
249
|