예제 #1
0
        private IodineMethod CompileMethod(FunctionDeclaration funcDecl)
        {
            symbolTable.NextScope();
            IodineMethod methodBuilder = new IodineMethod(module, funcDecl.Name, funcDecl.InstanceMethod,
                                                          funcDecl.Parameters.Count,
                                                          symbolTable.CurrentScope.SymbolCount);
            FunctionCompiler compiler = new FunctionCompiler(symbolTable,
                                                             methodBuilder);

            methodBuilder.Variadic           = funcDecl.Variadic;
            methodBuilder.AcceptsKeywordArgs = funcDecl.AcceptsKeywordArgs;
            for (int i = 0; i < funcDecl.Parameters.Count; i++)
            {
                methodBuilder.Parameters [funcDecl.Parameters [i]] = symbolTable.GetSymbol
                                                                         (funcDecl.Parameters [i]).Index;
            }
            funcDecl.Children [0].Visit(compiler);
            AstNode lastNode = funcDecl.Children [0].LastOrDefault();

            if (lastNode != null)
            {
                methodBuilder.EmitInstruction(lastNode.Location, Opcode.LoadNull);
            }
            else
            {
                methodBuilder.EmitInstruction(funcDecl.Location, Opcode.LoadNull);
            }
            methodBuilder.FinalizeLabels();
            symbolTable.LeaveScope();
            return(methodBuilder);
        }
예제 #2
0
 public override void Accept(NameExpression ident)
 {
     if (ident.Value == "_")
     {
         methodBuilder.EmitInstruction(ident.Location, Opcode.LoadTrue);
     }
     else
     {
         methodBuilder.EmitInstruction(ident.Location, Opcode.LoadLocal, temporary);
         methodBuilder.EmitInstruction(ident.Location, Opcode.StoreLocal,
                                       symbolTable.GetSymbol(ident.Value).Index);
         methodBuilder.EmitInstruction(ident.Location, Opcode.LoadTrue);
     }
 }
예제 #3
0
        public override void Accept(BinaryExpression binop)
        {
            if (binop.Operation == BinaryOperation.Assign)
            {
                binop.Right.Visit(this);
                if (binop.Left is NameExpression)
                {
                    NameExpression ident = (NameExpression)binop.Left;
                    Symbol         sym   = symbolTable.GetSymbol(ident.Value);
                    if (sym.Type == SymbolType.Local)
                    {
                        methodBuilder.EmitInstruction(ident.Location, Opcode.StoreLocal, sym.Index);
                        methodBuilder.EmitInstruction(ident.Location, Opcode.LoadLocal, sym.Index);
                    }
                    else
                    {
                        int globalIndex = methodBuilder.Module.DefineConstant(new IodineName(ident.Value));
                        methodBuilder.EmitInstruction(ident.Location, Opcode.StoreGlobal, globalIndex);
                        methodBuilder.EmitInstruction(ident.Location, Opcode.LoadGlobal, globalIndex);
                    }
                }
                else if (binop.Left is GetExpression)
                {
                    GetExpression getattr = binop.Left as GetExpression;
                    getattr.Target.Visit(this);
                    int attrIndex = methodBuilder.Module.DefineConstant(new IodineName(getattr.Field));
                    methodBuilder.EmitInstruction(getattr.Location, Opcode.StoreAttribute, attrIndex);
                    getattr.Target.Visit(this);
                    methodBuilder.EmitInstruction(getattr.Location, Opcode.LoadAttribute, attrIndex);
                }
                else if (binop.Left is IndexerExpression)
                {
                    IndexerExpression indexer = binop.Left as IndexerExpression;
                    indexer.Target.Visit(this);
                    indexer.Index.Visit(this);
                    methodBuilder.EmitInstruction(indexer.Location, Opcode.StoreIndex);
                    binop.Left.Visit(this);
                }
            }
            else if (binop.Operation == BinaryOperation.InstanceOf)
            {
                binop.Right.Visit(this);
                binop.Left.Visit(this);
                methodBuilder.EmitInstruction(binop.Location, Opcode.InstanceOf);
            }
            else if (binop.Operation == BinaryOperation.NotInstanceOf)
            {
                binop.Right.Visit(this);
                binop.Left.Visit(this);
                methodBuilder.EmitInstruction(binop.Location, Opcode.InstanceOf);
                methodBuilder.EmitInstruction(binop.Location, Opcode.UnaryOp, (int)UnaryOperation.BoolNot);
            }
            else if (binop.Operation == BinaryOperation.DynamicCast)
            {
                binop.Right.Visit(this);
                binop.Left.Visit(this);
                methodBuilder.EmitInstruction(binop.Location, Opcode.DynamicCast);
            }
            else if (binop.Operation == BinaryOperation.NullCoalescing)
            {
                binop.Right.Visit(this);
                binop.Left.Visit(this);
                methodBuilder.EmitInstruction(binop.Location, Opcode.NullCoalesce);
            }
            else
            {
                IodineLabel shortCircuitTrueLabel  = methodBuilder.CreateLabel();
                IodineLabel shortCircuitFalseLabel = methodBuilder.CreateLabel();
                IodineLabel endLabel = methodBuilder.CreateLabel();
                binop.Left.Visit(this);

                /*
                 * Short circuit evaluation
                 */
                switch (binop.Operation)
                {
                case BinaryOperation.BoolAnd:
                    methodBuilder.EmitInstruction(binop.Location, Opcode.Dup);
                    methodBuilder.EmitInstruction(binop.Location, Opcode.JumpIfFalse,
                                                  shortCircuitFalseLabel);
                    break;

                case BinaryOperation.BoolOr:
                    methodBuilder.EmitInstruction(binop.Location, Opcode.Dup);
                    methodBuilder.EmitInstruction(binop.Location, Opcode.JumpIfTrue,
                                                  shortCircuitTrueLabel);
                    break;
                }
                binop.Right.Visit(this);
                methodBuilder.EmitInstruction(binop.Location, Opcode.BinOp, (int)binop.Operation);
                methodBuilder.EmitInstruction(binop.Location, Opcode.Jump, endLabel);
                methodBuilder.MarkLabelPosition(shortCircuitTrueLabel);
                methodBuilder.EmitInstruction(binop.Location, Opcode.Pop);
                methodBuilder.EmitInstruction(binop.Location, Opcode.LoadTrue);
                methodBuilder.EmitInstruction(binop.Location, Opcode.Jump, endLabel);
                methodBuilder.MarkLabelPosition(shortCircuitFalseLabel);
                methodBuilder.EmitInstruction(binop.Location, Opcode.Pop);
                methodBuilder.EmitInstruction(binop.Location, Opcode.LoadFalse);
                methodBuilder.MarkLabelPosition(endLabel);
            }
        }