Rev 1913 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1913 | jaeger | 1 | |
2 | int i; |
||
3 | tp_vm *tp = (tp_vm*)tp_malloc(sizeof(tp_vm)); |
||
4 | tp->cur = 0; |
||
5 | tp->jmp = 0; |
||
6 | tp->ex = tp_None; |
||
7 | tp->root = tp_list(0); |
||
8 | for (i=0; i<256; i++) { tp->chars[i][0]=i; } |
||
9 | tp_gc_init(tp); |
||
10 | tp->_regs = tp_list(tp); |
||
11 | for (i=0; i |
||
12 | tp->builtins = tp_dict(tp); |
||
13 | tp->modules = tp_dict(tp); |
||
14 | tp->_params = tp_list(tp); |
||
15 | for (i=0; i |
||
16 | tp_set(tp,tp->root,tp_None,tp->builtins); |
||
17 | tp_set(tp,tp->root,tp_None,tp->modules); |
||
18 | tp_set(tp,tp->root,tp_None,tp->_regs); |
||
19 | tp_set(tp,tp->root,tp_None,tp->_params); |
||
20 | tp_set(tp,tp->builtins,tp_string("MODULES"),tp->modules); |
||
21 | tp_set(tp,tp->modules,tp_string("BUILTINS"),tp->builtins); |
||
22 | tp_set(tp,tp->builtins,tp_string("BUILTINS"),tp->builtins); |
||
23 | tp->regs = tp->_regs.list.val->items; |
||
24 | tp_full(tp); |
||
25 | return tp; |
||
26 | } |
||
27 | |||
28 | |||
29 | while (tp->root.list.val->len) { |
||
30 | _tp_list_pop(tp,tp->root.list.val,0,"tp_deinit"); |
||
31 | } |
||
32 | tp_full(tp); tp_full(tp); |
||
33 | tp_delete(tp,tp->root); |
||
34 | tp_gc_deinit(tp); |
||
35 | tp_free(tp); |
||
36 | } |
||
37 | |||
38 | |||
39 | |||
40 | void tp_frame(TP,tp_obj globals,tp_code *codes,tp_obj *ret_dest) { |
||
41 | tp_frame_ f; |
||
42 | f.globals = globals; |
||
43 | f.codes = codes; |
||
44 | f.cur = f.codes; |
||
45 | f.jmp = 0; |
||
46 | /* fprintf(stderr,"tp->cur: %d\n",tp->cur);*/ |
||
47 | f.regs = (tp->cur <= 0?tp->regs:tp->frames[tp->cur].regs+tp->frames[tp->cur].cregs); |
||
48 | f.ret_dest = ret_dest; |
||
49 | f.lineno = 0; |
||
50 | f.line = tp_string(""); |
||
51 | f.name = tp_string("?"); |
||
52 | f.fname = tp_string("?"); |
||
53 | f.cregs = 0; |
||
54 | /* return f;*/ |
||
55 | if (f.regs+256 >= tp->regs+TP_REGS || tp->cur >= TP_FRAMES-1) { tp_raise(,"tp_frame: stack overflow %d",tp->cur); } |
||
56 | tp->cur += 1; |
||
57 | tp->frames[tp->cur] = f; |
||
58 | } |
||
59 | |||
60 | |||
61 | if (!tp || !tp->jmp) { |
||
62 | con_printf("\nException:\n%s\n",TP_CSTR(e)); |
||
63 | exit(-1); |
||
64 | return; |
||
65 | } |
||
66 | if (e.type != TP_NONE) { tp->ex = e; } |
||
67 | tp_grey(tp,e); |
||
68 | longjmp(tp->buf,1); |
||
69 | } |
||
70 | |||
71 | |||
72 | int i; |
||
73 | con_printf("\n"); |
||
74 | for (i=0; i<=tp->cur; i++) { |
||
75 | if (!tp->frames[i].lineno) { continue; } |
||
76 | con_printf("File \"%s\", line %d, in %s\n %s\n", |
||
77 | TP_CSTR(tp->frames[i].fname),tp->frames[i].lineno, |
||
78 | TP_CSTR(tp->frames[i].name),TP_CSTR(tp->frames[i].line)); |
||
79 | } |
||
80 | con_printf("\nException:\n%s\n",TP_CSTR(tp->ex)); |
||
81 | } |
||
82 | |||
83 | |||
84 | |||
85 | |||
86 | int i; |
||
87 | for (i=tp->cur; i>=0; i--) { |
||
88 | if (tp->frames[i].jmp) { break; } |
||
89 | } |
||
90 | if (i >= 0) { |
||
91 | tp->cur = i; |
||
92 | tp->frames[i].cur = tp->frames[i].jmp; |
||
93 | tp->frames[i].jmp = 0; |
||
94 | return; |
||
95 | } |
||
96 | tp_print_stack(tp); |
||
97 | exit(-1); |
||
98 | } |
||
99 | |||
100 | |||
101 | /*con_printf("_tp_call %s %s\n",TP_CSTR(fnc), TP_CSTR(params));*/ |
||
102 | if (fnc.type == TP_DICT) { |
||
103 | _tp_call(tp,dest,tp_get(tp,fnc,tp_string("__call__")),params); |
||
104 | return; |
||
105 | } |
||
106 | if (fnc.type == TP_FNC && !(fnc.fnc.ftype&1)) { |
||
107 | *dest = _tp_tcall(tp,fnc); |
||
108 | tp_grey(tp,*dest); |
||
109 | return; |
||
110 | } |
||
111 | if (fnc.type == TP_FNC) { |
||
112 | tp_frame(tp,fnc.fnc.info->globals,(tp_code*)fnc.fnc.val,dest); |
||
113 | if ((fnc.fnc.ftype&2)) { |
||
114 | tp->frames[tp->cur].regs[0] = params; |
||
115 | _tp_list_insert(tp,params.list.val,0,fnc.fnc.info->self); |
||
116 | } else { |
||
117 | tp->frames[tp->cur].regs[0] = params; |
||
118 | } |
||
119 | return; |
||
120 | } |
||
121 | tp_params_v(tp,1,fnc); tp_print(tp); |
||
122 | tp_raise(,"tp_call: %s is not callable",TP_CSTR(fnc)); |
||
123 | } |
||
124 | |||
125 | |||
126 | |||
127 | tp_obj *dest = tp->frames[tp->cur].ret_dest; |
||
128 | if (dest) { *dest = v; tp_grey(tp,v); } |
||
129 | /* memset(tp->frames[tp->cur].regs,0,TP_REGS_PER_FRAME*sizeof(tp_obj)); |
||
130 | fprintf(stderr,"regs:%d\n",(tp->frames[tp->cur].cregs+1));*/ |
||
131 | memset(tp->frames[tp->cur].regs,0,tp->frames[tp->cur].cregs*sizeof(tp_obj)); |
||
132 | tp->cur -= 1; |
||
133 | } |
||
134 | |||
135 | |||
136 | TP_IEOF,TP_IADD,TP_ISUB,TP_IMUL,TP_IDIV,TP_IPOW,TP_IAND,TP_IOR,TP_ICMP,TP_IGET,TP_ISET, |
||
137 | TP_INUMBER,TP_ISTRING,TP_IGGET,TP_IGSET,TP_IMOVE,TP_IDEF,TP_IPASS,TP_IJUMP,TP_ICALL, |
||
138 | TP_IRETURN,TP_IIF,TP_IDEBUG,TP_IEQ,TP_ILE,TP_ILT,TP_IDICT,TP_ILIST,TP_INONE,TP_ILEN, |
||
139 | TP_ILINE,TP_IPARAMS,TP_IIGET,TP_IFILE,TP_INAME,TP_INE,TP_IHAS,TP_IRAISE,TP_ISETJMP, |
||
140 | TP_IMOD,TP_ILSH,TP_IRSH,TP_IITER,TP_IDEL,TP_IREGS, |
||
141 | TP_ITOTAL |
||
142 | }; |
||
143 | |||
144 | |||
145 | "EOF","ADD","SUB","MUL","DIV","POW","AND","OR","CMP","GET","SET","NUM", |
||
146 | "STR","GGET","GSET","MOVE","DEF","PASS","JUMP","CALL","RETURN","IF","DEBUG", |
||
147 | "EQ","LE","LT","DICT","LIST","NONE","LEN","LINE","PARAMS","IGET","FILE", |
||
148 | "NAME","NE","HAS","RAISE","SETJMP","MOD","LSH","RSH","ITER","DEL","REGS", |
||
149 | };*/ |
||
150 | |||
151 | |||
152 | #define VB ((int)e.regs.b) |
||
153 | #define VC ((int)e.regs.c) |
||
154 | #define RA regs[e.regs.a] |
||
155 | #define RB regs[e.regs.b] |
||
156 | #define RC regs[e.regs.c] |
||
157 | #define UVBC (unsigned short)(((VB<<8)+VC)) |
||
158 | #define SVBC (short)(((VB<<8)+VC)) |
||
159 | #define GA tp_grey(tp,RA) |
||
160 | #define SR(v) f->cur = cur; return(v); |
||
161 | |||
162 | |||
163 | tp_frame_ *f = &tp->frames[tp->cur]; |
||
164 | tp_obj *regs = f->regs; |
||
165 | tp_code *cur = f->cur; |
||
166 | while(1) { |
||
167 | tp_code e = *cur; |
||
168 | /* fprintf(stderr,"%2d.%4d: %-6s %3d %3d %3d\n",tp->cur,cur-f->codes,tp_strings[e.i],VA,VB,VC); |
||
169 | int i; for(i=0;i<16;i++) { fprintf(stderr,"%d: %s\n",i,TP_CSTR(regs[i])); }*/ |
||
170 | switch (e.i) { |
||
171 | case TP_IEOF: tp_return(tp,tp_None); SR(0); break; |
||
172 | case TP_IADD: RA = tp_add(tp,RB,RC); break; |
||
173 | case TP_ISUB: RA = tp_sub(tp,RB,RC); break; |
||
174 | case TP_IMUL: RA = tp_mul(tp,RB,RC); break; |
||
175 | case TP_IDIV: RA = tp_div(tp,RB,RC); break; |
||
176 | case TP_IPOW: RA = tp_pow(tp,RB,RC); break; |
||
177 | case TP_IAND: RA = tp_and(tp,RB,RC); break; |
||
178 | case TP_IOR: RA = tp_or(tp,RB,RC); break; |
||
179 | case TP_IMOD: RA = tp_mod(tp,RB,RC); break; |
||
180 | case TP_ILSH: RA = tp_lsh(tp,RB,RC); break; |
||
181 | case TP_IRSH: RA = tp_rsh(tp,RB,RC); break; |
||
182 | case TP_ICMP: RA = tp_number(tp_cmp(tp,RB,RC)); break; |
||
183 | case TP_INE: RA = tp_number(tp_cmp(tp,RB,RC)!=0); break; |
||
184 | case TP_IEQ: RA = tp_number(tp_cmp(tp,RB,RC)==0); break; |
||
185 | case TP_ILE: RA = tp_number(tp_cmp(tp,RB,RC)<=0); break; |
||
186 | case TP_ILT: RA = tp_number(tp_cmp(tp,RB,RC)<0); break; |
||
187 | case TP_IPASS: break; |
||
188 | case TP_IIF: if (tp_bool(tp,RA)) { cur += 1; } break; |
||
189 | case TP_IGET: RA = tp_get(tp,RB,RC); GA; break; |
||
190 | case TP_IITER: |
||
191 | if (RC.number.val < tp_len(tp,RB).number.val) { |
||
192 | RA = tp_iter(tp,RB,RC); GA; |
||
193 | RC.number.val += 1; |
||
194 | cur += 1; |
||
195 | } |
||
196 | break; |
||
197 | case TP_IHAS: RA = tp_has(tp,RB,RC); break; |
||
198 | case TP_IIGET: tp_iget(tp,&RA,RB,RC); break; |
||
199 | case TP_ISET: tp_set(tp,RA,RB,RC); break; |
||
200 | case TP_IDEL: tp_del(tp,RA,RB); break; |
||
201 | case TP_IMOVE: RA = RB; break; |
||
202 | case TP_INUMBER: |
||
203 | RA = tp_number(*(tp_num*)(*++cur).string.val); |
||
204 | cur += sizeof(tp_num)/4; |
||
205 | continue; |
||
206 | case TP_ISTRING: |
||
207 | RA = tp_string_n((*(cur+1)).string.val,UVBC); |
||
208 | cur += (UVBC/4)+1; |
||
209 | break; |
||
210 | case TP_IDICT: RA = tp_dict_n(tp,VC/2,&RB); break; |
||
211 | case TP_ILIST: RA = tp_list_n(tp,VC,&RB); break; |
||
212 | case TP_IPARAMS: RA = tp_params_n(tp,VC,&RB); break; |
||
213 | case TP_ILEN: RA = tp_len(tp,RB); break; |
||
214 | case TP_IJUMP: cur += SVBC; continue; break; |
||
215 | case TP_ISETJMP: f->jmp = cur+SVBC; break; |
||
216 | case TP_ICALL: _tp_call(tp,&RA,RB,RC); cur++; SR(0); break; |
||
217 | case TP_IGGET: |
||
218 | if (!tp_iget(tp,&RA,f->globals,RB)) { |
||
219 | RA = tp_get(tp,tp->builtins,RB); GA; |
||
220 | } |
||
221 | break; |
||
222 | case TP_IGSET: tp_set(tp,f->globals,RA,RB); break; |
||
223 | case TP_IDEF: |
||
224 | RA = tp_def(tp,(*(cur+1)).string.val,f->globals); |
||
225 | cur += SVBC; continue; |
||
226 | break; |
||
227 | case TP_IRETURN: tp_return(tp,RA); SR(0); break; |
||
228 | case TP_IRAISE: _tp_raise(tp,RA); SR(0); break; |
||
229 | case TP_IDEBUG: |
||
230 | tp_params_v(tp,3,tp_string("DEBUG:"),tp_number(VA),RA); tp_print(tp); |
||
231 | break; |
||
232 | case TP_INONE: RA = tp_None; break; |
||
233 | case TP_ILINE: |
||
234 | f->line = tp_string_n((*(cur+1)).string.val,VA*4-1); |
||
235 | /* fprintf(stderr,"%7d: %s\n",UVBC,f->line.string.val);*/ |
||
236 | cur += VA; f->lineno = UVBC; |
||
237 | break; |
||
238 | case TP_IFILE: f->fname = RA; break; |
||
239 | case TP_INAME: f->name = RA; break; |
||
240 | case TP_IREGS: f->cregs = VA; break; |
||
241 | default: tp_raise(0,"tp_step: invalid instruction %d",e.i); break; |
||
242 | } |
||
243 | cur += 1; |
||
244 | } |
||
245 | SR(0); |
||
246 | } |
||
247 | |||
248 | |||
249 | if (tp->jmp) { |
||
250 | tp_raise(,"tp_run(%d) called recusively",cur); |
||
251 | } |
||
252 | tp->jmp = 1; |
||
253 | if (setjmp(tp->buf)) |
||
254 | { |
||
255 | tp_handle(tp); |
||
256 | } |
||
257 | while (tp->cur >= cur && tp_step(tp) != -1); |
||
258 | tp->cur = cur-1; |
||
259 | tp->jmp = 0; |
||
260 | } |
||
261 | |||
262 | |||
263 | |||
264 | tp_obj tmp; |
||
265 | tp_obj r = tp_None; |
||
266 | tmp = tp_get(tp,tp->modules,tp_string(mod)); |
||
267 | tmp = tp_get(tp,tmp,tp_string(fnc)); |
||
268 | _tp_call(tp,&r,tmp,params); |
||
269 | tp_run(tp,tp->cur); |
||
270 | return r; |
||
271 | } |
||
272 | |||
273 | |||
274 | tp_obj code = tp_None; |
||
275 | tp_obj g; |
||
276 | if (!((fname && strstr(fname,".tpc")) || codes)) { |
||
277 | return tp_call(tp,"py2bc","import_fname",tp_params_v(tp,2,tp_string(fname),tp_string(name))); |
||
278 | } |
||
279 | if (!codes) { |
||
280 | tp_params_v(tp,1,tp_string(fname)); |
||
281 | code = tp_load(tp); |
||
282 | /* We cast away the constness. */ |
||
283 | codes = (void *)code.string.val; |
||
284 | } else { |
||
285 | code = tp_data(tp,0,codes); |
||
286 | } |
||
287 | |||
288 | |||
289 | tp_set(tp,g,tp_string("__name__"),tp_string(name)); |
||
290 | tp_set(tp,g,tp_string("__code__"),code); |
||
291 | tp_set(tp,g,tp_string("__dict__"),g); |
||
292 | tp_frame(tp,g,(tp_code*)codes,0); |
||
293 | tp_set(tp,tp->modules,tp_string(name),g); |
||
294 | if (!tp->jmp) { |
||
295 | tp_run(tp,tp->cur); |
||
296 | } |
||
297 | |||
298 | |||
299 | } |
||
300 | |||
301 | |||
302 | |||
303 | |||
304 | tp_obj code = TP_OBJ(); |
||
305 | tp_obj globals = TP_OBJ(); |
||
306 | tp_frame(tp,globals,(tp_code*)code.string.val,0); |
||
307 | return tp_None; |
||
308 | } |
||
309 | |||
310 | |||
311 | |||
312 | tp_obj mod = TP_OBJ(); |
||
313 | char const *s; |
||
314 | tp_obj r; |
||
315 | |||
316 | |||
317 | return tp_get(tp,tp->modules,mod); |
||
318 | } |
||
319 | |||
320 | |||
321 | r = tp_import(tp,TP_CSTR(tp_add(tp,mod,tp_string(".tpc"))),s,0); |
||
322 | return r; |
||
323 | } |
||
324 | |||
325 | |||
326 | struct {const char *s;void *f;} b[] = { |
||
327 | {"print",tp_print}, {"range",tp_range}, {"raw_input", tp_raw_input}, |
||
3235 | jaeger | 328 | {"min",tp_min}, {"max",tp_max}, {"bind",tp_bind}, {"copy",tp_copy}, |
329 | {"import",tp_import_}, {"len",tp_len_}, {"assert",tp_assert}, |
||
1913 | jaeger | 330 | {"str",tp_str2}, {"float",tp_float}, {"system",tp_system}, |
331 | {"istype",tp_istype}, {"chr",tp_chr}, {"save",tp_save}, |
||
332 | {"load",tp_load}, {"fpack",tp_fpack}, {"abs",tp_abs}, |
||
333 | {"int",tp_int}, {"exec",tp_exec_}, {"exists",tp_exists}, |
||
334 | {"mtime",tp_mtime}, {"number",tp_float}, {"round",tp_round}, |
||
335 | {"ord",tp_ord}, {"merge",tp_merge}, {"syscall", tp_syscall}, {0,0}, |
||
336 | }; |
||
337 | int i; for(i=0; b[i].s; i++) { |
||
338 | tp_set(tp,tp->builtins,tp_string(b[i].s),tp_fnc(tp,(tp_obj (*)(tp_vm *))b[i].f)); |
||
339 | } |
||
340 | } |
||
341 | |||
342 | |||
343 | |||
344 | tp_obj self = tp_list(tp); |
||
345 | int i; |
||
346 | for (i=1; i |
||
347 | tp_set(tp,tp->builtins,tp_string("ARGV"),self); |
||
348 | } |
||
349 | |||
350 | |||
351 | |||
352 | return tp_import(tp,fname,"__main__",code); |
||
353 | } |
||
354 | tp_obj tp_compile(TP, tp_obj text, tp_obj fname) { |
||
355 | return tp_call(tp,"BUILTINS","compile",tp_params_v(tp,2,text,fname)); |
||
356 | } |
||
357 | |||
358 | |||
359 | tp_obj r=tp_None; |
||
360 | tp_frame(tp,globals,(tp_code*)code.string.val,&r); |
||
361 | tp_run(tp,tp->cur); |
||
362 | return r; |
||
363 | } |
||
364 | |||
365 | |||
366 | tp_obj code = tp_compile(tp,tp_string(text),tp_string(" |
||
367 | return tp_exec(tp,code,globals); |
||
368 | } |
||
369 | |||
370 | |||
371 | tp_vm *tp = _tp_init(); |
||
372 | tp_builtins(tp); |
||
373 | tp_args(tp,argc,argv); |
||
374 | tp_compiler(tp); |
||
375 | return tp; |
||
376 | } |
||
377 | |||
378 | |||
379 | |||
380 | #define><8)+VC)) |