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