コード例 #1
0
ファイル: typeof.cs プロジェクト: zjmit/go2cs
                                    // typeOf returns a distinct single-bit value that represents the type of n.
                                    //
                                    // Various implementations were benchmarked with BenchmarkNewInspector:
                                    //                                GOGC=off
                                    // - type switch                4.9-5.5ms    2.1ms
                                    // - binary search over a sorted list of types  5.5-5.9ms    2.5ms
                                    // - linear scan, frequency-ordered list     5.9-6.1ms    2.7ms
                                    // - linear scan, unordered list        6.4ms        2.7ms
                                    // - hash table                    6.5ms        3.1ms
                                    // A perfect hash seemed like overkill.
                                    //
                                    // The compiler's switch statement is the clear winner
                                    // as it produces a binary tree in code,
                                    // with constant conditions and good branch prediction.
                                    // (Sadly it is the most verbose in source code.)
                                    // Binary search suffered from poor branch prediction.
                                    //
                                    private static ulong typeOf(ast.Node n)
                                    {
                                        // Fast path: nearly half of all nodes are identifiers.
                                        {
                                            ptr <ast.Ident> (_, ok) = n._ <ptr <ast.Ident> >();

                                            if (ok)
                                            {
                                                return(1L << (int)(nIdent));
                                            }

                                            // These cases include all nodes encountered by ast.Inspect.
                                        }

                                        // These cases include all nodes encountered by ast.Inspect.
                                        switch (n.type())
                                        {
                                        case ptr <ast.ArrayType> _:
                                            return(1L << (int)(nArrayType));

                                            break;

                                        case ptr <ast.AssignStmt> _:
                                            return(1L << (int)(nAssignStmt));

                                            break;

                                        case ptr <ast.BadDecl> _:
                                            return(1L << (int)(nBadDecl));

                                            break;

                                        case ptr <ast.BadExpr> _:
                                            return(1L << (int)(nBadExpr));

                                            break;

                                        case ptr <ast.BadStmt> _:
                                            return(1L << (int)(nBadStmt));

                                            break;

                                        case ptr <ast.BasicLit> _:
                                            return(1L << (int)(nBasicLit));

                                            break;

                                        case ptr <ast.BinaryExpr> _:
                                            return(1L << (int)(nBinaryExpr));

                                            break;

                                        case ptr <ast.BlockStmt> _:
                                            return(1L << (int)(nBlockStmt));

                                            break;

                                        case ptr <ast.BranchStmt> _:
                                            return(1L << (int)(nBranchStmt));

                                            break;

                                        case ptr <ast.CallExpr> _:
                                            return(1L << (int)(nCallExpr));

                                            break;

                                        case ptr <ast.CaseClause> _:
                                            return(1L << (int)(nCaseClause));

                                            break;

                                        case ptr <ast.ChanType> _:
                                            return(1L << (int)(nChanType));

                                            break;

                                        case ptr <ast.CommClause> _:
                                            return(1L << (int)(nCommClause));

                                            break;

                                        case ptr <ast.Comment> _:
                                            return(1L << (int)(nComment));

                                            break;

                                        case ptr <ast.CommentGroup> _:
                                            return(1L << (int)(nCommentGroup));

                                            break;

                                        case ptr <ast.CompositeLit> _:
                                            return(1L << (int)(nCompositeLit));

                                            break;

                                        case ptr <ast.DeclStmt> _:
                                            return(1L << (int)(nDeclStmt));

                                            break;

                                        case ptr <ast.DeferStmt> _:
                                            return(1L << (int)(nDeferStmt));

                                            break;

                                        case ptr <ast.Ellipsis> _:
                                            return(1L << (int)(nEllipsis));

                                            break;

                                        case ptr <ast.EmptyStmt> _:
                                            return(1L << (int)(nEmptyStmt));

                                            break;

                                        case ptr <ast.ExprStmt> _:
                                            return(1L << (int)(nExprStmt));

                                            break;

                                        case ptr <ast.Field> _:
                                            return(1L << (int)(nField));

                                            break;

                                        case ptr <ast.FieldList> _:
                                            return(1L << (int)(nFieldList));

                                            break;

                                        case ptr <ast.File> _:
                                            return(1L << (int)(nFile));

                                            break;

                                        case ptr <ast.ForStmt> _:
                                            return(1L << (int)(nForStmt));

                                            break;

                                        case ptr <ast.FuncDecl> _:
                                            return(1L << (int)(nFuncDecl));

                                            break;

                                        case ptr <ast.FuncLit> _:
                                            return(1L << (int)(nFuncLit));

                                            break;

                                        case ptr <ast.FuncType> _:
                                            return(1L << (int)(nFuncType));

                                            break;

                                        case ptr <ast.GenDecl> _:
                                            return(1L << (int)(nGenDecl));

                                            break;

                                        case ptr <ast.GoStmt> _:
                                            return(1L << (int)(nGoStmt));

                                            break;

                                        case ptr <ast.Ident> _:
                                            return(1L << (int)(nIdent));

                                            break;

                                        case ptr <ast.IfStmt> _:
                                            return(1L << (int)(nIfStmt));

                                            break;

                                        case ptr <ast.ImportSpec> _:
                                            return(1L << (int)(nImportSpec));

                                            break;

                                        case ptr <ast.IncDecStmt> _:
                                            return(1L << (int)(nIncDecStmt));

                                            break;

                                        case ptr <ast.IndexExpr> _:
                                            return(1L << (int)(nIndexExpr));

                                            break;

                                        case ptr <ast.InterfaceType> _:
                                            return(1L << (int)(nInterfaceType));

                                            break;

                                        case ptr <ast.KeyValueExpr> _:
                                            return(1L << (int)(nKeyValueExpr));

                                            break;

                                        case ptr <ast.LabeledStmt> _:
                                            return(1L << (int)(nLabeledStmt));

                                            break;

                                        case ptr <ast.MapType> _:
                                            return(1L << (int)(nMapType));

                                            break;

                                        case ptr <ast.Package> _:
                                            return(1L << (int)(nPackage));

                                            break;

                                        case ptr <ast.ParenExpr> _:
                                            return(1L << (int)(nParenExpr));

                                            break;

                                        case ptr <ast.RangeStmt> _:
                                            return(1L << (int)(nRangeStmt));

                                            break;

                                        case ptr <ast.ReturnStmt> _:
                                            return(1L << (int)(nReturnStmt));

                                            break;

                                        case ptr <ast.SelectStmt> _:
                                            return(1L << (int)(nSelectStmt));

                                            break;

                                        case ptr <ast.SelectorExpr> _:
                                            return(1L << (int)(nSelectorExpr));

                                            break;

                                        case ptr <ast.SendStmt> _:
                                            return(1L << (int)(nSendStmt));

                                            break;

                                        case ptr <ast.SliceExpr> _:
                                            return(1L << (int)(nSliceExpr));

                                            break;

                                        case ptr <ast.StarExpr> _:
                                            return(1L << (int)(nStarExpr));

                                            break;

                                        case ptr <ast.StructType> _:
                                            return(1L << (int)(nStructType));

                                            break;

                                        case ptr <ast.SwitchStmt> _:
                                            return(1L << (int)(nSwitchStmt));

                                            break;

                                        case ptr <ast.TypeAssertExpr> _:
                                            return(1L << (int)(nTypeAssertExpr));

                                            break;

                                        case ptr <ast.TypeSpec> _:
                                            return(1L << (int)(nTypeSpec));

                                            break;

                                        case ptr <ast.TypeSwitchStmt> _:
                                            return(1L << (int)(nTypeSwitchStmt));

                                            break;

                                        case ptr <ast.UnaryExpr> _:
                                            return(1L << (int)(nUnaryExpr));

                                            break;

                                        case ptr <ast.ValueSpec> _:
                                            return(1L << (int)(nValueSpec));

                                            break;
                                        }
                                        return(0L);
                                    }
