public static IsArrayKeyword ( Symbol s ) : bool | ||
s | Symbol | |
Résultat | bool |
private void PrintTypeWithArraySizes(LNode cons) { LNode type = cons.Target; // Called by AutoPrintNewOperator; type is already validated. Debug.Assert(type.Calls(S.Of, 2) && S.IsArrayKeyword(type.Args[0].Name)); // We have to deal with the "constructor arguments" specially. // First of all, the constructor arguments appear inside the // square brackets, which is unusual: int[x + y]. But there's // something much more strange in case of arrays of arrays: the // order of the square brackets must be reversed. If the // constructor argument is 10, an array of two-dimensional // arrays of int is written int[10][,], rather than int[,][10] // which would be easier to handle. int dims = cons.ArgCount, innerDims; LNode elemType = type.Args[1]; var dimStack = InternalList <int> .Empty; while ((innerDims = CountDimensionsIfArrayType(elemType)) != 0) { dimStack.Add(innerDims); elemType = elemType.Args[1]; } PrintType(elemType, EP.Primary.LeftContext(ContinueExpr)); _out.Write('[', true); bool first = true; foreach (var arg in cons.Args) { if (first) { first = false; } else { WriteThenSpace(',', SpaceOpt.AfterComma); } PrintExpr(arg, StartExpr, 0); } _out.Write(']', true); // Write the brackets for the inner array types for (int i = dimStack.Count - 1; i >= 0; i--) { _out.Write(S.GetArrayKeyword(dimStack[i]).Name, true); } }
static Symbol SpecialTypeKind(LNode n, Ambiguity flags, Precedence context) { // detects when notation for special types applies: Foo[], Foo*, Foo? // assumes IsComplexIdentifier() is already known to be true LNode first; if (n.Calls(S.Of, 2) && (first = n.Args[0]).IsId && (flags & Ambiguity.TypeContext) != 0) { var kind = first.Name; if (S.IsArrayKeyword(kind) || kind == S.QuestionMark) { return(kind); } if (kind == S._Pointer && ((flags & Ambiguity.AllowPointer) != 0 || context.Left == StartStmt.Left)) { return(kind); } } return(null); }
public bool AutoPrintComplexIdentOperator(Precedence precedence, Precedence context, Ambiguity flags) { // Handles #of and @`.`, including array types int argCount = _n.ArgCount; Symbol name = _n.Name; Debug.Assert((name == S.Of || name == S.Dot) && _n.IsCall); var first = _n.Args[0, null]; if (first == null) { return(false); // no args } bool needParens, needSpecialOfNotation = false; if (!CanAppearIn(precedence, context, out needParens) || needParens) { return(false); // this only happens inside $ operator, e.g. $(a.b) } if (name == S.Dot) { // The trouble with the dot is its high precedence; because of // this, arguments after a dot cannot use prefix notation as a // fallback. For example "@.(a, b(c))" cannot be printed "a.b(c)" // since that means @.(a, b)(c)". The first argument to non- // unary "." can use prefix notation safely though, e.g. // "@.(b(c), a)" can (and must) be printed "b(c).a". if (argCount > 2) { return(false); } if (HasPAttrs(first)) { return(false); } LNode afterDot = _n.Args.Last; // Unary dot is no problem: .(a) is parsed the same as .a, i.e. // the parenthesis are ignored, so we can print an expr like // @`.`(a+b) as .(a+b), but the parser counts parens on binary // dot, so in that case the argument after the dot must not be any // kind of call (except substitution) and must not have attributes, // unless it is in parens. if (argCount == 2 && !afterDot.IsParenthesizedExpr()) { if (HasPAttrs(afterDot)) { return(false); } if (afterDot.IsCall && afterDot.Name != S.Substitute) { return(false); } } else if ((flags & Ambiguity.CastRhs) != 0) { return(false); // cannot print (Foo) @`.`(x) as (Foo) .x } } else if (name == S.Of) { var ici = ICI.Default | ICI.AllowAttrs; if ((flags & Ambiguity.InDefinitionName) != 0) { ici |= ICI.NameDefinition; } if (!IsComplexIdentifier(_n, ici)) { if (IsComplexIdentifier(_n, ici | ICI.AllowAnyExprInOf)) { needSpecialOfNotation = true; } else { return(false); } } } if (name == S.Dot) { if (argCount == 1) { _out.Write('.', true); PrintExpr(first, EP.Substitute); } else { PrintExpr(first, precedence.LeftContext(context), flags & Ambiguity.TypeContext); _out.Write('.', true); PrintExpr(_n.Args[1], precedence.RightContext(context)); } } else if (_n.Name == S.Of) { // Check for special type names such as Foo? or Foo[] Symbol stk = SpecialTypeKind(_n, flags, context); if (stk != null) { if (S.IsArrayKeyword(stk)) { // We do something very strange in case of arrays of arrays: // the order of the square brackets must be reversed when // arrays are nested. For example, an array of two-dimensional // arrays of int is written int[][,], rather than int[,][] // which would be much easier to handle. var stack = InternalList <Symbol> .Empty; var innerType = _n; do { stack.Add(stk); innerType = innerType.Args[1]; } while (S.IsArrayKeyword(stk = SpecialTypeKind(innerType, flags, context) ?? GSymbol.Empty)); PrintType(innerType, EP.Primary.LeftContext(context), (flags & Ambiguity.AllowPointer)); for (int i = 0; i < stack.Count; i++) { _out.Write(stack[i].Name, true); // e.g. [] or [,] } } else { PrintType(_n.Args[1], EP.Primary.LeftContext(context), (flags & Ambiguity.AllowPointer)); _out.Write(stk == S._Pointer ? '*' : '?', true); } return(true); } PrintExpr(first, precedence.LeftContext(context)); _out.Write(needSpecialOfNotation ? "!(" : "<", true); for (int i = 1; i < argCount; i++) { if (i > 1) { WriteThenSpace(',', SpaceOpt.AfterCommaInOf); } PrintType(_n.Args[i], StartExpr, Ambiguity.InOf | Ambiguity.AllowPointer | (flags & Ambiguity.InDefinitionName)); } _out.Write(needSpecialOfNotation ? ')' : '>', true); } else { Debug.Assert(_n.Name == S.Substitute); G.Verify(AutoPrintOperator(ContinueExpr, 0)); } return(true); }