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 }