protected override void Stmt(string result, LNode input, Action <EcsNodePrinter> configure = null, Mode mode = Mode.Both) { bool exprMode = (mode & Mode.Expression) != 0; if ((mode & Mode.PrinterTest) == 0) { return; } var sb = new StringBuilder(); var printer = EcsNodePrinter.New(input, sb, " "); printer.AllowChangeParentheses = false; printer.NewlineOptions &= ~(NewlineOpt.AfterOpenBraceInNewExpr | NewlineOpt.BeforeCloseBraceInNewExpr); if (configure != null) { configure(printer); } if (exprMode) { printer.PrintExpr(); } else { printer.PrintStmt(); } AreEqual(result, sb.ToString()); }
public string Print(LNode node, IMessageSink msgs, object mode = null, string indentString = "\t", string lineSeparator = "\n") { var sb = new StringBuilder(); EcsNodePrinter.Print(node, sb, msgs, mode, indentString, lineSeparator); return(sb.ToString()); }
public void StaticMethods() { AreEqual("@this", EcsNodePrinter.PrintId(GSymbol.Get("this"), false)); AreEqual("normal_id", EcsNodePrinter.PrintId(GSymbol.Get("normal_id"), false)); AreEqual("operator+", EcsNodePrinter.PrintId(S.Add, true)); AreEqual("operator`frack!`", EcsNodePrinter.PrintId(GSymbol.Get("frack!"), true)); AreEqual(@"@@`frack!`", EcsNodePrinter.PrintSymbolLiteral(GSymbol.Get("frack!"))); AreEqual(@"@@this", EcsNodePrinter.PrintSymbolLiteral(GSymbol.Get("this"))); }
public static LNode use_symbols(LNode input, IMacroContext context) { var args_body = context.GetArgsAndBody(true); // Decode options (TODO: invent a simpler approach) string prefix = "sy_"; var inherited = new HashSet <Symbol>(); foreach (var pair in MacroContext.GetOptions(args_body.A)) { if (pair.Key.Name == "prefix" && pair.Value.IsId) { prefix = pair.Value.Name.Name; } else if (pair.Key.Name == "inherit" && pair.Value.Value is Symbol) { inherited.Add((Symbol)pair.Value.Value); } else if (pair.Key.Name == "inherit" && (pair.Value.Calls(S.Braces) || pair.Value.Calls(S.Tuple)) && pair.Value.Args.All(n => n.Value is Symbol)) { foreach (var arg in pair.Value.Args) { inherited.Add((Symbol)arg.Value); } } else { context.Sink.Write(Severity.Warning, pair.Value, "Unrecognized parameter. Expected prefix:id or inherit:{@@A; @@B; ...})"); } } // Replace all symbols while collecting a list of them var symbols = new Dictionary <Symbol, LNode>(); VList <LNode> output = args_body.B.SmartSelect(stmt => stmt.ReplaceRecursive(n => { var sym = n.Value as Symbol; if (n.IsLiteral && sym != null) { return(symbols[sym] = LNode.Id(prefix + EcsNodePrinter.SanitizeIdentifier(sym.Name))); } return(null); })); // Return updated code with variable declaration at the top for all non-inherit symbols used. var _Symbol = F.Id("Symbol"); var vars = (from sym in symbols where !inherited.Contains(sym.Key) select F.Call(S.Assign, sym.Value, F.Call(S.Cast, F.Literal(sym.Key.Name), _Symbol))).ToList(); if (vars.Count > 0) { output.Insert(0, F.Call(S.Var, ListExt.Single(_Symbol).Concat(vars)) .WithAttrs(input.Attrs.Add(F.Id(S.Static)).Add(F.Id(S.Readonly)))); } return(F.Call(S.Splice, output)); }
void CheckIsComplexIdentifier(bool? result, LNode expr) { var np = new EcsNodePrinter(expr, null); _testNum++; var isCI = EcsValidators.IsComplexIdentifier(expr); if (result == null && !isCI) return; else if (result == isCI) return; Assert.Fail(string.Format( "IsComplexIdentifier: fail on test #{0} '{1}'. Expected {2}, got {3}", _testNum, expr.ToString(), result, isCI)); }
static LNode GetForwardingTarget(LNode fwd, LNode methodName) { if (fwd.Calls(S.Forward, 1)) { LNode target = fwd.Args[0]; if (target.Calls(S.Dot, 2) && (target.Args[1].IsIdNamed(_hash) || target.Args[1].IsIdNamed(__))) { return(target.WithArgChanged(1, target.Args[1].WithName( EcsNodePrinter.KeyNameComponentOf(methodName)))); } return(target); } else { return(null); } }
void CheckIsComplexIdentifier(bool?result, LNode expr) { var np = new EcsNodePrinter(expr, null); _testNum++; var isCI = EcsValidators.IsComplexIdentifier(expr); if (result == null && !isCI) { return; } else if (result == isCI) { return; } Assert.Fail(string.Format( "IsComplexIdentifier: fail on test #{0} '{1}'. Expected {2}, got {3}", _testNum, expr.ToString(), result, isCI)); }
/// <summary>Expresses an EC# token as a string.</summary> /// <remarks>Note that some Tokens do not contain enough information to /// reconstruct a useful token string, e.g. comment tokens do not store the /// comment but merely contain the location of the comment in the source code. /// For performance reasons, a <see cref="Token"/> does not have a reference /// to its source file, so this method cannot return the original string. /// <para/> /// The results are undefined if the token was not produced by <see cref="EcsLexer"/>. /// </remarks> public static string ToString(Token t) { StringBuilder sb = new StringBuilder(); if (t.Kind == TokenKind.Operator || t.Kind == TokenKind.Assignment || t.Kind == TokenKind.Dot) { if (t.Type() == TT.BQString) { return(EcsNodePrinter.PrintString((t.Value ?? "").ToString(), '`', false)); } string value = (t.Value ?? "(null)").ToString(); return(value); } switch (t.Type()) { case TT.EOF: return("/*EOF*/"); case TT.Spaces: return(" "); case TT.Newline: return("\n"); case TT.SLComment: return("//\n"); case TT.MLComment: return("/**/"); case TT.Shebang: return("#!" + (t.Value ?? "").ToString() + "\n"); case TT.Id: case TT.ContextualKeyword: return(EcsNodePrinter.PrintId(t.Value as Symbol ?? GSymbol.Empty)); case TT.@base: return("base"); case TT.@this: return("this"); case TT.Number: case TT.String: case TT.SQString: case TT.Symbol: case TT.OtherLit: return(EcsNodePrinter.PrintLiteral(t.Value, t.Style)); case TT.Comma: return(","); case TT.Semicolon: return(";"); case TT.LParen: return("("); case TT.RParen: return(")"); case TT.LBrack: return("["); case TT.RBrack: return("]"); case TT.LBrace: return("{"); case TT.RBrace: return("}"); case TT.AttrKeyword: string value = (t.Value ?? "(null)").ToString(); return(value); case TT.TypeKeyword: Symbol valueSym = (t.Value as Symbol) ?? GSymbol.Empty; string result; if (EcsNodePrinter.TypeKeywords.TryGetValue(valueSym, out result)) { return(result); } else { Debug.Fail("Unexpected value for " + t.Type()); return((t.Value ?? "(null)").ToString()); } case TT.@break: return("break"); case TT.@case: return("case"); case TT.@checked: return("checked"); case TT.@class: return("class"); case TT.@continue: return("continue"); case TT.@default: return("default"); case TT.@delegate: return("delegate"); case TT.@do: return("do"); case TT.@enum: return("enum"); case TT.@event: return("event"); case TT.@fixed: return("fixed"); case TT.@for: return("for"); case TT.@foreach: return("foreach"); case TT.@goto: return("goto"); case TT.@if: return("if"); case TT.@interface: return("interface"); case TT.@lock: return("lock"); case TT.@namespace: return("namespace"); case TT.@return: return("return"); case TT.@struct: return("struct"); case TT.@switch: return("switch"); case TT.@throw: return("throw"); case TT.@try: return("try"); case TT.@unchecked: return("unchecked"); case TT.@using: return("using"); case TT.@while: return("while"); case TT.@operator: return("operator"); case TT.@sizeof: return("sizeof"); case TT.@typeof: return("typeof"); case TT.@else: return("else"); case TT.@catch: return("catch"); case TT.@finally: return("finally"); case TT.@in: return("in"); case TT.@as: return("as"); case TT.@is: return("is"); case TT.@new: return("new"); case TT.@out: return("out"); case TT.@stackalloc: return("stackalloc"); case TT.PPif: return("#if"); case TT.PPelse: return("#else"); case TT.PPelif: return("#elif"); case TT.PPendif: return("#endif"); case TT.PPdefine: return("#define"); case TT.PPundef: return("#undef"); case TT.PPwarning: return("#warning" + t.Value); case TT.PPerror: return("#error" + t.Value); case TT.PPnote: return("#note" + t.Value); case TT.PPline: return("#line"); case TT.PPregion: return("#region" + t.Value); case TT.PPendregion: return("#endregion"); case TT.PPpragma: return("#pragma"); case TT.PPignored: return((t.Value ?? "").ToString()); default: return(string.Format("@`unknown token 0x{0:X4}`", t.TypeInt)); } }
static VList <LNode> AddLineDirectives(VList <LNode> nodes, bool stmtContext, ref int sourceLine_) { int sourceLine = sourceLine_; nodes = nodes.SmartSelect(node => { if (stmtContext && sourceLine > 0 && node.AttrNamed(S.TriviaAppendStatement) == null) { sourceLine++; // printer will print a newline by default } int explicitNewlines = node.Attrs.Count(n => n.IsIdNamed(S.TriviaNewline)); sourceLine += explicitNewlines; // Generate line directive if necessary; to avoid excess // clutter, don't consider emit #line directives within an expression. string lineDirective = null; if (stmtContext || explicitNewlines != 0) { if (node.Range.Source is EmptySourceFile || string.IsNullOrEmpty(node.Range.Source.FileName)) { // synthetic code: no source location if (sourceLine != -1) { sourceLine = -1; lineDirective = "#line default"; } } else { var start = node.Range.Start; if (sourceLine != start.Line) { sourceLine = start.Line; lineDirective = "#line " + start.Line + " " + EcsNodePrinter.PrintString(start.FileName, '"'); } } } int sourceLineWas = sourceLine; if (node.Name.Name.StartsWith("#") && node.ArgCount > 1) { // For some special calls like #if, #while, and #doWhile, // printer might print newlines in places we don't know about, // so erase our knowledge of what the current line is. if (sourceLine > 0) { sourceLine = int.MinValue; } } // Process children node = node.WithAttrs(AddLineDirectives(node.Attrs, false, ref sourceLine)); if (node.IsCall) { node = node.WithArgs(AddLineDirectives(node.Args, node.Calls(S.Braces), ref sourceLine)); } if (sourceLine > 0) { sourceLine += node.GetTrailingTrivia().Count(n => n.IsIdNamed(S.TriviaNewline)); } // Finally, add a line directive if requested. if (lineDirective != null) { var trivia = F.Trivia(S.TriviaCsPPRawText, lineDirective); if (!node.Attrs.Contains(trivia)) { // Trivia tends not to be included in the source range so adding #line // before trivia is generally wrong, while adding #line after attributes // tends to be wrong too. Sigh. Search for a good location to insert... // unless inserting #line default which we can just put at the beginning int insertIndex = 0; if (sourceLineWas > 0) { insertIndex = node.Attrs.IndexWhere(n => n.Range.Start.Line == sourceLineWas && n.Range.Source == node.Range.Source); if (insertIndex == -1) { insertIndex = node.Attrs.Count; } } node = node.WithAttrs(node.Attrs.Insert(insertIndex, trivia)); } } return(node); }); sourceLine_ = sourceLine; return(nodes); }
private static bool DetectSetOrCreateMember(LNode arg, out Symbol relevantAttribute, out Symbol fieldName, out Symbol paramName, out LNode newArg, out LNode propOrFieldDecl) { relevantAttribute = null; fieldName = null; paramName = null; newArg = null; propOrFieldDecl = null; LNode _, type, name, defaultValue, propArgs; if (EcsValidators.IsPropertyDefinition(arg, out type, out name, out propArgs, out _, out defaultValue) && propArgs.ArgCount == 0) { // #property(Type, Name<T>, {...}) relevantAttribute = S.Property; fieldName = EcsNodePrinter.KeyNameComponentOf(name); paramName = ChooseArgName(fieldName); if (defaultValue != null) // initializer is Args[4] { newArg = LNode.Call(S.Var, LNode.List(type, F.Assign(paramName, defaultValue)), arg); propOrFieldDecl = arg.WithArgs(arg.Args.Initial(4)); } else { newArg = LNode.Call(S.Var, LNode.List(type, F.Id(paramName)), arg); propOrFieldDecl = arg; } DSOCM_DistributeAttributes(arg.Attrs, ref newArg, ref propOrFieldDecl); return(true); } else if (IsVar(arg, out type, out paramName, out defaultValue)) { int a_i = 0; foreach (var attr in arg.Attrs) { if (attr.IsId) { var a = attr.Name; if (a == _set || FieldCreationAttributes.Contains(a)) { relevantAttribute = a; fieldName = paramName; paramName = ChooseArgName(fieldName); if (a == _set) { newArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.Without(attr)); } else { // in case of something like "[A] public params T arg = value", // assume that "= value" represents a default value, not a field // initializer. Most attributes stay on the argument. newArg = arg.WithArgChanged(1, defaultValue != null ? F.Assign(paramName, defaultValue) : F.Id(paramName)); propOrFieldDecl = LNode.Call(S.Var, LNode.List(type, F.Id(fieldName)), arg); DSOCM_DistributeAttributes(arg.Attrs, ref newArg, ref propOrFieldDecl); } break; } } a_i++; } return(newArg != null); } return(false); }
public static LNode DollarSignVariable(LNode node, IMacroContext context) { LNode id; if (node.ArgCount == 1 && (id = node.Args[0]).IsId && !id.HasPAttrs()) { object value; if (context.ScopedProperties.TryGetValue("$" + id.Name.Name, out value)) { if (value is LNode) { return(((LNode)value).WithRange(id.Range)); } else { context.Sink.Warning(id, "The specified scoped property is not a syntax tree. " + "Use `#getScopedProperty({0})` to insert it as a literal.", EcsNodePrinter.PrintId(id.Name)); } } else { context.Sink.Error(id, "There is no macro property in scope named `{0}`", id.Name); } } return(null); }
/// <summary>Expresses an EC# token as a string.</summary> /// <remarks>Note that some Tokens do not contain enough information to /// reconstruct a useful token string, e.g. comment tokens do not store the /// comment but merely contain the location of the comment in the source code. /// For performance reasons, a <see cref="Token"/> does not have a reference /// to its source file, so this method cannot return the original string. /// <para/> /// The results are undefined if the token was not produced by <see cref="EcsLexer"/>. /// </remarks> public static string ToString(Token t, ICharSource sourceCode) { if (sourceCode != null && t.EndIndex <= sourceCode.Count) { return(sourceCode.Slice(t.StartIndex, t.Length).ToString()); } StringBuilder sb = new StringBuilder(); if (t.Kind == TokenKind.Operator || t.Kind == TokenKind.Assignment || t.Kind == TokenKind.Dot) { if (t.Type() == TT.BQString) { return(EcsNodePrinter.PrintString((t.Value ?? "").ToString(), '`', false)); } string value = (t.Value ?? "(null)").ToString(); return(value); } switch (t.Type()) { case TT.EOF: return("/*EOF*/"); case TT.Spaces: return(" "); case TT.Newline: return("\n"); case TT.SLComment: return("//\n"); case TT.MLComment: return("/**/"); case TT.Shebang: return("#!" + (t.Value ?? "").ToString() + "\n"); case TT.Id: case TT.ContextualKeyword: case TT.LinqKeyword: var mode = (t.Style & NodeStyle.Operator) != 0 ? EcsNodePrinter.IdPrintMode.Operator : (t.Style & NodeStyle.VerbatimId) != 0 ? EcsNodePrinter.IdPrintMode.Verbatim : EcsNodePrinter.IdPrintMode.Normal; return(EcsNodePrinter.PrintId(t.Value as Symbol ?? GSymbol.Empty, mode)); case TT.Base: return("base"); case TT.This: return("this"); case TT.Literal: return(EcsNodePrinter.PrintLiteral(t.Value, t.Style)); case TT.Comma: return(","); case TT.Semicolon: return(";"); case TT.LParen: return("("); case TT.RParen: return(")"); case TT.LBrack: return("["); case TT.RBrack: return("]"); case TT.LBrace: return("{"); case TT.RBrace: return("}"); case TT.AttrKeyword: string value = (t.Value ?? "(null)").ToString(); return(value); case TT.TypeKeyword: Symbol valueSym = (t.Value as Symbol) ?? GSymbol.Empty; string result; if (EcsFacts.TypeKeywords.TryGetValue(valueSym, out result)) { return(result); } else { Debug.Fail("Unexpected value for " + t.Type()); return((t.Value ?? "(null)").ToString()); } case TT.CheckedOrUnchecked: Debug.Assert(LNode.IsSpecialName((Symbol)t.Value)); return(((Symbol)t.Value).Name.Substring(1)); case TT.Break: return("break"); case TT.Case: return("case"); case TT.Class: return("class"); case TT.Continue: return("continue"); case TT.Default: return("default"); case TT.Delegate: return("delegate"); case TT.Do: return("do"); case TT.Enum: return("enum"); case TT.Event: return("event"); case TT.Fixed: return("fixed"); case TT.For: return("for"); case TT.Foreach: return("foreach"); case TT.Goto: return("goto"); case TT.If: return("if"); case TT.Interface: return("interface"); case TT.Lock: return("lock"); case TT.Namespace: return("namespace"); case TT.Return: return("return"); case TT.Struct: return("struct"); case TT.Switch: return("switch"); case TT.Throw: return("throw"); case TT.Try: return("try"); case TT.Using: return("using"); case TT.While: return("while"); case TT.Operator: return("operator"); case TT.Sizeof: return("sizeof"); case TT.Typeof: return("typeof"); case TT.Else: return("else"); case TT.Catch: return("catch"); case TT.Finally: return("finally"); case TT.In: return("in"); case TT.As: return("as"); case TT.Is: return("is"); case TT.New: return("new"); case TT.Out: return("out"); case TT.Stackalloc: return("stackalloc"); case TT.PPif: return("#if"); case TT.PPelse: return("#else"); case TT.PPelif: return("#elif"); case TT.PPendif: return("#endif"); case TT.PPdefine: return("#define"); case TT.PPundef: return("#undef"); case TT.PPwarning: return("#warning" + t.Value); case TT.PPerror: return("#error" + t.Value); case TT.PPnote: return("#note" + t.Value); case TT.PPline: return("#line"); case TT.PPregion: return("#region" + t.Value); case TT.PPendregion: return("#endregion"); case TT.PPpragma: return("#pragma"); case TT.PPignored: return((t.Value ?? "").ToString()); default: return(string.Format("@`unknown token 0x{0:X4}`", t.TypeInt)); } }
public static LNode SetOrCreateMember(LNode fn, IMessageSink sink) { // Expecting #fn(Type, Name, #(args), {body}) if (fn.ArgCount < 3 || !fn.Args[2].Calls(S.AltList)) { return(null); } var args = fn.Args[2].Args; LNode body = null; VList <LNode> propOrFieldDecls = VList <LNode> .Empty; VList <LNode> setStmts = VList <LNode> .Empty; for (int i = 0; i < args.Count; i++) { var arg = args[i]; Symbol a = S.Property; Symbol fieldName = null; Symbol paramName = null; LNode plainArg = null; LNode propOrFieldDecl = null; if (arg.CallsMin(S.Property, 4)) { // #property(Type, Name<T>, {...}) var name = arg.Args[1]; fieldName = EcsNodePrinter.KeyNameComponentOf(name); paramName = ChooseArgName(fieldName); if (arg.ArgCount == 5) // initializer is Args[4] { plainArg = F.Var(arg.Args[0], F.Call(S.Assign, F.Id(paramName), arg.Args[4])); propOrFieldDecl = arg.WithArgs(arg.Args.First(4)); } else { plainArg = F.Var(arg.Args[0], paramName); propOrFieldDecl = arg; } } else { LNode type, defaultValue; if (IsVar(arg, out type, out paramName, out defaultValue)) { int a_i = 0; foreach (var attr in arg.Attrs) { if (attr.IsId) { a = attr.Name; if (a == _set || a == S.Public || a == S.Internal || a == S.Protected || a == S.Private || a == S.ProtectedIn || a == S.Static || a == S.Partial) { fieldName = paramName; paramName = ChooseArgName(fieldName); if (a == _set) { plainArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.RemoveAt(a_i)); } else { // in case of something like "[A] public params T arg = value", // assume that "= value" represents a default value, not a field // initializer, that [A] belongs on the field, except `params` // which stays on the argument. plainArg = F.Var(type, paramName, defaultValue); propOrFieldDecl = arg; if (arg.Args[1].Calls(S.Assign, 2)) { propOrFieldDecl = arg.WithArgChanged(1, arg.Args[1].Args[0]); } int i_params = arg.Attrs.IndexWithName(S.Params); if (i_params > -1) { plainArg = plainArg.PlusAttr(arg.Attrs[i_params]); propOrFieldDecl = propOrFieldDecl.WithAttrs(propOrFieldDecl.Attrs.RemoveAt(i_params)); } } break; } } a_i++; } } } if (plainArg != null) { if (body == null) { if (fn.ArgCount < 4 || !fn.Args[3].Calls(S.Braces)) { return(Reject(sink, arg, Localize.Localized("'{0}': to set or create a field or property, the method must have a body in braces {{}}.", a))); } body = fn.Args[3]; } args[i] = plainArg; LNode assignment; if (fieldName == paramName) { assignment = F.Call(S.Assign, F.Dot(F.@this, F.Id(fieldName)), F.Id(paramName)); } else { assignment = F.Call(S.Assign, F.Id(fieldName), F.Id(paramName)); } setStmts.Add(assignment); if (propOrFieldDecl != null) { propOrFieldDecls.Add(propOrFieldDecl); } } } if (body != null) // if this macro has been used... { var parts = fn.Args; parts[2] = parts[2].WithArgs(args); parts[3] = body.WithArgs(body.Args.InsertRange(0, setStmts)); fn = fn.WithArgs(parts); if (propOrFieldDecls.IsEmpty) { return(fn); } else { propOrFieldDecls.Add(fn); return(F.Call(S.Splice, propOrFieldDecls)); } } return(null); }
private static bool DetectSetOrCreateMember(LNode arg, out Symbol relevantAttribute, out Symbol fieldName, out Symbol paramName, out LNode plainArg, out LNode propOrFieldDecl) { relevantAttribute = null; fieldName = null; paramName = null; plainArg = null; propOrFieldDecl = null; LNode _, type, name, defaultValue, propArgs; if (EcsValidators.IsPropertyDefinition(arg, out type, out name, out propArgs, out _, out defaultValue) && propArgs.ArgCount == 0) { // #property(Type, Name<T>, {...}) relevantAttribute = S.Property; fieldName = EcsNodePrinter.KeyNameComponentOf(name); paramName = ChooseArgName(fieldName); if (defaultValue != null) // initializer is Args[4] { plainArg = F.Var(type, paramName, defaultValue); propOrFieldDecl = arg.WithArgs(arg.Args.First(4)); } else { plainArg = F.Var(type, paramName); propOrFieldDecl = arg; } return(true); } else if (IsVar(arg, out type, out paramName, out defaultValue)) { int a_i = 0; foreach (var attr in arg.Attrs) { if (attr.IsId) { var a = attr.Name; if (a == _set || a == S.Public || a == S.Internal || a == S.Protected || a == S.Private || a == S.ProtectedIn || a == S.Static || a == S.Partial) { relevantAttribute = a; fieldName = paramName; paramName = ChooseArgName(fieldName); if (a == _set) { plainArg = F.Var(type, paramName, defaultValue).WithAttrs(arg.Attrs.Without(attr)); } else { // in case of something like "[A] public params T arg = value", // assume that "= value" represents a default value, not a field // initializer, that [A] belongs on the field, except `params` // which stays on the argument. plainArg = F.Var(type, paramName, defaultValue); propOrFieldDecl = arg; if (arg.Args[1].Calls(S.Assign, 2)) { propOrFieldDecl = arg.WithArgChanged(1, arg.Args[1].Args[0]); } int i_params = arg.Attrs.IndexWithName(S.Params); if (i_params > -1) { plainArg = plainArg.PlusAttr(arg.Attrs[i_params]); propOrFieldDecl = propOrFieldDecl.WithAttrs(propOrFieldDecl.Attrs.RemoveAt(i_params)); } } break; } } a_i++; } return(plainArg != null); } return(false); }