root/lang/cplusplus/minipy/trunk/translator.cpp @ 7256

Revision 7256, 36.1 kB (checked in by hayamiz, 5 years ago)

lang/cplusplus/minipy: initial import of mini-python

Line 
1#include "translator.hpp"
2
3Translator::Translator(){
4   
5}
6
7void Translator::compile_error(const string & msg, const SrcPos & pos){
8    cerr << "compile error:::" << endl
9         << "  " << msg << " at " << pos.filename << ":" << pos.line_no << endl;
10    exit(1);
11}
12
13bool Translator::numeric_expr(const Expr & expr){
14    bool ret;
15
16    switch(expr.kind){
17    case expr_kind_literal_int:
18        ret = true;
19        break;
20    case expr_kind_literal_float:
21        ret = true;
22        break;
23    case expr_kind_paren:
24        ret = this->numeric_expr(*expr.u.paren);
25        break;
26    case expr_kind_operator:
27        if (expr.u.op->fix == fix_kind_prefix){
28            switch(expr.u.op->kind){
29            case TOK_PLUS:
30            case TOK_MINUS:
31            case TOK_TILDE:
32                ret = numeric_expr(expr.u.op->args[0]);
33                break;
34            default:
35                ret = false;
36            }
37        } else if(expr.u.op->fix == fix_kind_infix){
38            switch(expr.u.op->kind){
39            case TOK_PLUS:
40            case TOK_MINUS:
41            case TOK_MUL:
42            case TOK_DIV:
43            case TOK_LSHIFT:
44            case TOK_RSHIFT:
45            case TOK_XOR:
46            case TOK_AMP:
47            case TOK_BAR:
48                ret = numeric_expr(expr.u.op->args[0])
49                    && numeric_expr(expr.u.op->args[1]);
50                break;
51            default:
52                ret = false;
53            }
54        } else {
55            return false;
56        }
57        break;
58    default:
59        ret = false;
60    }
61   
62    return ret;
63}
64
65void Translator::insns_val_infix_operator(const Expr & expr, vm_assembler & vmasm, LocalEnv * lenv){
66    // infix operators
67    // TOK_PLUS, TOK_MINUS, TOK_MUL, TOK_DIV
68    // TOK_EQ_EQ, TOK_NEQ, TOK_GT, TOK_GEQ, TOK_LT, TOK_LEQ
69    // TOK_LSHIFT, TOK_RSHIFT, TOK_XOR, TOK_AMP, TOK_BAR
70    // TOK_KW_OR, TOK_KW_AND,  TOK_KW_IS, TOK_KW_IN
71    // TOK_KW_IS_NOT, TOK_KW_NOT_IN
72    switch(expr.u.op->kind){
73    case TOK_PLUS:
74        this->insns_push(expr.u.op->args[0], vmasm, lenv);
75        if (expr.u.op->args[1].kind == expr_kind_var
76            && !lenv->is_global(expr.u.op->args[1].u.var)
77            && !lenv->is_toplevel
78            && lenv->exists(expr.u.op->args[1].u.var)) {
79            vmasm.LREF_ADD2(vm_operand::integer(
80                                lenv->look_var(expr.u.op->args[1].u.var))
81                            ,expr.pos);
82        } else {
83            this->insns_val(expr.u.op->args[1], vmasm, lenv);
84            vmasm.ADD2(expr.pos);
85        }
86//         if (this->numeric_expr(expr)){
87//             vmasm.ADD2_NUM(expr.pos);
88//         } else {
89//             vmasm.ADD2(expr.pos);
90//         }
91        break;
92    case TOK_MINUS:
93        this->insns_push(expr.u.op->args[0], vmasm, lenv);
94        if (expr.u.op->args[1].kind == expr_kind_var
95            && !lenv->is_global(expr.u.op->args[1].u.var)
96            && !lenv->is_toplevel
97            && lenv->exists(expr.u.op->args[1].u.var)) {
98            vmasm.LREF_SUB2(vm_operand::integer(
99                                lenv->look_var(expr.u.op->args[1].u.var))
100                            ,expr.pos);
101        } else {
102            this->insns_val(expr.u.op->args[1], vmasm, lenv);
103            vmasm.SUB2(expr.pos);
104        }
105//         if (this->numeric_expr(expr)){
106//             vmasm.SUB2_NUM(expr.pos);
107//         } else {
108//             vmasm.SUB2(expr.pos);
109//         }
110       
111        break;
112    case TOK_MUL:
113        this->insns_push(expr.u.op->args[0], vmasm, lenv);
114        if (expr.u.op->args[1].kind == expr_kind_var
115            && !lenv->is_global(expr.u.op->args[1].u.var)
116            && !lenv->is_toplevel
117            && lenv->exists(expr.u.op->args[1].u.var)) {
118            // stacktop(0) * LREF(n)
119            vmasm.LREF_MUL2(vm_operand::integer(
120                                lenv->look_var(expr.u.op->args[1].u.var))
121                            ,expr.pos);
122        } else {
123            // stacktop(0) * VAL
124            this->insns_val(expr.u.op->args[1], vmasm, lenv);
125            vmasm.MUL2(expr.pos);
126        }
127//         if (this->numeric_expr(expr)){
128//             vmasm.MUL2_NUM(expr.pos);
129//         } else {
130//             vmasm.MUL2(expr.pos);
131//         }
132        break;
133    case TOK_DIV:
134        this->insns_push(expr.u.op->args[0], vmasm, lenv);
135        if (expr.u.op->args[1].kind == expr_kind_var
136            && !lenv->is_global(expr.u.op->args[1].u.var)
137            && !lenv->is_toplevel
138            && lenv->exists(expr.u.op->args[1].u.var)) {
139            vmasm.LREF_DIV2(vm_operand::integer(
140                                lenv->look_var(expr.u.op->args[1].u.var))
141                            ,expr.pos);
142        } else {
143            this->insns_val(expr.u.op->args[1], vmasm, lenv);
144            vmasm.DIV2(expr.pos);
145        }
146//         if (this->numeric_expr(expr)){
147//             vmasm.DIV2_NUM(expr.pos);
148//         } else {
149//             vmasm.DIV2(expr.pos);
150//         }
151       
152        break;
153    case TOK_MOD:
154        vmasm.PUSH_ENV(expr.pos);
155        this->insns_push(expr.u.op->args[0], vmasm, lenv);
156        this->insns_push(expr.u.op->args[1], vmasm, lenv);
157        vmasm.GREF_CALL(vm_operand::name(Symbol::get("mod")), expr.pos);
158        break;
159    case TOK_EQ_EQ:
160        this->insns_push(expr.u.op->args[0], vmasm, lenv);
161        this->insns_val(expr.u.op->args[1], vmasm, lenv);
162        vmasm.EQL2(expr.pos);
163        break;
164    case TOK_NEQ:
165        this->insns_push(expr.u.op->args[0], vmasm, lenv);
166        this->insns_val(expr.u.op->args[1], vmasm, lenv);
167        vmasm.NEQL2(expr.pos);
168        break;
169    case TOK_GT:
170        this->insns_push(expr.u.op->args[0], vmasm, lenv);
171        this->insns_val(expr.u.op->args[1], vmasm, lenv);
172        vmasm.NUMGT2(expr.pos);
173        break;
174    case TOK_GEQ:
175        this->insns_push(expr.u.op->args[0], vmasm, lenv);
176        this->insns_val(expr.u.op->args[1], vmasm, lenv);
177        vmasm.NUMGEQ2(expr.pos);
178        break;
179    case TOK_LT:
180        this->insns_push(expr.u.op->args[0], vmasm, lenv);
181        this->insns_val(expr.u.op->args[1], vmasm, lenv);
182        vmasm.NUMLT2(expr.pos);
183        break;
184    case TOK_LEQ:
185        this->insns_push(expr.u.op->args[0], vmasm, lenv);
186        this->insns_val(expr.u.op->args[1], vmasm, lenv);
187        vmasm.NUMLEQ2(expr.pos);
188        break;
189    case TOK_LSHIFT:
190        this->insns_push(expr.u.op->args[0], vmasm, lenv);
191        this->insns_val(expr.u.op->args[1], vmasm, lenv);
192        vmasm.LSHIFT2(expr.pos);
193        break;
194    case TOK_RSHIFT:
195        this->insns_push(expr.u.op->args[0], vmasm, lenv);
196        this->insns_val(expr.u.op->args[1], vmasm, lenv);
197        vmasm.RSHIFT2(expr.pos);
198        break;
199    case TOK_XOR:
200        this->insns_push(expr.u.op->args[0], vmasm, lenv);
201        this->insns_val(expr.u.op->args[1], vmasm, lenv);
202        vmasm.BITXOR2(expr.pos);
203        break;
204    case TOK_AMP:
205        this->insns_push(expr.u.op->args[0], vmasm, lenv);
206        this->insns_val(expr.u.op->args[1], vmasm, lenv);
207        vmasm.BITAND2(expr.pos);
208        break;
209    case TOK_BAR:
210        this->insns_push(expr.u.op->args[0], vmasm, lenv);
211        this->insns_val(expr.u.op->args[1], vmasm, lenv);
212        vmasm.BITOR2(expr.pos);
213        break;
214    case TOK_KW_OR:
215        this->insns_push(expr.u.op->args[0], vmasm, lenv);
216        this->insns_val(expr.u.op->args[1], vmasm, lenv);
217        vmasm.OR2(expr.pos);
218        break;
219    case TOK_KW_AND:
220        this->insns_push(expr.u.op->args[0], vmasm, lenv);
221        this->insns_val(expr.u.op->args[1], vmasm, lenv);
222        vmasm.AND2(expr.pos);
223        break;
224    case TOK_KW_IS:
225        this->insns_push(expr.u.op->args[0], vmasm, lenv);
226        this->insns_val(expr.u.op->args[1], vmasm, lenv);
227        vmasm.IS2(expr.pos);
228        break;
229    case TOK_KW_IN:
230        this->insns_push(expr.u.op->args[0], vmasm, lenv);
231        this->insns_val(expr.u.op->args[1], vmasm, lenv);
232        vmasm.IN2(expr.pos);
233        break;
234    case TOK_KW_IS_NOT:
235        this->insns_push(expr.u.op->args[0], vmasm, lenv);
236        this->insns_val(expr.u.op->args[1], vmasm, lenv);
237        vmasm.IS2(expr.pos);
238        vmasm.NOT(expr.pos);
239        break;
240    case TOK_KW_NOT_IN:
241        this->insns_push(expr.u.op->args[0], vmasm, lenv);
242        this->insns_val(expr.u.op->args[1], vmasm, lenv);
243        vmasm.IN2(expr.pos);
244        vmasm.NOT(expr.pos);
245        break;
246    default:
247        perror("Invalid infix operator");
248        exit(1);
249    }
250}
251
252void Translator::scan_defun_local_var(const vector<Stm> & stms, LocalEnv * lenv){
253    for(int i = 0;i < (int)stms.size();i++){
254        const Stm & stm = stms[i];
255        switch(stm.kind){
256        case stm_kind_expression:
257        case stm_kind_del:
258        case stm_kind_pass:
259        case stm_kind_return:
260        case stm_kind_break:
261        case stm_kind_print:
262        case stm_kind_fundef:
263        case stm_kind_continue:
264            break;
265        case stm_kind_if:
266            for(int j = 0;j < (int)stm.u.i->size();j++){
267                this->scan_defun_local_var((*stm.u.i)[j].s, lenv);
268            }
269            break;
270        case stm_kind_while:
271            this->scan_defun_local_var(stm.u.w->b, lenv);
272            break;
273        case stm_kind_for:
274            if (lenv->is_toplevel){
275            }else{
276                if (!lenv->is_global(stm.u.f->x)){ // if local env
277                    lenv->add_var(stm.u.f->x); // allocate loop var
278                }
279                lenv->loopvar_queue.push(lenv->current_offset());
280                if (stm.u.f->e.kind == expr_kind_call
281                    && stm.u.f->e.u.call->f.kind == expr_kind_var
282                    && stm.u.f->e.u.call->f.u.var->compare("range") == 0){
283                    // range() for-loop
284                    lenv->add_var(); // loop var limit
285                    lenv->add_var(); // loop var step
286                } else {
287                    lenv->add_var(); // loop var index
288                    lenv->add_var(); // loop var index limit
289                    lenv->add_var(); // loop sequence
290                }
291            }
292            this->scan_defun_local_var(stm.u.f->b, lenv);
293            break;
294        case stm_kind_global:
295            lenv->mark_global(stm.u.g);
296            break;
297        case stm_kind_assignment:
298            if (lenv->is_toplevel) {
299                break;
300            }
301            if (stm.u.a->target.kind == expr_kind_var){
302                if (!lenv->is_global(stm.u.a->target.u.var)){
303                    lenv->add_var(stm.u.a->target.u.var);
304                }
305            }
306            break;
307        }
308    }
309}
310
311void Translator::insns_val(const Expr & expr, vm_assembler & vmasm, LocalEnv * lenv){
312
313    vector<Expr>::iterator itr;
314
315    switch(expr.kind){
316    case expr_kind_var:
317        if (lenv->is_global(expr.u.var)){
318            vmasm.GREF(vm_operand::name(expr.u.var), expr.pos);
319        } else if (! lenv->is_toplevel && lenv->exists(expr.u.var)) {
320            vmasm.LREF(vm_operand::integer(lenv->look_var(expr.u.var)), expr.pos);
321        } else {
322            vmasm.GREF(vm_operand::name(expr.u.var), expr.pos);
323        }
324        break;
325    case expr_kind_none:
326        vmasm.IMMVAL(vm_operand::pyval(Py_val::mk_none()), expr.pos);
327        break;
328    case expr_kind_literal_int:
329        vmasm.IMMVAL_NUM(vm_operand::pyval(Py_val::mk_int(expr.u.lit_i)), expr.pos);
330        break;
331    case expr_kind_literal_float:
332        vmasm.IMMVAL_NUM(vm_operand::pyval(Py_val::mk_float(expr.u.lit_f)), expr.pos);
333        break;
334    case expr_kind_literal_string:
335        vmasm.IMMVAL(vm_operand::pyval(Py_val::mk_string(*expr.u.lit_s)), expr.pos);
336        break;
337    case expr_kind_display_list:
338        for(itr = expr.u.disp->begin();itr != expr.u.disp->end()
339                ;itr++){
340            this->insns_push(*itr, vmasm, lenv);
341        }
342        vmasm.MKLIST(vm_operand::integer(expr.u.disp->size()), expr.pos);
343        break;
344    case expr_kind_display_tuple:
345        for(itr = expr.u.disp->begin(); itr != expr.u.disp->end()
346                ;itr++){
347            this->insns_push(*itr, vmasm, lenv);
348        }
349        vmasm.MKTUPLE(vm_operand::integer(expr.u.disp->size()), expr.pos);
350        break;
351    case expr_kind_display_dict:
352        for(itr = expr.u.disp->begin(); itr != expr.u.disp->end()
353                ;itr++){
354            this->insns_push(itr->u.op->args[0], vmasm, lenv); // push key
355            this->insns_push(itr->u.op->args[1], vmasm, lenv); // push value
356        }
357        vmasm.MKDICT(vm_operand::integer(expr.u.disp->size()), expr.pos);
358        break;
359    case expr_kind_paren:
360        this->insns_val(*expr.u.paren, vmasm, lenv);
361        break;
362    case expr_kind_operator:
363        // operators
364        // TOK_PLUS, TOK_MINUS, TOK_MUL, TOK_DIV
365        // TOK_EQ_EQ, TOK_NEQ, TOK_GT, TOK_GEQ, TOK_LT, TOK_LEQ
366        // TOK_TILDE, TOK_LSHIFT, TOK_RSHIFT, TOK_XOR, TOK_AMP, TOK_BAR
367        // TOK_KW_OR, TOK_KW_AND, TOK_KW_NOT, TOK_KW_IS, TOK_KW_IN
368        if (expr.u.op->fix == fix_kind_prefix){
369            switch(expr.u.op->kind){
370            case TOK_PLUS:
371                this->insns_val(expr.u.op->args[0], vmasm, lenv);
372                break;
373            case TOK_MINUS:
374                this->insns_push(expr.u.op->args[0], vmasm, lenv);
375                vmasm.IMMVAL_NUM(vm_operand::integer(-1), expr.pos);
376                vmasm.MUL2_NUM(expr.pos);
377                break;
378            case TOK_TILDE:
379                this->insns_val(expr.u.op->args[0], vmasm, lenv);
380                vmasm.BITINV(expr.pos);
381                break;
382            case TOK_KW_NOT:
383                this->insns_val(expr.u.op->args[0], vmasm, lenv);
384                vmasm.NOT(expr.pos);
385                break;
386            default:
387                perror("Invalid prefix operator.");
388                exit(1);
389            }
390        } else {
391            this->insns_val_infix_operator(expr, vmasm, lenv);
392        }
393        break;
394    case expr_kind_attref:
395        // cases like 'foo.bar()' are treated in case expr_kind_call.
396        perror("Attref must be used as function name.");
397        exit(1);
398        break;
399    case expr_kind_subscript:
400        this->insns_push((*expr.u.sub)[0], vmasm, lenv);
401        this->insns_val((*expr.u.sub)[1], vmasm, lenv);
402        vmasm.GETITEM(expr.pos);
403        break;
404    case expr_kind_call:
405        // optimize some functions as instructions
406        if (expr.u.call->f.kind == expr_kind_var){
407            symbol_t func = expr.u.call->f.u.var;
408            if(func == Symbol::get("print_string")){
409                this->insns_val(expr.u.call->args[0], vmasm, lenv);
410                vmasm.PRINTSTR(expr.pos);
411                break;
412            }
413        }
414       
415        vmasm.PUSH_ENV(expr.pos); // make new env
416        // set up args
417        if (expr.u.call->f.kind == expr_kind_attref){
418            this->insns_push(expr.u.call->f.u.atr->a, vmasm, lenv);
419        }
420        for(itr = expr.u.call->args.begin(); itr != expr.u.call->args.end(); itr++){
421            this->insns_push(*itr, vmasm, lenv);
422        }
423
424        if (! lenv->is_toplevel
425            && expr.u.call->f.kind == expr_kind_var
426            && lenv->name->compare(*expr.u.call->f.u.var) == 0){
427            vmasm.SELF_CALL(vm_operand::pyval(lenv->self), expr.pos);
428        } else {
429            switch(expr.u.call->f.kind){
430            case expr_kind_attref:
431                vmasm.GREF_CALL(vm_operand::name(expr.u.call->f.u.atr->f), expr.pos);
432                break;
433            case expr_kind_var:
434                if (! lenv->is_toplevel && lenv->exists(expr.u.call->f.u.var)){
435                    vmasm.LREF_CALL(
436                        vm_operand::integer(lenv->look_var(expr.u.call->f.u.var))
437                        , expr.pos);
438                } else {
439                    vmasm.GREF_CALL(vm_operand::name(expr.u.call->f.u.var), expr.pos);
440                }
441                break;
442            default:
443                this->insns_val(expr.u.call->f, vmasm, lenv);
444                vmasm.VREF_CALL(expr.pos);
445            }
446        }
447        break;
448    case expr_kind_list:
449        for(itr = expr.u.list->begin(); itr != expr.u.list->end()
450                ;itr++){
451            this->insns_push(*itr, vmasm, lenv);
452        }
453        vmasm.MKTUPLE(vm_operand::integer(expr.u.list->size()), expr.pos);
454        break;
455    }
456}
457
458void Translator::insns_push(const Expr & expr, vm_assembler & vmasm, LocalEnv * lenv){
459    vector<Expr>::iterator itr;
460
461    switch(expr.kind){
462    case expr_kind_var:
463        if (! lenv->is_toplevel  && lenv->exists(expr.u.var)) {
464            vmasm.LREF_PUSH(vm_operand::integer(lenv->look_var(expr.u.var)), expr.pos);
465        } else {
466            vmasm.GREF_PUSH(vm_operand::name(expr.u.var), expr.pos);
467        }
468        break;
469    case expr_kind_none:
470        vmasm.PUSHI(vm_operand::pyval(Py_val::mk_none()), expr.pos);
471        break;
472    case expr_kind_literal_int:
473        vmasm.PUSHI_NUM(vm_operand::pyval(Py_val::mk_int(expr.u.lit_i)), expr.pos);
474        break;
475    case expr_kind_literal_float:
476        vmasm.PUSHI_NUM(vm_operand::pyval(Py_val::mk_float(expr.u.lit_f)), expr.pos);
477        break;
478    case expr_kind_literal_string:
479        vmasm.PUSHI(vm_operand::pyval(Py_val::mk_string(*expr.u.lit_s)), expr.pos);
480        break;
481    case expr_kind_display_list:
482        for(itr = expr.u.disp->begin();itr != expr.u.disp->end()
483                ;itr++){
484            this->insns_push(*itr, vmasm, lenv);
485        }
486        vmasm.MKLIST(vm_operand::integer(expr.u.disp->size()), expr.pos);
487        vmasm.PUSH(expr.pos);
488        break;
489    case expr_kind_paren:
490        this->insns_push(*expr.u.paren, vmasm, lenv);
491        break;
492    case expr_kind_display_tuple:
493    case expr_kind_display_dict:
494    case expr_kind_operator:
495    case expr_kind_attref:
496    case expr_kind_subscript:
497    case expr_kind_list:
498    case expr_kind_call:
499        this->insns_val(expr, vmasm, lenv);
500        vmasm.PUSH(expr.pos);
501        break;
502    default:
503        perror("Invalid expression");
504    }
505}
506
507void Translator::insns_stms(const vector<Stm> & stm, vm_assembler & vmasm, LocalEnv * lenv){
508    for(int i = 0;i < (int)stm.size();i++){
509        this->insns_stm(stm[i], vmasm, lenv);
510    }
511}
512
513void Translator::insns_loop_stms(const vector<Stm> & stms, vm_assembler & vmasm, int start_addr, vector<int> & break_addrs, LocalEnv * lenv){
514    for(int i = 0;i < (int)stms.size();i++){
515        const Stm & stm = stms[i];
516        switch(stm.kind){
517        case stm_kind_expression:
518        case stm_kind_assignment:
519        case stm_kind_del:
520        case stm_kind_pass:
521        case stm_kind_return:
522        case stm_kind_print:
523        case stm_kind_global:
524        case stm_kind_while:
525        case stm_kind_for:
526        case stm_kind_fundef:
527            this->insns_stm(stm, vmasm, lenv);
528            break;
529        case stm_kind_break:
530            break_addrs.push_back(vmasm.insns.size());
531            vmasm.GOTO(vm_operand::integer(-1), stm.pos);
532            break;
533        case stm_kind_continue:
534            vmasm.GOTO(vm_operand::integer(start_addr), stm.pos);
535            break;
536        case stm_kind_if:
537        {
538            queue<int> goto_endif_queue;
539
540            for(vector<StmIfBranch>::iterator itr = stm.u.i->begin()
541                    ; itr != stm.u.i->end(); itr++){
542                if( itr->elsep ){
543                    this->insns_loop_stms(itr->s, vmasm, start_addr, break_addrs, lenv);
544                } else {
545                    this->insns_val(itr->e, vmasm, lenv);
546                    int gotoinst = vmasm.insns.size();
547                    vmasm.GOTOIFNOT(vm_operand::integer(-1), itr->e.pos);
548                    this->insns_loop_stms(itr->s, vmasm, start_addr, break_addrs, lenv);
549                    if (itr != stm.u.i->end() - 1){
550                        goto_endif_queue.push(vmasm.insns.size());
551                        vmasm.GOTO(vm_operand::integer(-1), itr->s.back().pos);
552                    }
553                    vmasm.insns[gotoinst].operand = (void *)vmasm.insns.size();
554                }
555            }
556
557            while(! goto_endif_queue.empty()){
558                vmasm.insns[goto_endif_queue.front()].operand = (void *)vmasm.insns.size();
559                goto_endif_queue.pop();
560            }
561        }
562        break;
563        }
564    }
565}
566
567void Translator::insns_stm(const Stm & stm, vm_assembler & vmasm, LocalEnv * lenv){
568
569    switch(stm.kind){
570    case stm_kind_expression:
571        this->insns_val(*stm.u.e, vmasm, lenv);
572        break;
573    case stm_kind_assignment:
574        this->insns_val(stm.u.a->val, vmasm, lenv);
575        if (stm.u.a->target.kind == expr_kind_var){
576            if (lenv->is_toplevel || lenv->is_global(stm.u.a->target.u.var)){
577                vmasm.GSET(vm_operand::name(stm.u.a->target.u.var), stm.pos);
578            } else if (lenv != NULL && lenv->exists(stm.u.a->target.u.var)){
579                vmasm.LSET(vm_operand::integer(lenv->look_var(stm.u.a->target.u.var)), stm.pos);
580            } else if(! lenv->is_toplevel) {
581                cerr << "compile error:::" << endl;
582                cerr << "   " << stm.pos.filename << ":" << stm.pos.line_no << endl;
583            } else {
584                vmasm.GSET(vm_operand::name(stm.u.a->target.u.var), stm.pos);
585            }
586        } else if (stm.u.a->target.kind == expr_kind_subscript){
587            Expr & sub = stm.u.a->target;
588            this->insns_push((*sub.u.sub)[0], vmasm, lenv);
589            this->insns_push((*sub.u.sub)[1], vmasm, lenv);
590            this->insns_val(stm.u.a->val, vmasm, lenv);
591            vmasm.SETITEM(stm.pos);
592        }
593        break;
594    case stm_kind_del:
595        if (stm.u.e->kind == expr_kind_subscript){
596            this->insns_push((*stm.u.a->target.u.sub)[0], vmasm, lenv);
597            this->insns_val((*stm.u.a->target.u.sub)[1], vmasm, lenv);
598            vmasm.DELITEM(stm.pos);
599        } else {
600            cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
601        }
602        break;
603    case stm_kind_pass:
604        // do nothing
605        break;
606    case stm_kind_return:
607        this->insns_val(*stm.u.e, vmasm, lenv);
608        vmasm.RET(stm.pos);
609        break;
610    case stm_kind_break:
611        compile_error("no loop to break", stm.pos);
612        break;
613    case stm_kind_continue:
614        compile_error("no loop to continue", stm.pos);
615        break;
616    case stm_kind_print:
617        this->insns_val(*stm.u.e, vmasm, lenv);
618        vmasm.PRINT(stm.pos);
619        break;
620    case stm_kind_global:
621        if (! lenv->is_global(stm.u.g)){
622            compile_error("invalid global declare", stm.pos);
623        }
624        break;
625    case stm_kind_if:
626    {
627        queue<int> goto_endif_queue;
628
629        for(vector<StmIfBranch>::iterator itr = stm.u.i->begin()
630                ; itr != stm.u.i->end(); itr++){
631            if( itr->elsep ){
632                this->insns_stms(itr->s, vmasm, lenv);
633            } else {
634                this->insns_val(itr->e, vmasm, lenv);
635                int gotoinst = vmasm.insns.size();
636                vmasm.GOTOIFNOT(vm_operand::integer(-1), itr->e.pos);
637                this->insns_stms(itr->s, vmasm, lenv);
638                if (itr != stm.u.i->end() - 1){
639                    goto_endif_queue.push(vmasm.insns.size());
640                    vmasm.GOTO(vm_operand::integer(-1), itr->s.back().pos);
641                }
642                vmasm.insns[gotoinst].operand = (void *)vmasm.insns.size();
643            }
644        }
645
646        while(! goto_endif_queue.empty()){
647            vmasm.insns[goto_endif_queue.front()].operand = (void *)vmasm.insns.size();
648            goto_endif_queue.pop();
649        }
650    }
651        break;
652    case stm_kind_while:
653    {
654        int start_addr = vmasm.insns.size();
655        this->insns_val(stm.u.w->e, vmasm, lenv);
656        int gotoif_addr = vmasm.insns.size();
657        vmasm.GOTOIFNOT(vm_operand::integer(-1), stm.pos);
658       
659        vector<int> break_addrs;
660        this->insns_loop_stms(stm.u.w->b, vmasm, start_addr, break_addrs, lenv);
661       
662        vmasm.GOTO(vm_operand::integer(start_addr), stm.pos);
663       
664        int endwhile_addr = vmasm.insns.size();
665        vmasm.insns[gotoif_addr].operand = (void *)endwhile_addr;
666        for(int i = 0;i < (int)break_addrs.size();i++){
667            vmasm.insns[break_addrs[i]].operand = (void *)endwhile_addr;
668        }
669    }
670        break;
671    case stm_kind_for:
672    {
673        if (!lenv->is_toplevel && !lenv->exists(stm.u.f->x)){
674            compile_error("loop variable '" + *stm.u.f->x + "' is not allocated.", stm.pos);
675        }
676        if (!lenv->is_toplevel && lenv->loopvar_queue.empty()){
677            compile_error("loop local variables are not allocated.", stm.pos);
678        }
679       
680        int loopvar = 0;
681        int loopvar_index = 0;
682        int loopvar_limit = 0;
683        int loopseq = 0;
684
685        // for range-for-loop
686        int loopvar_step = 0;
687
688        // 0 ... normal loop
689        // 1 ... range(N) loop
690        // 2 ... range(N, M) loop
691        // 3 ... range(N, M, L) loop
692        int loop_type = 0;
693        if (stm.u.f->e.kind == expr_kind_call
694            && stm.u.f->e.u.call->f.kind == expr_kind_var
695            && stm.u.f->e.u.call->f.u.var->compare("range") == 0){
696            loop_type = stm.u.f->e.u.call->args.size();
697        }
698
699        if (lenv->is_toplevel){
700            switch (loop_type){
701            case 1:
702                loopvar_limit = lenv->current_offset();
703                lenv->add_var(); // loop var limit
704                vmasm.PUSH(stm.pos);
705
706                loopvar_step = lenv->current_offset();
707                lenv->add_var(); // loop var step
708                vmasm.PUSH(stm.pos);
709                break;
710            case 2:
711                loopvar_limit = lenv->current_offset();
712                lenv->add_var(); // loop var limit
713                vmasm.PUSH(stm.pos);
714
715                loopvar_step = lenv->current_offset();
716                lenv->add_var(); // loop var step
717                vmasm.PUSH(stm.pos);
718                break;
719            case 3:
720                loopvar_limit = lenv->current_offset();
721                lenv->add_var(); // loop var limit
722                vmasm.PUSH(stm.pos);
723
724                loopvar_step = lenv->current_offset();
725                lenv->add_var(); // loop var step
726                vmasm.PUSH(stm.pos);
727                break;
728            default:
729                loopvar_index = lenv->current_offset();
730                lenv->add_var(); // loop var index
731                vmasm.PUSH(stm.pos);
732
733                loopvar_limit = lenv->current_offset();
734                lenv->add_var(); // loop var index limit
735                vmasm.PUSH(stm.pos);
736
737                loopseq = lenv->current_offset();
738                lenv->add_var(); // loop sequence
739                vmasm.PUSH(stm.pos);
740            }
741        } else {
742            if (! lenv->is_global(stm.u.f->x)){
743                loopvar = lenv->look_var(stm.u.f->x);
744            }
745            switch (loop_type){
746            case 1:
747                loopvar_limit = lenv->loopvar_queue.front();
748                loopvar_step = lenv->loopvar_queue.front() + 1;
749                break;
750            case 2:
751                loopvar_limit = lenv->loopvar_queue.front();
752                loopvar_step = lenv->loopvar_queue.front() + 1;
753                break;
754            case 3:
755                loopvar_limit = lenv->loopvar_queue.front();
756                loopvar_step = lenv->loopvar_queue.front() + 1;
757                break;
758            default:
759                loopvar_index = lenv->loopvar_queue.front();
760                loopvar_limit = lenv->loopvar_queue.front() + 1;
761                loopseq = lenv->loopvar_queue.front() + 2;
762            }
763            lenv->loopvar_queue.pop();
764        }
765       
766        vector<int> break_addrs;
767
768//         switch (loop_type){
769//         case 1:
770//             cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
771//             break;
772//         case 2:
773//             cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
774//             break;
775//         case 3:
776//             cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
777//             break;
778//         default:
779//             break;
780//         }
781
782        // **** initialize ****
783        switch (loop_type){
784        case 1:
785            vmasm.IMMVAL_NUM(vm_operand::pyval(mkint(0)), stm.pos);
786            if (lenv->is_toplevel || lenv->is_global(stm.u.f->x)){
787                vmasm.GSET(vm_operand::name(stm.u.f->x), stm.pos);
788            } else {
789                vmasm.LSET(vm_operand::integer(loopvar), stm.pos);
790            }
791            this->insns_val(stm.u.f->e.u.call->args[0], vmasm, lenv);
792            vmasm.LSET(vm_operand::integer(loopvar_limit), stm.pos);
793            break;
794        case 2:
795            this->insns_val(stm.u.f->e.u.call->args[0], vmasm, lenv);
796            if (lenv->is_toplevel || lenv->is_global(stm.u.f->x)){
797                vmasm.GSET(vm_operand::name(stm.u.f->x), stm.pos);
798            } else {
799                vmasm.LSET(vm_operand::integer(loopvar), stm.pos);
800            }
801            this->insns_val(stm.u.f->e.u.call->args[1], vmasm, lenv);
802            vmasm.LSET(vm_operand::integer(loopvar_limit), stm.pos);
803            break;
804        case 3:
805            cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
806            break;
807        default:
808            vmasm.IMMVAL_NUM(vm_operand::pyval(Py_val::mk_int(0)), stm.pos);
809            vmasm.LSET(vm_operand::integer(loopvar_index), stm.pos); // init loopvar index
810            this->insns_val(stm.u.f->e, vmasm, lenv);
811            vmasm.LSET(vm_operand::integer(loopseq), stm.pos); // set loop seqence
812            vmasm.LEN(stm.pos);
813            vmasm.LSET(vm_operand::integer(loopvar_limit), stm.pos); // set loop limit
814        }
815        // **** initialize ****
816
817       
818        if (loop_type == 0){
819            vmasm.LREF_PUSH(vm_operand::integer(loopvar_index), stm.pos);
820        } else {
821            if (lenv->is_toplevel || lenv->is_global(stm.u.f->x)){
822                vmasm.GREF_PUSH(vm_operand::name(stm.u.f->x), stm.pos);
823            } else {
824                vmasm.LREF_PUSH(vm_operand::integer(loopvar), stm.pos);
825            }
826        }
827
828        int first_addr = vmasm.insns.size(); // skip loopvar increment if firsttime
829        vmasm.GOTO(vm_operand::integer(-1), stm.pos);
830
831       
832        // **** increment step ****
833        int start_addr = vmasm.insns.size();
834        switch (loop_type){
835        case 1:
836            if (lenv->is_toplevel || lenv->is_global(stm.u.f->x)){
837                vmasm.GINC(vm_operand::name(stm.u.f->x), stm.pos);
838                vmasm.GREF_PUSH(vm_operand::name(stm.u.f->x), stm.pos);
839            } else {
840                vmasm.LINC(vm_operand::integer(loopvar), stm.pos);
841                vmasm.LREF_PUSH(vm_operand::integer(loopvar), stm.pos);
842            }
843            break;
844        case 2:
845            if (lenv->is_toplevel || lenv->is_global(stm.u.f->x)){
846                vmasm.GINC(vm_operand::name(stm.u.f->x), stm.pos);
847                vmasm.GREF_PUSH(vm_operand::name(stm.u.f->x), stm.pos);
848            } else {
849                vmasm.LINC(vm_operand::integer(loopvar), stm.pos);
850                vmasm.LREF_PUSH(vm_operand::integer(loopvar), stm.pos);
851            }
852            break;
853        case 3:
854            cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
855            break;
856        default:
857            vmasm.LINC(vm_operand::integer(loopvar_index), stm.pos);
858            vmasm.LREF_PUSH(vm_operand::integer(loopvar_index), stm.pos);
859
860        }
861       
862        vmasm.insns[first_addr].operand = (void*)vmasm.insns.size();
863        // condition check
864        vmasm.LREF(vm_operand::integer(loopvar_limit), stm.pos);
865        vmasm.NUMLT2(stm.pos);
866        // **** increment step ****
867
868
869           
870        // goto end if loopvar_index >= loopvar_limit
871        break_addrs.push_back(vmasm.insns.size());
872        vmasm.GOTOIFNOT(vm_operand::integer(-1), stm.pos);
873
874
875           
876        // **** load loop sequence ****
877        switch (loop_type){
878        case 1:
879            break;
880        case 2:
881            break;
882        case 3:
883            cerr << "not implemented @ " << __FILE__ << ":" << __LINE__ << endl; exit(1);
884            break;
885        default:
886            vmasm.LREF_PUSH(vm_operand::integer(loopseq), stm.pos);
887            vmasm.LREF(vm_operand::integer(loopvar_index), stm.pos);
888            vmasm.GETITEM(stm.pos);
889            if (lenv->is_toplevel || lenv->is_global(stm.u.f->x)){
890                vmasm.GSET(vm_operand::name(stm.u.f->x), stm.pos);
891            } else {
892                vmasm.LSET(vm_operand::integer(loopvar), stm.pos);
893            }
894        }
895        // **** load loop sequence ****
896
897        this->insns_loop_stms(stm.u.f->b, vmasm, start_addr, break_addrs, lenv);
898        vmasm.GOTO(vm_operand::integer(start_addr), stm.pos);
899
900        int endfor_addr = vmasm.insns.size();
901        for (int i = 0;i < (int)break_addrs.size();i++){
902            vmasm.insns[break_addrs[i]].operand = (void*)endfor_addr;
903        }
904
905        if (lenv->is_toplevel){
906            lenv->pop_var(); // loop var index
907            vmasm.POP(stm.pos);
908
909            lenv->pop_var(); // loop var index limit
910            vmasm.POP(stm.pos);
911
912            lenv->pop_var(); // loop sequence
913            vmasm.POP(stm.pos);
914        }
915    }
916        break;
917    case stm_kind_fundef:
918
919        LocalEnv * prev_lenv = lenv;
920        lenv = new LocalEnv(stm.u.d->f);
921
922        // register arguments as local variable
923        for(vector<symbol_t>::iterator itr = stm.u.d->ps.begin();
924            itr != stm.u.d->ps.end(); itr++){
925            lenv->add_var(*itr);
926        }
927        // allocate stack for local vars
928        this->scan_defun_local_var(stm.u.d->b, lenv);
929
930        py_val_t self;
931        if (prev_lenv->is_toplevel){
932            vmasm.GDEFUN(vm_operand::name(stm.u.d->f), stm.pos);
933            vmasm.GOTO(vm_operand::integer(-1), stm.pos);
934            vmasm.fundef(stm.u.d->f, stm.u.d->ps.size()
935                         , lenv->size() - stm.u.d->ps.size(), *genv, stm.pos);
936            self = genv->lookup_sym(stm.u.d->f);
937        } else {
938            vmasm.LDEFUN(
939                vm_operand::pyval(
940                    self = Py_val::mk_vm_ifun(stm.u.d->f
941                                              , stm.u.d->ps.size()
942                                              , lenv->size() - stm.u.d->ps.size()
943                                              , vmasm.insns.size() + 2
944                                              , stm.pos))
945                , stm.pos);
946            vmasm.GOTO(vm_operand::integer(-1), stm.pos);
947            prev_lenv->add_var(stm.u.d->f);
948        }
949
950        lenv->self = self;
951       
952        int goto_index = vmasm.label_index - 1;
953
954        for(vector<Stm>::iterator itr = stm.u.d->b.begin()
955                ; itr != stm.u.d->b.end(); itr++){
956            this->insns_stm(*itr, vmasm, lenv);
957        }
958        if (stm.u.d->b.back().kind != stm_kind_return){
959            vmasm.RET(stm.u.d->b.back().pos);
960        }
961        vmasm.insns[goto_index].operand = (void*)vmasm.label_index;
962
963        delete(lenv);
964        lenv = prev_lenv;
965        break;
966    }
967}
968
969void Translator::compile_file(const vector<Stm> & stms
970                              , vm_assembler & vmasm, Env & genv){
971    this->genv = &genv;
972
973    LocalEnv toplevel(Symbol::get("*toplevel*"));
974    toplevel.is_toplevel = true;
975
976    this->scan_defun_local_var(stms, &toplevel);
977   
978    for(int i = 0; i < (int)stms.size();i++){
979        this->insns_stm(stms[i], vmasm, &toplevel);
980    }
981}
982
983LocalEnv::LocalEnv(const symbol_t n): name(n){
984    // FP points to the static link
985    /*
986              ...
987              arg2
988              arg1
989           -----------
990              info
991    FP ->  static link
992           -----------
993    */
994    this->offset = 0;
995    this->is_toplevel = false;
996}
997
998void LocalEnv::add_var(const symbol_t var){
999    if (! this->exists(var)){
1000        this->table[var] = this->offset++;
1001    }
1002}
1003
1004// for loop temporaries allocation
1005void LocalEnv::add_var(){
1006    this->offset++;
1007}
1008
1009void LocalEnv::pop_var(){
1010    this->offset--;
1011}
1012
1013int LocalEnv::look_var(const symbol_t var){
1014    if (this->table.find(var) != this->table.end()) {
1015        int ret = this->table[var];
1016        if (ret >= offset){
1017            perror("compile error : LocalEnv::look_var");
1018            exit(1);
1019        }
1020        return ret;
1021    } else {
1022        return -1;
1023    }
1024}
1025
1026int LocalEnv::size(){
1027    return this->offset;
1028}
1029
1030void LocalEnv::mark_global(const symbol_t var){
1031    this->globals[var] = 1;
1032}
1033
1034bool LocalEnv::is_global(const symbol_t var){
1035    return this->globals.find(var) != this->globals.end();
1036}
1037
1038int LocalEnv::current_offset(){
1039    return this->offset;
1040}
1041
1042bool LocalEnv::exists(const symbol_t var){
1043    return this->table.find(var) != this->table.end();
1044}
Note: See TracBrowser for help on using the browser.