root/as2/E3Engine/CodeGenerator.as

リビジョン 299, 13.1 kB (コミッタ: yossy, コミット時期: 4 年 前)

Imported Lab code.

Line 
1 class CodeGenerator
2 {
3         private var code:Array;
4         private var stackList:Array;
5         private var localVariableList:Array;
6        
7         public function CodeGenerator ()
8         {
9                 initialize();
10         }
11        
12         public function initialize () : Void
13         {
14                 code = new Array();
15                 stackList = new Array();
16                 localVariableList = new Array();
17                
18                 // reserved
19                 put(null);
20                
21                 beginNewScope();
22         }
23        
24         private function error (message:String) : Void
25         {
26                 throw new Error('CodeGenerator [error] '+message);
27         }
28        
29         public function getCode () : Array
30         {
31                 return code;
32         }
33        
34         public function put (element:Object) : Number
35         {
36                 return code.push(element)-1;
37         }
38         public function putStoreStack () : Void
39         {
40                 stackList.push(put(null));
41         }
42         public function putLoadStack () : Void
43         {
44                 var _code:Array = code;
45                
46                 var current:Number = Number(stackList.pop());
47                 var next:Number;
48                
49                 var address:Number = put(null);
50                
51                 for (;;) {
52                         next = _code[current];
53                         _code[current] = address;
54                         if (next == null) break;
55                         current = next;
56                 }
57         }
58         public function popStack () : Number
59         {
60                 return Number(stackList.pop());
61         }
62         public function pushStack (address:Number) : Void
63         {
64                 stackList.push(address);
65         }
66         public function setStackPatch (address:Number) : Void
67         {
68                 code[stackList[stackList.length-1]] = address;
69         }
70         public function putCrossLoadStack () : Void
71         {
72                 swapStack();
73                 putLoadStack();
74                 putLoadStack();
75         }
76         public function swapStack (a:Number, b:Number) : Void
77         {
78                 a = stackList.length - (a !== undefined ? a : 0) - 1;
79                 b = stackList.length - (b !== undefined ? b : 1) - 1;
80                
81                 var n:Number = stackList[a];
82                 stackList[a] = stackList[b];
83                 stackList[b] = n;
84         }
85         public function getStackLength () : Number
86         {
87                 return stackList.length;
88         }
89         public function cleanUpStack (begin:Number) : Void
90         {
91                 if (begin === undefined ) begin = 0;
92                
93                 var _stackList:Array = stackList;
94                
95                 for (; _stackList.length > begin; ) {
96                         popAndDestroyStack();
97                 }
98         }
99         public function popAndDestroyStack () : Void
100         {
101                 var _code:Array = code;
102                 var current:Number = Number(stackList.pop());
103                 var next:Number;
104                 for (;;) {
105                         next = _code[current];
106                         _code[current] = 0;
107                         if (next == null) break;
108                         current = next;
109                 }
110         }
111        
112         public function putLabel (label:Label) : Void
113         {
114                 if (label.isExists) {
115                         put(label.address);
116                 }
117                 else {
118                         label.address = put(label.address);
119                 }
120         }
121         public function setLabel (label:Label) : Void
122         {
123                 var address:Number = code.length;
124                 setLabelAddress(label, address);
125                 label.commitAddress(address);
126         }
127         public function setLabelAddress (label:Label, address:Number) : Void
128         {
129                 var _code:Array = code;
130                
131                 var current:Number = label.address;
132                 var next:Number;
133                
134                 for (;;) {
135                         if (current == null) break;
136                        
137                         next = _code[current];
138                         _code[current] = address;
139                         current = next;
140                 }
141         }
142        
143         public function beginNewScope () : Void
144         {
145                 localVariableList.unshift(new Object());
146         }
147         public function closeScope () : Void
148         {
149                 localVariableList.shift();
150         }
151         public function isLocalVariable (identifier:Object) : Boolean
152         {
153                 return localVariableList[0].hasOwnProperty(String(identifier));
154         }
155         public function addLocalVariable (identifier:Object) : Void
156         {
157                 localVariableList[0][identifier] = true;
158         }
159        
160         public function putExpressionResult (expressionResult:ExpressionResult) : Void
161         {
162                 switch (expressionResult.type) {
163                         case 'variable': {
164                                 putGetVariable(String(expressionResult.value));
165                                 expressionResult.setType('stack');
166                         }
167                         break;
168                        
169                         case 'member': {
170                                 putGetMember(expressionResult.getObjectExpression(), expressionResult.getMemberExpression());
171                                 expressionResult.setType('stack');
172                         }
173                         break;
174                 }
175         }
176        
177         private function putValue (expressionResult:ExpressionResult) : Void
178         {
179                 switch (expressionResult.type) {
180                         case 'literal': {
181                                 put(expressionResult.value);
182                         }
183                         break;
184                        
185                         case 'stack': {
186                                 putLoadStack();
187                         }
188                         break;
189                        
190                         default : {
191                                 error('putValueError');
192                         }
193                 }
194         }
195         private function putBinaryValue (left:ExpressionResult, right:ExpressionResult) : Void
196         {
197                 if (left.isType('literal') && right.isType('literal')) {
198                         put(left.value);
199                         put(right.value);
200                 }
201                 else if (left.isType('stack') && right.isType('stack')) {
202                         putCrossLoadStack();
203                 }
204                 else if (left.isType('stack')) {
205                         putLoadStack();
206                         put(right.value);
207                 }
208                 else if (right.isType('stack')) {
209                         put(left.value);
210                         putLoadStack();
211                 }
212                 else {
213                         error('putBinaryValueError');
214                 }
215         }
216        
217         public function putSuspend () : Void
218         {
219                 put('SPD');
220         }
221        
222         public function putLiteral (expressionResult:ExpressionResult) : Void
223         {
224                 put('LIT');
225                 put(expressionResult.value);
226                 putStoreStack();
227         }
228        
229         public function putCall (identifier:ExpressionResult, numOfArguments:Number) : Void
230         {
231                 if (isLocalVariable(identifier.value)) {
232                         put('CALLL');
233                 }
234                 else {
235                         put('CALL');
236                 }
237                 put(identifier.value);
238                 put(numOfArguments);
239                 putStoreStack();
240         }
241         public function putCallMember (objectExpression:ExpressionResult, memberExpression:ExpressionResult, numOfArguments:Number) : Void
242         {
243                 put('CALLM');
244                 putBinaryValue(objectExpression, memberExpression);
245                 /*
246                 if (ExpressionResult(memberExpression.value).isType('literal')) {
247                         putLoadStack();
248                         put(ExpressionResult(memberExpression.value).value);
249                 }
250                 else {
251                         putCrossLoadStack();
252                 }
253                 */
254                 put(numOfArguments);
255                 putStoreStack();
256         }
257         public function putCallFunctor (numOfArguments:Number) : Void
258         {
259                 put('CALLF');
260                 putLoadStack();
261                 put(numOfArguments);
262                 putStoreStack();
263         }
264        
265         public function putReturnFunction (returnValue:ExpressionResult) : Void
266         {
267                 put('RET');
268                 putValue(returnValue);
269         }
270         public function putReturnCoroutine (returnValue:ExpressionResult) : Void
271         {
272                 put('CRET');
273                 putValue(returnValue);
274         }
275         public function putFunction () : Label
276         {
277                 var label:Label = new Label();
278                
279                 put('FUNC');
280                 putLabel(label);
281                 putStoreStack();
282                
283                 return label;
284         }
285         public function putCoroutine () : Label
286         {
287                 var label:Label = new Label();
288                
289                 put('COR');
290                 putLabel(label);
291                 putStoreStack();
292                
293                 return label;
294         }
295         public function putArgument (argumentIndex:Number, identifier:String) : Void
296         {
297                 put('ARG');
298                 put(argumentIndex);
299                 put(identifier);
300                 addLocalVariable(identifier);
301         }
302        
303         public function putJump (label:Label) : Void
304         {
305                 put('JMP');
306                 putLabel(label);
307         }
308        
309         public function putIf (expressionResult:ExpressionResult, label:Label) : Void
310         {
311                 put('IF');
312                 putValue(expressionResult);
313                 putLabel(label);
314         }
315         public function putNif (expressionResult:ExpressionResult, label:Label) : Void
316         {
317                 put('NIF');
318                 putValue(expressionResult);
319                 putLabel(label);
320         }
321        
322         // �񍀉��Z
323         public function putBinaryOperation (operation:String, left:ExpressionResult, right:ExpressionResult) : Void
324         {
325                 put(operation);
326                 putBinaryValue(left, right);
327                 putStoreStack();
328         }
329        
330         // �P�����Z
331         public function putUnaryOperation (operation:String, expression:ExpressionResult) : Void
332         {
333                 put(operation);
334                 putValue(expression);
335                 putStoreStack();
336         }
337        
338         public function putIncrement (expressionResult:ExpressionResult) : Void
339         {
340                 putIncDec('INC', false, expressionResult);
341         }
342         public function putDecrement (expressionResult:ExpressionResult) : Void
343         {
344                 putIncDec('DEC', false, expressionResult);
345         }
346         public function putPostfixIncrement (expressionResult:ExpressionResult) : Void
347         {
348                 putIncDec('INC', true, expressionResult);
349         }
350         public function putPostfixDecrement (expressionResult:ExpressionResult) : Void
351         {
352                 putIncDec('DEC', true, expressionResult);
353         }
354         private function putIncDec (operation:String, isPostfix:Boolean, expressionResult:ExpressionResult) : Void
355         {
356                 switch (expressionResult.type) {
357                         case 'member': {
358                                 var objectExpression:ExpressionResult = expressionResult.getObjectExpression();
359                                 var memberExpression:ExpressionResult = expressionResult.getMemberExpression();
360                                 if (!memberExpression.isLiteral()) {
361                                         putExpressionResult(memberExpression);
362                                         var s:Number = popStack();
363                                         putDuplicate(memberExpression);
364                                         pushStack(s);
365                                         putDuplicate(objectExpression);
366                                         swapStack(1, 2);
367                                 }
368                                 else {
369                                         putDuplicate(objectExpression);
370                                 }
371                                 putGetMember(objectExpression, memberExpression);
372                                 expressionResult.setTypeStack();
373                                 if (isPostfix) {
374                                         putDuplicate(expressionResult);
375                                         var s:Number = popStack();
376                                         putUnaryOperation(operation, expressionResult);
377                                         putSetMember(objectExpression, memberExpression, expressionResult);
378                                         popAndDestroyStack();
379                                         pushStack(s);
380                                 }
381                                 else {
382                                         putUnaryOperation(operation, expressionResult);
383                                         putSetMember(objectExpression, memberExpression, expressionResult);
384                                 }
385                         }
386                         break;
387                        
388                         case 'variable': {
389                                 var identifier:String = String(expressionResult.value);
390                                 putGetVariable(identifier);
391                                 expressionResult.setTypeStack();
392                                 if (isPostfix) {
393                                         putDuplicate(expressionResult);
394                                 }
395                                 putUnaryOperation(operation, expressionResult);
396                                 putSetVariable(identifier, expressionResult);
397                                 if (isPostfix) {
398                                         popAndDestroyStack();
399                                 }
400                         }
401                         break;
402                        
403                         default: {
404                                 error('putIncDecError');
405                         }
406                 }
407         }
408        
409         public function putWith (objectExpression:ExpressionResult) : Void
410         {
411                 put('WITH');
412                 putValue(objectExpression);
413         }
414         public function putEndWith () : Void
415         {
416                 put('EWITH');
417         }
418        
419         public function putPush (expressionResult:ExpressionResult) : Void
420         {
421                 put('PUSH');
422                 putValue(expressionResult);
423         }
424         public function putPop () : Void
425         {
426                 put('POP');
427                 putStoreStack();
428         }
429        
430         public function putDuplicate (expressionResult:ExpressionResult) : Void
431         {
432                 put('DUP');
433                 putValue(expressionResult);
434                 putStoreStack();
435                 putStoreStack();
436         }
437        
438         public function putThis () : Void
439         {
440                 put('THIS');
441                 putStoreStack();
442         }
443        
444         public function putArrayLiteral (numOfElements:Number) : Void
445         {
446                 put('ARRAY');
447                 put(numOfElements);
448                 putStoreStack();
449         }
450         public function putObjectLiteral (numOfProperties:Number) : Void
451         {
452                 put('OBJ');
453                 put(numOfProperties);
454                 putStoreStack();
455         }
456        
457         public function putGetVariable (identifier:String) : Void
458         {
459                 if (isLocalVariable(identifier)) {
460                         put('GETL');
461                 }
462                 else {
463                         put('GET');
464                 }
465                 put(identifier);
466                 putStoreStack();
467         }
468         public function putSetVariable (identifier:String, right:ExpressionResult) : Void
469         {
470                 if (isLocalVariable(identifier)) {
471                         put('SETL');
472                 }
473                 else {
474                         put('SET');
475                 }
476                 put(identifier);
477                 putValue(right);
478                 putStoreStack();
479         }
480         public function putSetLocalVariable (identifier:String, right:ExpressionResult) : Void
481         {
482                 put('SETL');
483                 put(identifier);
484                 putValue(right);
485                 putStoreStack();
486                 addLocalVariable(identifier);
487         }
488         public function putGetMember (objectExpression:ExpressionResult, memberExpression:ExpressionResult) : Void
489         {
490                 put('GETM');
491                 putBinaryValue(objectExpression, memberExpression);
492                 putStoreStack();
493         }
494         public function putSetMember (objectExpression:ExpressionResult, memberExpression:ExpressionResult, right:ExpressionResult) : Void
495         {
496                 put('SETM');
497                 if (objectExpression.isLiteral()) {
498                         if (memberExpression.isLiteral()) {
499                                 if (right.isLiteral()) {
500                                         put(objectExpression.value);
501                                         put(memberExpression.value);
502                                         put(right.value);
503                                 }
504                                 else {
505                                         put(objectExpression.value);
506                                         put(memberExpression.value);
507                                         putLoadStack();
508                                 }
509                         }
510                         else {
511                                 if (right.isLiteral()) {
512                                         put(objectExpression.value);
513                                         putLoadStack();
514                                         put(right.value);
515                                 }
516                                 else {
517                                         put(objectExpression.value);
518                                         putCrossLoadStack();
519                                 }
520                         }
521                 }
522                 else {
523                         if (memberExpression.isLiteral()) {
524                                 if (right.isLiteral()) {
525                                         putLoadStack();
526                                         put(memberExpression.value);
527                                         put(right.value);
528                                 }
529                                 else {
530                                         swapStack();
531                                         putLoadStack();
532                                         put(memberExpression.value);
533                                         putLoadStack();
534                                 }
535                         }
536                         else {
537                                 if (right.isLiteral()) {
538                                         putCrossLoadStack();
539                                         put(right.value);
540                                 }
541                                 else {
542                                         swapStack(0, 2);
543                                         putLoadStack();
544                                         putLoadStack();
545                                         putLoadStack();
546                                 }
547                         }
548                 }
549                 putStoreStack();
550         }
551        
552         public function putNew (numOfArguments:Number) : Void
553         {
554                 put('NEW');
555                 putLoadStack();
556                 put(numOfArguments);
557                 putStoreStack();
558         }
559        
560         public function putDelete (expressionResult:ExpressionResult) : Void
561         {
562                 if (expressionResult.isType('variable') || expressionResult.isType('literal')) {
563                         if (isLocalVariable(expressionResult.value)) {
564                                 put('DELL');
565                         }
566                         else {
567                                 put('DEL');
568                         }
569                         put(expressionResult.value);
570                         putStoreStack();
571                 }
572                 else {
573                         put('DEL');
574                         putLoadStack();
575                         putStoreStack();
576                 }
577         }
578         public function putDeleteMember (objectExpression:ExpressionResult, expressionResult:ExpressionResult) : Void
579         {
580                 put('DELM');
581                 putBinaryValue(objectExpression, expressionResult);
582                 /*
583                 if (ExpressionResult(expressionResult.value).isType('literal')) {
584                         putLoadStack();
585                         put(ExpressionResult(expressionResult.value).value);
586                 }
587                 else {
588                         putCrossLoadStack();
589                 }
590                 */
591                 putStoreStack();
592         }
593 }
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。