Esempio n. 1
0
        public Instr Emit_RangeInc(Dot2Node node)
        {
            node.car.Compile(this);
            node.cdr.Compile(this);

            Pop(2);

            var instr = AppendInstruction(new Instr(OpCode.RangeInc, vm.CurrentScope.sp));

            Push();

            return(instr);
        }
Esempio n. 2
0
        private void Gen(CodeGenScope s, AstNode tree, int val)
        {
            int nt;
            int rlev = s.rlev;

            if (tree == null)
            {
                if (val != NOVAL)
                {
                    GenOp_1(s, OpCode.LoadNIL, s.sp);
                    Push(s, 1);
                }
                return;
            }

            s.rlev++;
            if (s.rlev > CodeGenScope.MAX_RLEV_LENGTH)
            {
                throw new Exception("too complex expression");
            }

            s.lineno = tree.lineno;

            Console.WriteLine($"Gen: {tree}");

            switch (tree.type)
            {
            case AstNodeType.LAMBDA:
                if (val != NOVAL)
                {
                    int idx = LambdaBody(s, tree, true);
                    GenOp_2(s, OpCode.Lambda, s.sp, idx);
                    Push(s);
                }
                break;

            case AstNodeType.BLOCK:
                if (val != NOVAL)
                {
                    int idx = LambdaBody(s, tree, true);
                    GenOp_2(s, OpCode.Block, s.sp, idx);
                    Push(s);
                }
                break;

            case AstNodeType.IF:
                int     pos1, pos2;
                IfNode  ifNode   = tree.As <IfNode> ();
                AstNode elsepart = ifNode.@else;

                if (ifNode.cond == null)
                {
                    Gen(s, elsepart, val);
                    goto exit;
                }

                switch (ifNode.cond.type)
                {
                case AstNodeType.TRUE:
                case AstNodeType.INT:
                case AstNodeType.STR:
                    Gen(s, ifNode.then, val);
                    goto exit;

                case AstNodeType.FALSE:
                case AstNodeType.NIL:
                    Gen(s, elsepart, val);
                    goto exit;
                }

                Gen(s, ifNode.cond, val);
                Pop(s, 1);

                pos1 = GenJmp2(s, OpCode.JmpNot, s.sp, 0, val);
                Gen(s, ifNode.then, val);

                if (elsepart != null)
                {
                    if (val != NOVAL)
                    {
                        Pop(s, 1);
                    }
                    pos2 = GenJmp(s, OpCode.Jmp, 0);
                    Gen(s, elsepart, val);
                }
                else
                {
                    if (val != NOVAL)
                    {
                        Pop(s, 1);
                        pos2 = GenJmp(s, OpCode.Jmp, 0);
                        GenOp_1(s, OpCode.LoadNIL, s.sp);
                        Push(s, 1);
                    }
                    else
                    {
                        //dispatch ( s, pos1 );
                    }
                }

                break;

            case AstNodeType.AND:
            case AstNodeType.OR:
            case AstNodeType.WHILE:
            case AstNodeType.UNTIL:
            case AstNodeType.FOR:
                ForBody(s, tree);
                if (val != NOVAL)
                {
                    Push(s);
                }
                break;

            case AstNodeType.CASE:
                // TODO:
                break;

            case AstNodeType.SCOPE:
                ScopeBody(s, tree, NOVAL);
                break;

            case AstNodeType.FCALL:
            case AstNodeType.CALL:
                GenCall(s, tree, 0, val, false);
                break;

            case AstNodeType.SCALL:
                GenCall(s, tree, 0, 0, true);
                break;

            case AstNodeType.DOT2:
                Dot2Node dot2Node = tree.As <Dot2Node> ();
                Gen(s, dot2Node.car, val);
                Gen(s, dot2Node.cdr, val);
                if (val != NOVAL)
                {
                    Pop(s); Pop(s);
                    GenOp_1(s, OpCode.RangeInc, s.sp);
                    Push(s);
                }
                break;

            case AstNodeType.DOT3:
                Dot3Node dot3Node = tree.As <Dot3Node> ();
                Gen(s, dot3Node.car, val);
                Gen(s, dot3Node.cdr, val);
                if (val != NOVAL)
                {
                    Pop(s); Pop(s);
                    GenOp_1(s, OpCode.RangeExc, s.sp);
                    Push(s);
                }
                break;

            case AstNodeType.COLON2:
            case AstNodeType.COLON3:
            case AstNodeType.ARRAY:
            case AstNodeType.HASH:
            case AstNodeType.KW_HASH:
                // TODO:
                break;

            case AstNodeType.SPLAT:
                // TODO:
                break;

            case AstNodeType.ASGN:
                GenAssignment(s, tree, s.sp, val);
                break;

            case AstNodeType.MASGN:
            case AstNodeType.OP_ASGN:
            case AstNodeType.SUPER:
            case AstNodeType.RETURN:
            case AstNodeType.YIELD:
            case AstNodeType.BREAK:
            case AstNodeType.NEXT:
            case AstNodeType.REDO:
            case AstNodeType.RETRY:
                // TODO:
                break;

            case AstNodeType.LVAR:
                if (val != NOVAL)
                {
                    int idx = s.FindLocalVarIdx(nsym(tree));

                    if (idx > 0)
                    {
                        GenMove(s, s.sp, idx, val != 0);
                        if (val != 0 && s.parser.on_eval)
                        {
                            GenOp_0(s, OpCode.Nop);
                        }
                    }
                    else
                    {
                        int          lv = 0;
                        CodeGenScope up = s.prev;

                        while (up != null)
                        {
                            idx = up.FindLocalVarIdx(nsym(tree));
                            if (idx > 0)
                            {
                                GenOp_3(s, OpCode.GetUpVar, s.sp, idx, lv);
                                break;
                            }

                            lv++;
                            up = up.prev;
                        }
                    }

                    Push(s);
                }
                break;

            case AstNodeType.GVAR:
                int gsym = NewSym(s, nsym(tree));
                GenOp_2(s, OpCode.GetGV, s.sp, gsym);
                if (val != 0)
                {
                    Push(s);
                }
                break;

            case AstNodeType.IVAR:
                int isym = NewSym(s, nsym(tree));
                GenOp_2(s, OpCode.GetIV, s.sp, isym);
                if (val != 0)
                {
                    Push(s);
                }
                break;

            case AstNodeType.CVAR:
                int csym = NewSym(s, nsym(tree));
                GenOp_2(s, OpCode.GetCV, s.sp, csym);
                if (val != NOVAL)
                {
                    Push(s);
                }
                break;

            case AstNodeType.CONST:
                int cnstSym = NewSym(s, nsym(tree));
                GenOp_2(s, OpCode.GetConst, s.sp, cnstSym);
                if (val != NOVAL)
                {
                    Push(s);
                }
                break;

            case AstNodeType.DEFINED:
                Gen(s, tree, val);
                break;

            case AstNodeType.ARG:
                /* should not happen */
                break;

            case AstNodeType.BLOCK_ARG:
                Gen(s, tree, val);
                break;

            case AstNodeType.INT:
                if (val != NOVAL)
                {
                    int off = NewLiteral(s, tree.As <IntNode>().value);
                    GenOp_2(s, OpCode.LoadI, s.sp, off);

                    Push(s);
                }
                break;

            case AstNodeType.FLOAT:
                if (val != NOVAL)
                {
                    int off = NewLiteral(s, tree.As <FloatNode>().value);
                    GenOp_2(s, OpCode.LoadI, s.sp, off);

                    Push(s);
                }
                break;

            case AstNodeType.STR:
                if (val != NOVAL)
                {
                    int off = NewLiteral(s, Value.Str(tree.As <StringNode>().token));
                    GenOp_2(s, OpCode.String, s.sp, off);

                    Push(s);
                }
                break;

            case AstNodeType.SYM:
                if (val != NOVAL)
                {
                    int off = NewSym(s, nsym(tree));
                    GenOp_2(s, OpCode.LoadSYM, s.sp, off);

                    Push(s);
                }
                break;

            case AstNodeType.SELF:
                if (val != NOVAL)
                {
                    GenOp_1(s, OpCode.LoadSelf, s.sp);
                    Push(s);
                }
                break;

            case AstNodeType.NIL:
                if (val != NOVAL)
                {
                    GenOp_1(s, OpCode.LoadNIL, s.sp);
                    Push(s);
                }
                break;

            case AstNodeType.TRUE:
                if (val != NOVAL)
                {
                    GenOp_1(s, OpCode.LoadT, s.sp);
                    Push(s);
                }
                break;

            case AstNodeType.FALSE:
                if (val != NOVAL)
                {
                    GenOp_1(s, OpCode.LoadF, s.sp);
                    Push(s);
                }
                break;

            case AstNodeType.CLASS:
            case AstNodeType.MODULE:
            case AstNodeType.SCLASS:
            case AstNodeType.DEF:
            case AstNodeType.SDEF:
                // TODO:
                break;

            case AstNodeType.CMD_LIST:
                foreach (var cmd in tree.As <ExpressionListNode> ().exprs)
                {
                    Gen(s, cmd, val);
                }
                break;

            default:
                break;
            }

exit:
            s.rlev = rlev;
        }