Mercurial > projects > dmdscript-tango
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 } |