예제 #1
0
 public void Visit(Node node)
 {
     if (node is ClassDeclarationNode)
     {
         GSharpClass clazz = new GSharpClass(((ClassDeclarationNode)node).Name, CompileMethod(((ClassDeclarationNode)node).Constructor, true));
         for (int i = 1; i < node.Children.Count; i++)
         {
             clazz.AddInstanceMethod(CompileMethod((FunctionDeclarationNode)node.Children[i], true));
         }
         module.SetAttribute(((ClassDeclarationNode)node).Name, clazz);
     }
     else if (node is CodeBlock)
     {
         VisitSubnodes(node);
     }
     else if (node is EnumDeclarationNode)
     {
         GSharpEnum ienum = new GSharpEnum();
         foreach (string name in ((EnumDeclarationNode)node).Items.Keys)
         {
             ienum.AddItem(name, ((EnumDeclarationNode)node).Items[name]);
         }
         module.SetAttribute(((EnumDeclarationNode)node).Name, ienum);
     }
     else if (node is FunctionDeclarationNode)
     {
         module.AddMethod(CompileMethod((FunctionDeclarationNode)node, false));
     }
     else if (node is ScopeNode)
     {
         VisitSubnodes(node);
     }
     else if (node is UseNode)
     {
         GSharpModule import = GSharpModule.CompileModule(((UseNode)node).Module);
         if (import != null)
         {
             module.SetAttribute(((UseNode)node).Module, import);
         }
     }
 }
