comparison dmdscript_tango/dfunction.d @ 0:55c2951c07be

initial, files origin, premoved tree
author saaadel
date Sun, 24 Jan 2010 12:34:47 +0200
parents
children 8363a4bf6a8f
comparison
equal deleted inserted replaced
-1:000000000000 0:55c2951c07be
1
2 /* Digital Mars DMDScript source code.
3 * Copyright (c) 2000-2002 by Chromium Communications
4 * D version Copyright (c) 2004-2005 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.dfunction;
23
24 import std.string;
25 import std.c.stdlib;
26
27 import dmdscript.script;
28 import dmdscript.dobject;
29 import dmdscript.value;
30 import dmdscript.protoerror;
31 import dmdscript.threadcontext;
32 import dmdscript.text;
33 import dmdscript.errmsgs;
34 import dmdscript.property;
35 import dmdscript.scopex;
36 import dmdscript.dnative;
37 import dmdscript.functiondefinition;
38 import dmdscript.parse;
39 import dmdscript.ddeclaredfunction;
40
41 /* ===================== Dfunction_constructor ==================== */
42
43 class Dfunction_constructor : Dfunction
44 {
45 this(ThreadContext *tc)
46 {
47 super(1, tc.Dfunction_prototype);
48
49 // Actually put in later by Dfunction::init()
50 //unsigned attributes = DontEnum | DontDelete | ReadOnly;
51 //Put(TEXT_prototype, Dfunction::getPrototype(), attributes);
52 }
53
54 void *Construct(CallContext *cc, Value *ret, Value[] arglist)
55 {
56 // ECMA 15.3.2.1
57 d_string bdy;
58 d_string P;
59 FunctionDefinition fd;
60 ErrInfo errinfo;
61
62 //writef("Dfunction_constructor::Construct()\n");
63
64 // Get parameter list (P) and body from arglist[]
65 if (arglist.length)
66 {
67 bdy = arglist[arglist.length - 1].toString();
68 if (arglist.length >= 2)
69 {
70 for (uint a = 0; a < arglist.length - 1; a++)
71 {
72 if (a)
73 P ~= ',';
74 P ~= arglist[a].toString();
75 }
76 }
77 }
78
79 if (Parser.parseFunctionDefinition(fd, P, bdy, errinfo))
80 goto Lsyntaxerror;
81
82 if (fd)
83 {
84 Scope sc;
85
86 sc.ctor(fd);
87 fd.semantic(&sc);
88 errinfo = sc.errinfo;
89 if (errinfo.message)
90 goto Lsyntaxerror;
91 fd.toIR(null);
92 Dfunction fobj = new DdeclaredFunction(fd);
93 ret.putVobject(fobj);
94 }
95 else
96 ret.putVundefined();
97
98 return null;
99
100 Lsyntaxerror:
101 Dobject o;
102
103 ret.putVundefined();
104 o = new syntaxerror.D0(&errinfo);
105 Value* v = new Value;
106 v.putVobject(o);
107 return v;
108 }
109
110 void *Call(CallContext *cc, Dobject othis, Value* ret, Value[] arglist)
111 {
112 // ECMA 15.3.1
113 return Construct(cc, ret, arglist);
114 }
115 }
116
117
118 /* ===================== Dfunction_prototype_toString =============== */
119
120 void* Dfunction_prototype_toString(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist)
121 {
122 d_string s;
123 Dfunction f;
124
125 //writef("function.prototype.toString()\n");
126 // othis must be a Function
127 if (!othis.isClass(TEXT_Function))
128 { ErrInfo errinfo;
129 ret.putVundefined();
130 return Dobject.RuntimeError(&errinfo, ERR_TS_NOT_TRANSFERRABLE);
131 }
132 else
133 {
134 // Generate string that looks like a FunctionDeclaration
135 // FunctionDeclaration:
136 // function Identifier (Identifier, ...) Block
137
138 // If anonymous function, the name should be "anonymous"
139 // per ECMA 15.3.2.1.19
140
141 f = cast(Dfunction)othis;
142 s = f.toString();
143 ret.putVstring(s);
144 }
145 return null;
146 }
147
148 /* ===================== Dfunction_prototype_apply =============== */
149
150 void* Dfunction_prototype_apply(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist)
151 {
152 // ECMA v3 15.3.4.3
153
154 Value* thisArg;
155 Value* argArray;
156 Dobject o;
157 void* v;
158
159 thisArg = &vundefined;
160 argArray = &vundefined;
161 switch (arglist.length)
162 {
163 case 0:
164 break;
165 default:
166 argArray = &arglist[1];
167 case 1:
168 thisArg = &arglist[0];
169 break;
170 }
171
172 if (thisArg.isUndefinedOrNull())
173 o = cc.global;
174 else
175 o = thisArg.toObject();
176
177 if (argArray.isUndefinedOrNull())
178 {
179 v = othis.Call(cc, o, ret, null);
180 }
181 else
182 {
183 if (argArray.isPrimitive())
184 {
185 Ltypeerror:
186 ret.putVundefined();
187 ErrInfo errinfo;
188 return Dobject.RuntimeError(&errinfo, ERR_ARRAY_ARGS);
189 }
190 Dobject a;
191
192 a = argArray.toObject();
193
194 // Must be array or arguments object
195 if (!a.isDarray() && !a.isDarguments())
196 goto Ltypeerror;
197
198 uint len;
199 uint i;
200 Value[] alist;
201 Value* x;
202
203 x = a.Get(TEXT_length);
204 len = x ? x.toUint32() : 0;
205
206 Value[] p1;
207 Value* v1;
208 if (len < 128)
209 v1 = cast(Value*)alloca(len * Value.sizeof);
210 if (v1)
211 alist = v1[0 .. len];
212 else
213 { p1 = new Value[len];
214 alist = p1;
215 }
216
217 for (i = 0; i < len; i++)
218 {
219 x = a.Get(i);
220 Value.copy(&alist[i], x);
221 }
222
223 v = othis.Call(cc, o, ret, alist);
224
225 delete p1;
226 }
227 return v;
228 }
229
230 /* ===================== Dfunction_prototype_call =============== */
231
232 void* Dfunction_prototype_call(Dobject pthis, CallContext *cc, Dobject othis, Value *ret, Value[] arglist)
233 {
234 // ECMA v3 15.3.4.4
235 Value* thisArg;
236 Dobject o;
237 void* v;
238
239 if (arglist.length == 0)
240 {
241 o = cc.global;
242 v = othis.Call(cc, o, ret, arglist);
243 }
244 else
245 {
246 thisArg = &arglist[0];
247 if (thisArg.isUndefinedOrNull())
248 o = cc.global;
249 else
250 o = thisArg.toObject();
251 v = othis.Call(cc, o, ret, arglist[1 .. length]);
252 }
253 return v;
254 }
255
256 /* ===================== Dfunction_prototype ==================== */
257
258 class Dfunction_prototype : Dfunction
259 {
260 this(ThreadContext *tc)
261 {
262 super(0, tc.Dobject_prototype);
263
264 uint attributes = DontEnum;
265
266 classname = TEXT_Function;
267 name = "prototype";
268 Put(TEXT_constructor, tc.Dfunction_constructor, attributes);
269
270 static NativeFunctionData nfd[] =
271 [
272 { &TEXT_toString, &Dfunction_prototype_toString, 0 },
273 { &TEXT_apply, &Dfunction_prototype_apply, 2 },
274 { &TEXT_call, &Dfunction_prototype_call, 1 },
275 ];
276
277 DnativeFunction.init(this, nfd, attributes);
278 }
279
280 void *Call(CallContext *cc, Dobject othis, Value* ret, Value[] arglist)
281 {
282 // ECMA v3 15.3.4
283 // Accept any arguments and return "undefined"
284 ret.putVundefined();
285 return null;
286 }
287 }
288
289
290 /* ===================== Dfunction ==================== */
291
292 class Dfunction : Dobject
293 { tchar[] name;
294 Dobject[] scopex; // Function object's scope chain per 13.2 step 7
295
296 this(d_uint32 length)
297 {
298 this(length, Dfunction.getPrototype());
299 }
300
301 this(d_uint32 length, Dobject prototype)
302 {
303 super(prototype);
304 classname = TEXT_Function;
305 name = TEXT_Function;
306 Put(TEXT_length, length, DontDelete | DontEnum | ReadOnly);
307 Put(TEXT_arity, length, DontDelete | DontEnum | ReadOnly);
308 }
309
310 d_string getTypeof()
311 { // ECMA 11.4.3
312 return TEXT_function;
313 }
314
315 d_string toString()
316 {
317 // Native overrides of this function replace Identifier with the actual name.
318 // Don't need to do parameter list, though.
319 d_string s;
320
321 s = std.string.format("function %s() { [native code] }", name);
322 return s;
323 }
324
325 void *HasInstance(Value* ret, Value* v)
326 {
327 // ECMA v3 15.3.5.3
328 Dobject V;
329 Value* w;
330 Dobject o;
331
332 if (v.isPrimitive())
333 goto Lfalse;
334 V = v.toObject();
335 w = Get(TEXT_prototype);
336 if (w.isPrimitive())
337 { ErrInfo errinfo;
338 return RuntimeError(&errinfo, errmsgtbl[ERR_MUST_BE_OBJECT], w.getType());
339 }
340 o = w.toObject();
341 for (;;)
342 {
343 V = V.internal_prototype;
344 if (!V)
345 goto Lfalse;
346 if (o == V)
347 goto Ltrue;
348 }
349
350 Ltrue:
351 ret.putVboolean(true);
352 return null;
353
354 Lfalse:
355 ret.putVboolean(false);
356 return null;
357 }
358
359 static Dfunction isFunction(Value* v)
360 {
361 Dfunction r;
362 Dobject o;
363
364 r = null;
365 if (!v.isPrimitive())
366 {
367 o = v.toObject();
368 if (o.isClass(TEXT_Function))
369 r = cast(Dfunction)o;
370 }
371 return r;
372 }
373
374
375 static Dfunction getConstructor()
376 {
377 ThreadContext *tc = ThreadContext.getThreadContext();
378 assert(tc);
379 return tc.Dfunction_constructor;
380 }
381
382 static Dobject getPrototype()
383 {
384 ThreadContext *tc = ThreadContext.getThreadContext();
385 assert(tc);
386 return tc.Dfunction_prototype;
387 }
388
389 static void init(ThreadContext *tc)
390 {
391 tc.Dfunction_constructor = new Dfunction_constructor(tc);
392 tc.Dfunction_prototype = new Dfunction_prototype(tc);
393
394 tc.Dfunction_constructor.Put(TEXT_prototype, tc.Dfunction_prototype, DontEnum | DontDelete | ReadOnly);
395
396 tc.Dfunction_constructor.internal_prototype = tc.Dfunction_prototype;
397 tc.Dfunction_constructor.proptable.previous = tc.Dfunction_prototype.proptable;
398 }
399 }