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); }
private static void simplifyLiteral(this simplifier s, reflect.Value typ, ast.Expr astType, ast.Expr x, ptr <ast.Expr> _addr_px) { ref ast.Expr px = ref _addr_px.val;