예제 #2
0
        public void Visit(Node node)
        {
            if (node is ArgumentsListNode)
            {
                VisitSubnodes(node);
            }
            else if (node is BinaryOperationNode)
            {
                BinaryOperationNode binop = (BinaryOperationNode)node;

                if (binop.BinaryOperation == BinaryOperation.Assignment)
                {
                    Visit(binop.Right);

                    if (binop.Left is IdentifierNode)
                    {
                        IdentifierNode ident = (IdentifierNode)binop.Left;
                        Symbol         sym   = symbolTable.GetSymbol(ident.Name);
                        if (sym.Type == SymbolType.Local)
                        {
                            methodBuilder.EmitInstruction(OperationCode.StoreLocal, sym.Index);
                            methodBuilder.EmitInstruction(OperationCode.LoadLocal, sym.Index);
                        }
                        else
                        {
                            int globalIndex = methodBuilder.Module.DefineConstant(new GSharpName(ident.Name));
                            methodBuilder.EmitInstruction(OperationCode.StoreGlobal, globalIndex);
                            methodBuilder.EmitInstruction(OperationCode.LoadGlobal, globalIndex);
                        }
                    }
                    else if (binop.Left is GetAttributeNode)
                    {
                        Visit(((GetAttributeNode)binop.Left).Target);
                        int attrIndex = methodBuilder.Module.DefineConstant(new GSharpName(((GetAttributeNode)binop.Left).Field));
                        methodBuilder.EmitInstruction(OperationCode.StoreAttribute, attrIndex);
                        Visit(((GetAttributeNode)binop.Left).Target);
                        methodBuilder.EmitInstruction(OperationCode.LoadAttribute, attrIndex);
                    }
                    else if (binop.Left is IndexerNode)
                    {
                        Visit(((IndexerNode)binop.Left).Target);
                        Visit(((IndexerNode)binop.Left).Index);
                        methodBuilder.EmitInstruction(OperationCode.StoreIndex);
                        Visit(binop.Left);
                    }
                }
                else if (binop.BinaryOperation == BinaryOperation.InstanceOf)
                {
                    Visit(binop.Right);
                    Visit(binop.Left);
                    methodBuilder.EmitInstruction(OperationCode.InstanceOf);
                }
                else
                {
                    Visit(binop.Right);
                    Visit(binop.Left);
                    methodBuilder.EmitInstruction(OperationCode.BinaryOperation, (int)binop.BinaryOperation);
                }
            }
            else if (node is BooleanFalseNode)
            {
                methodBuilder.EmitInstruction(OperationCode.LoadFalse);
            }
            else if (node is BooleanTrueNode)
            {
                methodBuilder.EmitInstruction(OperationCode.LoadTrue);
            }
            else if (node is CodeBlock)
            {
                VisitSubnodes(node);
            }
            else if (node is EnumDeclarationNode)
            {
                GSharpEnum ienum = new GSharpEnum();
                foreach (string name in ((EnumDeclarationNode)node).Items.Keys)
                {
                    ienum.AddItem(name, ((EnumDeclarationNode)node).Items[name]);
                }
                methodBuilder.EmitInstruction(OperationCode.LoadConst, methodBuilder.Module.DefineConstant(ienum));
                methodBuilder.EmitInstruction(OperationCode.StoreLocal, symbolTable.GetSymbol(((EnumDeclarationNode)node).Name).Index);
            }
            else if (node is ExpressionNode)
            {
                VisitSubnodes(node);
            }
            else if (node is ForNode)
            {
                GSharpLabel forLabel   = methodBuilder.CreateLabel();
                GSharpLabel breakLabel = methodBuilder.CreateLabel();
                breakLabels.Push(breakLabel);
                Visit(((ForNode)node).Initializer);
                methodBuilder.MarkLabelPosition(forLabel);
                Visit(((ForNode)node).Condition);
                methodBuilder.EmitInstruction(OperationCode.JumpIfFalse, breakLabel);
                Visit(((ForNode)node).Body);
                Visit(((ForNode)node).AfterThought);
                methodBuilder.EmitInstruction(OperationCode.Jump, forLabel);
                methodBuilder.MarkLabelPosition(breakLabel);
                breakLabels.Pop();
            }
            else if (node is FunctionCallNode)
            {
                Visit(((FunctionCallNode)node).Arguments);
                Visit(((FunctionCallNode)node).Target);
                methodBuilder.EmitInstruction(OperationCode.Invoke, ((FunctionCallNode)node).Arguments.Children.Count);
            }
            else if (node is GetAttributeNode)
            {
                Visit(((GetAttributeNode)node).Target);
                methodBuilder.EmitInstruction(OperationCode.LoadAttribute, methodBuilder.Module.DefineConstant(new GSharpName(((GetAttributeNode)node).Field)));
            }
            else if (node is IdentifierNode)
            {
                IdentifierNode ident = (IdentifierNode)node;

                if (symbolTable.IsSymbolDefined(ident.Name))
                {
                    Symbol sym = symbolTable.GetSymbol(ident.Name);
                    if (sym.Type == SymbolType.Local)
                    {
                        methodBuilder.EmitInstruction(OperationCode.LoadLocal, sym.Index);
                    }
                    else
                    {
                        methodBuilder.EmitInstruction(OperationCode.LoadGlobal, methodBuilder.Module.DefineConstant(new GSharpName(ident.Name)));
                    }
                }
                else
                {
                    methodBuilder.EmitInstruction(OperationCode.LoadGlobal, methodBuilder.Module.DefineConstant(new GSharpName(ident.Name)));
                }
            }
            else if (node is IfNode)
            {
                GSharpLabel elseLabel = methodBuilder.CreateLabel();
                GSharpLabel endLabel  = methodBuilder.CreateLabel();
                Visit(((IfNode)node).Condition);
                methodBuilder.EmitInstruction(OperationCode.JumpIfFalse, elseLabel);
                Visit(((IfNode)node).Body);
                methodBuilder.EmitInstruction(OperationCode.Jump, endLabel);
                methodBuilder.MarkLabelPosition(elseLabel);
                Visit(((IfNode)node).ElseBody);
                methodBuilder.MarkLabelPosition(endLabel);
            }
            else if (node is IndexerNode)
            {
                Visit(((IndexerNode)node).Target);
                Visit(((IndexerNode)node).Index);
                methodBuilder.EmitInstruction(OperationCode.LoadIndex);
            }
            else if (node is NumberNode)
            {
                methodBuilder.EmitInstruction(OperationCode.LoadConst, methodBuilder.Module.DefineConstant(new GSharpInteger(((NumberNode)node).Value)));
            }
            else if (node is ReturnNode)
            {
                VisitSubnodes(node);
                methodBuilder.EmitInstruction(OperationCode.Return);
            }
            else if (node is ScopeNode)
            {
                symbolTable.CurrentScope = symbolTable.CurrentScope.ChildScopes[currentScope++];
                FunctionCompiler scopeCompiler = new FunctionCompiler(symbolTable, methodBuilder);
                foreach (Node n in node.Children)
                {
                    scopeCompiler.Visit(n);
                }
                symbolTable.CurrentScope = symbolTable.CurrentScope.ParentScope;
            }
            else if (node is StringNode)
            {
                methodBuilder.EmitInstruction(OperationCode.LoadConst, methodBuilder.Module.DefineConstant(new GSharpString(((StringNode)node).Value)));
            }
            else if (node is ThisNode)
            {
                methodBuilder.EmitInstruction(OperationCode.LoadThis);
            }
            else if (node is WhileNode)
            {
                GSharpLabel whileLabel = methodBuilder.CreateLabel();
                GSharpLabel breakLabel = methodBuilder.CreateLabel();
                breakLabels.Push(breakLabel);
                methodBuilder.MarkLabelPosition(whileLabel);
                Visit(((WhileNode)node).Condition);
                methodBuilder.EmitInstruction(OperationCode.JumpIfFalse, breakLabel);
                Visit(((WhileNode)node).Body);
                methodBuilder.EmitInstruction(OperationCode.Jump, whileLabel);
                methodBuilder.MarkLabelPosition(breakLabel);
                breakLabels.Pop();
            }
        }