0
|
1
|
|
2 /* Digital Mars DMDScript source code.
|
|
3 * Copyright (c) 2000-2002 by Chromium Communications
|
|
4 * D version Copyright (c) 2004-2007 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
|
3
|
22 module dmdscript_tango.functiondefinition;
|
0
|
23
|
4
|
24 //import std.stdio;
|
0
|
25
|
3
|
26 import dmdscript_tango.script;
|
|
27 import dmdscript_tango.identifier;
|
|
28 import dmdscript_tango.statement;
|
|
29 import dmdscript_tango.dfunction;
|
|
30 import dmdscript_tango.scopex;
|
|
31 import dmdscript_tango.irstate;
|
|
32 import dmdscript_tango.opcodes;
|
|
33 import dmdscript_tango.ddeclaredfunction;
|
|
34 import dmdscript_tango.symbol;
|
|
35 import dmdscript_tango.dobject;
|
|
36 import dmdscript_tango.ir;
|
|
37 import dmdscript_tango.textgen.errmsgs;
|
|
38 import dmdscript_tango.value;
|
|
39 import dmdscript_tango.property;
|
0
|
40
|
|
41 /* ========================== FunctionDefinition ================== */
|
|
42
|
|
43 class FunctionDefinition : TopStatement
|
|
44 {
|
|
45 // Maybe the following two should be done with derived classes instead
|
|
46 int isglobal; // !=0 if the global anonymous function
|
|
47 int isanonymous; // !=0 if anonymous function
|
|
48 int iseval; // !=0 if eval function
|
|
49
|
|
50 Identifier* name; // null for anonymous function
|
|
51 Identifier*[] parameters; // array of Identifier's
|
|
52 TopStatement[] topstatements; // array of TopStatement's
|
|
53
|
|
54 Identifier*[] varnames; // array of Identifier's
|
|
55 FunctionDefinition[] functiondefinitions;
|
|
56 FunctionDefinition enclosingFunction;
|
|
57 int nestDepth;
|
|
58 int withdepth; // max nesting of ScopeStatement's
|
|
59
|
|
60 SymbolTable *labtab; // symbol table for LabelSymbol's
|
|
61
|
|
62 IR *code;
|
|
63 uint nlocals;
|
|
64
|
|
65
|
|
66 this(TopStatement[] topstatements)
|
|
67 {
|
|
68 super(0);
|
|
69 st = FUNCTIONDEFINITION;
|
|
70 this.isglobal = 1;
|
|
71 this.topstatements = topstatements;
|
|
72 }
|
|
73
|
|
74 this(Loc loc, int isglobal,
|
|
75 Identifier *name, Identifier*[] parameters,
|
|
76 TopStatement[] topstatements)
|
|
77 {
|
|
78 super(loc);
|
|
79
|
|
80 //writef("FunctionDefinition('%ls')\n", name ? name.string : L"");
|
|
81 st = FUNCTIONDEFINITION;
|
|
82 this.isglobal = isglobal;
|
|
83 this.name = name;
|
|
84 this.parameters = parameters;
|
|
85 this.topstatements = topstatements;
|
|
86 }
|
|
87
|
|
88 Statement semantic(Scope *sc)
|
|
89 {
|
|
90 uint i;
|
|
91 TopStatement ts;
|
|
92 FunctionDefinition fd;
|
|
93
|
|
94 //writef("FunctionDefinition::semantic(%s)\n", this);
|
|
95
|
|
96 // Log all the FunctionDefinition's so we can rapidly
|
|
97 // instantiate them at runtime
|
|
98 fd = enclosingFunction = sc.funcdef;
|
|
99
|
|
100 // But only push it if it is not already in the array
|
|
101 for (i = 0; ; i++)
|
|
102 {
|
|
103 if (i == fd.functiondefinitions.length) // not in the array
|
|
104 { fd.functiondefinitions ~= this;
|
|
105 break;
|
|
106 }
|
|
107 if (fd.functiondefinitions[i] is this) // already in the array
|
|
108 break;
|
|
109 }
|
|
110
|
|
111 //writef("isglobal = %d, isanonymous = %d\n", isglobal, isanonymous);
|
|
112 if (!isglobal && !isanonymous)
|
|
113 { sc = sc.push(this);
|
|
114 sc.nestDepth++;
|
|
115 }
|
|
116 nestDepth = sc.nestDepth;
|
|
117 //writefln("nestDepth = %d", nestDepth);
|
|
118
|
|
119 if (topstatements.length)
|
|
120 {
|
|
121 for (i = 0; i < topstatements.length; i++)
|
|
122 {
|
|
123 ts = topstatements[i];
|
|
124 //writefln("calling semantic routine %d which is %x\n",i, cast(uint)cast(void*)ts);
|
|
125 if (!ts.done)
|
|
126 { ts = ts.semantic(sc);
|
|
127 if (sc.errinfo.message)
|
|
128 break;
|
|
129
|
|
130 if (iseval)
|
|
131 {
|
|
132 // There's an implied "return" on the last statement
|
|
133 if ((i + 1) == topstatements.length)
|
|
134 {
|
|
135 ts = ts.ImpliedReturn();
|
|
136 }
|
|
137 }
|
|
138 topstatements[i] = ts;
|
|
139 ts.done = 1;
|
|
140 }
|
|
141 }
|
|
142
|
|
143 // Make sure all the LabelSymbol's are defined
|
|
144 if (labtab)
|
|
145 {
|
|
146 foreach (Symbol s; labtab.members)
|
|
147 { LabelSymbol ls = cast(LabelSymbol) s;
|
|
148 if (!ls.statement)
|
|
149 error(sc, errmsgtbl[ERR_UNDEFINED_LABEL],
|
|
150 ls.toString(), toString());
|
|
151 }
|
|
152 }
|
|
153 }
|
|
154
|
|
155 if (!isglobal && !isanonymous)
|
|
156 sc.pop();
|
|
157
|
|
158 FunctionDefinition fdx = this;
|
|
159 return cast(Statement)cast(void*)fdx;
|
|
160 }
|
|
161
|
|
162 void toBuffer(inout tchar[] buf)
|
|
163 { uint i;
|
|
164
|
|
165 //writef("FunctionDefinition::toBuffer()\n");
|
|
166 if (!isglobal)
|
|
167 {
|
|
168 buf ~= "function ";
|
|
169 if (isanonymous)
|
|
170 buf ~= "anonymous";
|
|
171 else if (name)
|
|
172 buf ~= name.toString();
|
|
173 buf ~= '(';
|
|
174 for (i = 0; i < parameters.length; i++)
|
|
175 {
|
|
176 if (i)
|
|
177 buf ~= ',';
|
|
178 buf ~= parameters[i].toString();
|
|
179 }
|
|
180 buf ~= ")\n{ \n";
|
|
181 }
|
|
182 if (topstatements)
|
|
183 {
|
|
184 for (i = 0; i < topstatements.length; i++)
|
|
185 {
|
|
186 topstatements[i].toBuffer(buf);
|
|
187 }
|
|
188 }
|
|
189 if (!isglobal)
|
|
190 {
|
|
191 buf ~= "}\n";
|
|
192 }
|
|
193 }
|
|
194
|
|
195 void toIR(IRstate *ignore)
|
|
196 {
|
|
197 IRstate irs;
|
|
198 uint i;
|
|
199
|
|
200 //writefln("FunctionDefinition.toIR() done = %d", done);
|
|
201 irs.ctor();
|
|
202 if (topstatements.length)
|
|
203 {
|
|
204 for (i = 0; i < topstatements.length; i++)
|
|
205 { TopStatement ts;
|
|
206 FunctionDefinition fd;
|
|
207
|
|
208 ts = topstatements[i];
|
|
209 if (ts.st == FUNCTIONDEFINITION)
|
|
210 {
|
|
211 fd = cast(FunctionDefinition)ts;
|
|
212 if (fd.code)
|
|
213 continue;
|
|
214 }
|
|
215 ts.toIR(&irs);
|
|
216 }
|
|
217
|
|
218 // Don't need parse trees anymore, release to garbage collector
|
|
219 topstatements[] = null;
|
|
220 topstatements = null;
|
|
221 labtab = null; // maybe delete it?
|
|
222 }
|
|
223 irs.gen0(0, IRret);
|
|
224 irs.gen0(0, IRend);
|
|
225
|
|
226 //irs.validate();
|
|
227
|
|
228 irs.doFixups();
|
|
229 irs.optimize();
|
|
230
|
|
231 code = cast(IR *) irs.codebuf.data;
|
|
232 irs.codebuf.data = null;
|
|
233 nlocals = irs.nlocals;
|
|
234 }
|
|
235
|
|
236 void instantiate(Dobject[] scopex, Dobject actobj, uint attributes)
|
|
237 {
|
|
238 //writefln("FunctionDefinition.instantiate() %s nestDepth = %d", name ? name.toString() : "", nestDepth);
|
|
239
|
|
240 // Instantiate all the Var's per 10.1.3
|
|
241 foreach (Identifier* name; varnames)
|
|
242 {
|
|
243 // If name is already declared, don't override it
|
|
244 //writefln("\tVar Put(%s)", name.toString());
|
|
245 actobj.Put(name.toString(), &vundefined, Instantiate | DontOverride | attributes);
|
|
246 }
|
|
247
|
|
248 // Instantiate the Function's per 10.1.3
|
|
249 foreach (FunctionDefinition fd; functiondefinitions)
|
|
250 {
|
|
251 // Set [[Scope]] property per 13.2 step 7
|
|
252 Dfunction fobject = new DdeclaredFunction(fd);
|
|
253 fobject.scopex = scopex;
|
|
254
|
|
255 if (fd.name) // skip anonymous functions
|
|
256 {
|
|
257 //writefln("\tFunction Put(%s)", fd.name.toString());
|
|
258 actobj.Put(fd.name.toString(), fobject, Instantiate | attributes);
|
|
259 }
|
|
260 }
|
|
261 //writefln("-FunctionDefinition.instantiate()");
|
|
262 }
|
|
263 }
|