0
|
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
|
3
|
22 module dmdscript_tango.program;
|
0
|
23
|
4
|
24 //import std.stdio;
|
|
25 //import std.c.stdlib;
|
|
26 import tango.stdc.stdlib;
|
0
|
27
|
3
|
28 import dmdscript_tango.script;
|
|
29 import dmdscript_tango.dobject;
|
|
30 import dmdscript_tango.dglobal;
|
|
31 import dmdscript_tango.functiondefinition;
|
|
32 import dmdscript_tango.statement;
|
|
33 import dmdscript_tango.threadcontext;
|
|
34 import dmdscript_tango.value;
|
|
35 import dmdscript_tango.opcodes;
|
|
36 import dmdscript_tango.darray;
|
|
37 import dmdscript_tango.parse;
|
|
38 import dmdscript_tango.scopex;
|
|
39 import dmdscript_tango.text;
|
|
40 import dmdscript_tango.property;
|
0
|
41
|
|
42 class Program
|
|
43 {
|
|
44 uint errors; // if any errors in file
|
|
45 CallContext *callcontext;
|
|
46 FunctionDefinition globalfunction;
|
|
47
|
|
48 // Locale info
|
|
49 uint lcid; // current locale
|
|
50 tchar[] slist; // list separator
|
|
51
|
|
52 this()
|
|
53 {
|
|
54 initContext();
|
|
55 }
|
|
56
|
|
57 void initContext()
|
|
58 {
|
|
59 //writefln("Program.initContext()");
|
|
60 if (callcontext) // if already done
|
|
61 return;
|
|
62
|
|
63 callcontext = new CallContext();
|
|
64
|
|
65 CallContext *cc = callcontext;
|
|
66
|
|
67 // Do object inits
|
|
68 ThreadContext *tc = ThreadContext.getThreadContext();
|
|
69 assert(tc);
|
|
70
|
|
71 dobject_init(tc);
|
|
72
|
|
73 cc.prog = this;
|
|
74
|
|
75 // Create global object
|
|
76 cc.global = new Dglobal(null);
|
|
77
|
|
78 Dobject[] scopex;
|
|
79 scopex ~= cc.global;
|
|
80
|
|
81 cc.variable = cc.global;
|
|
82 cc.scopex = scopex;
|
|
83 cc.scoperoot++;
|
|
84 cc.globalroot++;
|
|
85
|
|
86 assert(tc.Ddate_prototype.proptable.table.length != 0);
|
|
87 }
|
|
88
|
|
89 /**************************************************
|
|
90 * Two ways of calling this:
|
|
91 * 1. with text representing group of topstatements (pfd == null)
|
|
92 * 2. with text representing a function name & body (pfd != null)
|
|
93 */
|
|
94
|
|
95 void compile(char[] progIdentifier, tchar[] srctext, FunctionDefinition *pfd)
|
|
96 {
|
|
97 TopStatement[] topstatements;
|
|
98 tchar[] msg;
|
|
99
|
|
100 //writef("parse_common()\n");
|
|
101 Parser p = new Parser(progIdentifier, srctext, 1);
|
|
102
|
|
103 ErrInfo errinfo;
|
|
104 if (p.parseProgram(topstatements, &errinfo))
|
|
105 {
|
|
106 topstatements[] = null;
|
|
107 throw new ScriptException(&errinfo);
|
|
108 }
|
|
109
|
|
110 if (pfd)
|
|
111 { // If we are expecting a function, we should have parsed one
|
|
112 assert(p.lastnamedfunc);
|
|
113 *pfd = p.lastnamedfunc;
|
|
114 }
|
|
115
|
|
116 // Build empty function definition array
|
|
117 // Make globalfunction an anonymous one (by passing in null for name) so
|
|
118 // it won't get instantiated as a property
|
|
119 globalfunction = new FunctionDefinition(0, 1, null, null, null);
|
|
120
|
|
121 // Any functions parsed in topstatements wind up in the global
|
|
122 // object (cc.global), where they are found by normal property lookups.
|
|
123 // Any global new top statements only get executed once, and so although
|
|
124 // the previous group of topstatements gets lost, it does not matter.
|
|
125
|
|
126 // In essence, globalfunction encapsulates the *last* group of topstatements
|
|
127 // passed to script, and any previous version of globalfunction, along with
|
|
128 // previous topstatements, gets discarded.
|
|
129
|
|
130 globalfunction.topstatements = topstatements;
|
|
131
|
|
132 // If pfd, it is not really necessary to create a global function just
|
|
133 // so we can do the semantic analysis, we could use p.lastnamedfunc
|
|
134 // instead if we're careful to insure that p.lastnamedfunc winds up
|
|
135 // as a property of the global object.
|
|
136
|
|
137 Scope sc;
|
|
138 sc.ctor(this, globalfunction); // create global scope
|
|
139 sc.src = srctext;
|
|
140 globalfunction.semantic(&sc);
|
|
141
|
|
142 msg = sc.errinfo.message;
|
|
143 if (msg) // if semantic() failed
|
|
144 {
|
|
145 globalfunction.topstatements[] = null;
|
|
146 globalfunction.topstatements = null;
|
|
147 globalfunction = null;
|
|
148 throw new ScriptException(&sc.errinfo);
|
|
149 }
|
|
150
|
|
151 if (pfd)
|
|
152 // If expecting a function, that is the only topstatement we should
|
|
153 // have had
|
|
154 (*pfd).toIR(null);
|
|
155 else
|
|
156 {
|
|
157 globalfunction.toIR(null);
|
|
158 }
|
|
159
|
|
160 // Don't need parse trees anymore, so null'ing the pointer allows
|
|
161 // the garbage collector to find & free them.
|
|
162 globalfunction.topstatements[] = null;
|
|
163 globalfunction.topstatements = null;
|
|
164 }
|
|
165
|
|
166 /*******************************
|
|
167 * Execute program.
|
|
168 * Throw ScriptException on error.
|
|
169 */
|
|
170
|
|
171 void execute(char[][] args)
|
|
172 {
|
|
173 // ECMA 10.2.1
|
|
174 //writef("Program.execute(argc = %d, argv = %p)\n", argc, argv);
|
|
175 //writef("Program.execute()\n");
|
|
176
|
|
177 initContext();
|
|
178
|
|
179 Value[] locals;
|
|
180 Value ret;
|
|
181 Value* result;
|
|
182 CallContext *cc = callcontext;
|
|
183 Darray arguments;
|
|
184 Dobject dglobal = cc.global;
|
|
185 Program program_save;
|
|
186
|
|
187 // Set argv and argc for execute
|
|
188 arguments = new Darray();
|
|
189 dglobal.Put(TEXT_arguments, arguments, DontDelete | DontEnum);
|
|
190 arguments.length.putVnumber(args.length);
|
|
191 for (int i = 0; i < args.length; i++)
|
|
192 {
|
|
193 arguments.Put(i, args[i], DontEnum);
|
|
194 }
|
|
195
|
|
196 Value[] p1;
|
|
197 Value* v;
|
|
198 version (Win32) // eh and alloca() not working under linux
|
|
199 {
|
|
200 if (globalfunction.nlocals < 128)
|
|
201 v = cast(Value*)alloca(globalfunction.nlocals * Value.sizeof);
|
|
202 }
|
|
203 if (v)
|
|
204 locals = v[0 .. globalfunction.nlocals];
|
|
205 else
|
|
206 {
|
|
207 p1 = new Value[globalfunction.nlocals];
|
|
208 locals = p1;
|
|
209 }
|
|
210
|
|
211 // Instantiate global variables as properties of global
|
|
212 // object with 0 attributes
|
|
213 globalfunction.instantiate(cc.scopex, cc.variable, 0);
|
|
214
|
|
215 // cc.scopex.reserve(globalfunction.withdepth + 1);
|
|
216
|
|
217 // The 'this' value is the global object
|
|
218 //printf("cc.scopex.ptr = %x, cc.scopex.length = %d\n", cc.scopex.ptr, cc.scopex.length);
|
|
219 program_save = getProgram();
|
|
220 try
|
|
221 {
|
|
222 setProgram(this);
|
|
223 ret.putVundefined();
|
|
224 result = cast(Value*)IR.call(cc, cc.global, globalfunction.code, &ret, locals.ptr);
|
|
225 }
|
|
226 finally
|
|
227 {
|
|
228 setProgram(program_save);
|
|
229 }
|
|
230 //writef("-Program.execute()\n");
|
|
231 if (result)
|
|
232 {
|
|
233 ErrInfo errinfo;
|
|
234
|
|
235 result.getErrInfo(&errinfo, cc.linnum);
|
|
236 cc.linnum = 0;
|
|
237 delete p1;
|
|
238 throw new ScriptException(&errinfo);
|
|
239 }
|
|
240
|
|
241 delete p1;
|
|
242 }
|
|
243
|
|
244 void toBuffer(inout tchar[] buf)
|
|
245 {
|
|
246 if (globalfunction)
|
|
247 globalfunction.toBuffer(buf);
|
|
248 }
|
|
249
|
|
250 /***********************************************
|
|
251 * Get/Set Program associated with this thread.
|
|
252 * This enables multiple scripts (Programs) running simultaneously
|
|
253 * in different threads.
|
|
254 * It is needed because which Program is being run is essentially
|
|
255 * global data - and this makes it thread local data.
|
|
256 */
|
|
257
|
|
258 static Program getProgram()
|
|
259 {
|
|
260 ThreadContext *tc;
|
|
261
|
|
262 tc = ThreadContext.getThreadContext();
|
|
263 assert(tc != null);
|
|
264 return tc.program;
|
|
265 }
|
|
266
|
|
267 static void setProgram(Program p)
|
|
268 {
|
|
269 ThreadContext *tc;
|
|
270
|
|
271 tc = ThreadContext.getThreadContext();
|
|
272
|
|
273 assert(tc != null);
|
|
274 tc.program = p;
|
|
275 }
|
|
276
|
|
277 }
|