コード例 #2
0
        private static ast.Visitor Visit(this simplifier s, ast.Node node)
        {
            switch (node.type())
            {
            case ptr <ast.CompositeLit> n:
                var      outer = n;
                ast.Expr keyType = default;                    ast.Expr eltType = default;

                switch (outer.Type.type())
                {
                case ptr <ast.ArrayType> typ:
                    eltType = typ.Elt;
                    break;

                case ptr <ast.MapType> typ:
                    keyType = typ.Key;
                    eltType = typ.Value;
                    break;
                }

                if (eltType != null)
                {
                    reflect.Value ktyp = default;
                    if (keyType != null)
                    {
                        ktyp = reflect.ValueOf(keyType);
                    }

                    var typ = reflect.ValueOf(eltType);
                    foreach (var(i, x) in outer.Elts)
                    {
                        var px = _addr_outer.Elts[i];
                        // look at value of indexed/named elements
                        {
                            ptr <ast.KeyValueExpr> (t, ok) = x._ <ptr <ast.KeyValueExpr> >();

                            if (ok)
                            {
                                if (keyType != null)
                                {
                                    s.simplifyLiteral(ktyp, keyType, t.Key, _addr_t.Key);
                                }

                                x  = t.Value;
                                px = _addr_t.Value;
                            }
                        }

                        s.simplifyLiteral(typ, eltType, x, px);
                    }
                    // node was simplified - stop walk (there are no subnodes to simplify)
                    return(null);
                }

                break;

            case ptr <ast.SliceExpr> n:
                if (n.Max != null)
                {
                    // - 3-index slices always require the 2nd and 3rd index
                    break;
                }

                {
                    ptr <ast.Ident> (s, _) = n.X._ <ptr <ast.Ident> >();

                    if (s != null && s.Obj != null)
                    {
                        // the array/slice object is a single, resolved identifier
                        {
                            ptr <ast.CallExpr> (call, _) = n.High._ <ptr <ast.CallExpr> >();

                            if (call != null && len(call.Args) == 1L && !call.Ellipsis.IsValid())
                            {
                                // the high expression is a function call with a single argument
                                {
                                    ptr <ast.Ident> (fun, _) = call.Fun._ <ptr <ast.Ident> >();

                                    if (fun != null && fun.Name == "len" && fun.Obj == null)
                                    {
                                        // the function called is "len" and it is not locally defined; and
                                        // because we don't have dot imports, it must be the predefined len()
                                        {
                                            ptr <ast.Ident> (arg, _) = call.Args[0L]._ <ptr <ast.Ident> >();

                                            if (arg != null && arg.Obj == s.Obj)
                                            {
                                                // the len argument is the array/slice object
                                                n.High = null;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    // Note: We could also simplify slice expressions of the form s[0:b] to s[:b]
                    //       but we leave them as is since sometimes we want to be very explicit
                    //       about the lower bound.
                    // An example where the 0 helps:
                    //       x, y, z := b[0:2], b[2:4], b[4:6]
                    // An example where it does not:
                    //       x, y := b[:n], b[n:]
                }
                // Note: We could also simplify slice expressions of the form s[0:b] to s[:b]
                //       but we leave them as is since sometimes we want to be very explicit
                //       about the lower bound.
                // An example where the 0 helps:
                //       x, y, z := b[0:2], b[2:4], b[4:6]
                // An example where it does not:
                //       x, y := b[:n], b[n:]
                break;

            case ptr <ast.RangeStmt> n:
                if (isBlank(n.Value))
                {
                    n.Value = null;
                }

                if (isBlank(n.Key) && n.Value == null)
                {
                    n.Key = null;
                }

                break;
            }

            return(s);
        }