public IType VisitArrayLiteral(ArrayLiteral arrayLiteral) { var firstElementType = GetExpressionType(arrayLiteral.Elements[0]); if (firstElementType == null) { return(null); } if (arrayLiteral.Length == 1) { return(new ArrayType(firstElementType, 1)); } for (var i = 1; i < arrayLiteral.Length; i++) { var element = arrayLiteral.Elements[i]; var elementType = GetExpressionType(element); if (elementType == null || elementType.IsSame(firstElementType)) { continue; } _context.Error( element.Span, "type mismatch in array literal; " + $"expected \"{firstElementType}\", but found \"{elementType}\""); return(null); } return(new ArrayType(firstElementType, arrayLiteral.Length)); }
private void ProcessArguments(ArrayLiteral arguments) { var processedArguments = CommandLineArgumentsConverter.ArrayLiteralToListOfArguments(m_context.StringTable, arguments); foreach (var argument in processedArguments) { // Not every arguments are valid. // Cmd.option function will return invalid argument if the argument value is undefined. if (!argument.IsDefined) { continue; } // It could be just a switch argument, i.e., argument name without a value if (!argument.Value.IsDefined) { AddOption(argument.Name, (string)null); continue; } switch (argument.Value.Type) { case CommandLineValueType.ScalarArgument: AddScalarArgument(argument.Name, argument.Value.ScalarArgument); break; case CommandLineValueType.ScalarArgumentArray: AddScalarArguments(argument.Name, argument.Value.ScalarArguments); break; } } }
public ArrayLiteral ParseArrayLiteral() { var al = new ArrayLiteral { Token = Next() }; Match(TokenType.LeftBracket); while (Next().IsNot(TokenType.RightBracket)) { al.Expressions.Add(ParseAssignmentExpression()); if (Next().Is(TokenType.Derive)) { if (al.Expressions.Count != 1) { throw Error("Invalid array definition", al.Token); } Match(TokenType.Derive); al.Expressions.Add(ParseAssignmentExpression()); al.IsRange = true; break; } if (Next().Is(TokenType.Comma)) { Match(TokenType.Comma); } } Match(TokenType.RightBracket); return(al); }
private static EvaluationResult ForEach(Context context, OrderedSet receiver, EvaluationResult arg, EvaluationStackFrame captures) { var cls = Converter.ExpectClosure(arg); var result = new EvaluationResult[receiver.Count]; int paramsCount = cls.Function.Params; using (var frame = EvaluationStackFrame.Create(cls.Function, captures.Frame)) { int i = 0; foreach (var item in receiver) { frame.TrySetArguments(paramsCount, item); result[i] = context.InvokeClosure(cls, frame); if (result[i].IsErrorValue) { return(EvaluationResult.Error); } ++i; } return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, context.TopStack.InvocationLocation, context.TopStack.Path))); } }
public virtual void Visit(ArrayLiteral node) { if (node != null) { AcceptChildren(node); } }
private static EvaluationResult ForEach(Context context, OrderedMap receiver, EvaluationResult arg, EvaluationStackFrame captures) { var cls = Converter.ExpectClosure(arg); var result = new EvaluationResult[receiver.Count]; int paramsCount = cls.Function.Params; // One frame can be reused for multiple calls of a callback function using (var frame = EvaluationStackFrame.Create(cls.Function, captures.Frame)) { var entry = context.TopStack; int i = 0; foreach (var kvp in receiver) { var kvpAsArray = ArrayLiteral.CreateWithoutCopy(new EvaluationResult[] { kvp.Key, kvp.Value }, entry.InvocationLocation, entry.Path); frame.TrySetArguments(paramsCount, EvaluationResult.Create(kvpAsArray)); result[i] = context.InvokeClosure(cls, frame); if (result[i].IsErrorValue) { return(EvaluationResult.Error); } ++i; } return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, entry.InvocationLocation, entry.Path))); } }
public void Visit(ArrayLiteral node) { if (node != null) { DoesRequire = true; } }
private static EvaluationResult SealDirectoryHelper(Context context, ModuleLiteral env, EvaluationStackFrame args, SealDirectoryKind sealDirectoryKind) { AbsolutePath path = Args.AsPath(args, 0, false); ArrayLiteral contents = Args.AsArrayLiteral(args, 1); var tags = Args.AsStringArrayOptional(args, 2); var description = Args.AsStringOptional(args, 3); // Only do scrub for fully seal directory var scrub = sealDirectoryKind.IsFull() ? Args.AsBoolOptional(args, 4) : false; var fileContents = new FileArtifact[contents.Length]; for (int i = 0; i < contents.Length; ++i) { fileContents[i] = Converter.ExpectFile(contents[i], strict: false, context: new ConversionContext(pos: i, objectCtx: contents)); } var sortedFileContents = SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> .CloneAndSort(fileContents, OrdinalFileArtifactComparer.Instance); DirectoryArtifact sealedDirectoryArtifact; if (!context.GetPipConstructionHelper().TrySealDirectory(path, sortedFileContents, sealDirectoryKind, tags, description, null, out sealedDirectoryArtifact, scrub)) { // Error has been logged return(EvaluationResult.Error); } var result = new StaticDirectory(sealedDirectoryArtifact, sealDirectoryKind, sortedFileContents.WithCompatibleComparer(OrdinalPathOnlyFileArtifactComparer.Instance)); return(new EvaluationResult(result)); }
private static EvaluationResult ToArray(Context context, string receiver, EvaluationStackFrame captures) { var elems = string.IsNullOrEmpty(receiver) ? CollectionUtilities.EmptyArray <EvaluationResult>() : receiver.ToCharArray().SelectArray(ch => EvaluationResult.Create(ch.ToString())); return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(elems, context.TopStack.InvocationLocation, context.TopStack.Path))); }
private IExpression ParseArrayLiteral() { var array = new ArrayLiteral { Token = CurrentToken, Elements = ParseExpressionList(Token.Rbracket) }; return(array); }
private Expression ParseArrayLiteral() { var array = new ArrayLiteral(); array.Token = this._curToken; array.Elements = this.ParseExpressionList(TokenType.RBRACKET); return(array); }
public void Visit(ArrayLiteral node) { if (node != null) { // if this is multi-line output, we're going to want to run some checks first // to see if we want to put the array all on one line or put elements on separate lines. var multiLine = false; if (m_settings.OutputMode == OutputMode.MultipleLines) { if (node.Elements.Count > 5 || NotJustPrimitives(node.Elements)) { multiLine = true; } } m_writer.Write('['); if (node.Elements != null) { if (multiLine) { // multiline -- let's pretty it up a bit m_settings.Indent(); try { var first = true; foreach (var element in node.Elements) { if (first) { first = false; } else { m_writer.Write(','); } NewLine(); element.Accept(this); } } finally { m_settings.Unindent(); } NewLine(); } else { // not multiline, so just run through all the items node.Elements.Accept(this); } } m_writer.Write(']'); } }
private IExpression ParseArrayLiteral() { var arr = new ArrayLiteral { Token = this.currentToken }; arr.Elements = ParseExpressionList(TokenType.RBracket); return(arr); }
private IExpression ParseArrayLiteral() { var array = new ArrayLiteral { Token = curToken }; array.Elements = ParseExpressionList(TokenType.RBracket); return(array); }
public virtual void Visit(ArrayLiteral node) { if (node != null) { foreach (var childNode in node.Children) { childNode.Accept(this); } } }
public virtual void Visit(ArrayLiteral node) { if (node != null) { if (node.Elements != null) { node.Elements.Accept(this); } } }
private static EvaluationResult GetContent(Context context, StaticDirectory receiver, EvaluationStackFrame captures) { GetProvenance(context, out AbsolutePath path, out LineInfo lineInfo); // Can't use content directly, because there is no IS-A relationship between collection // of value types and collection of objects. So need to box everything any way. var content = receiver.Contents.SelectArray(x => EvaluationResult.Create(x)); return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(content, lineInfo, path))); }
private static ArrayLiteral DeepCloneArray(ArrayLiteral array) { var results = new EvaluationResult[array.Count]; for (int i = 0; i < array.Count; i++) { results[i] = DeepCloneValue(array[i]); } return(ArrayLiteral.CreateWithoutCopy(results, array.Location, array.Path)); }
private IExpression ParseArrayLiteral() { var array = new ArrayLiteral { Token = _currentToken }; array.Elements = ParseExpressionList(TokenType.RBRACKET); return(array); }
public virtual object Walk(ArrayLiteral node) { if (Enter(node)) { foreach (var exp in node.Expressions) { exp.Accept(this); } } Exit(node); return(null); }
private static bool TryHashArray(ArrayLiteral array, HashingHelper helper) { helper.Add(array.Length); foreach (var item in array.Values) { if (!TryHashValue(item, helper)) { return(false); } } return(true); }
public bool VisitArrayLiteral(ArrayLiteral arrayLiteral) { var isValid = arrayLiteral.Elements.Aggregate( true, (current, element) => current & IsExpressionValid(element)); if (!isValid) { return(false); } return(Typer.GetExpressionType(_context, _environment, arrayLiteral) != null); }
private ArgumentValue[] ConvertArrayOfScalarArguments(ArrayLiteral scalarArguments) { Contract.Requires(scalarArguments != null); var results = new ArgumentValue[scalarArguments.Length]; for (int i = 0; i < scalarArguments.Length; ++i) { results[i] = ConvertScalarArgument(new PropertyValue(SymbolAtom.Invalid, scalarArguments, scalarArguments[i])); } return(results); }
private static EvaluationResult ToPathAtoms(Context context, RelativePath receiver, EvaluationStackFrame captures) { PathAtom[] atoms = receiver.GetAtoms(); EvaluationResult[] result = new EvaluationResult[atoms.Length]; for (int i = 0; i < atoms.Length; i++) { result[i] = EvaluationResult.Create(atoms[i]); } var entry = context.TopStack; return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(result, entry.InvocationLocation, entry.Path))); }
private static IEnumerable <object> GetDifferentListRepresenations <T>(IReadOnlyList <T> array) { var objectArray = new object[array.Count]; for (var i = 0; i < objectArray.Length; i++) { objectArray[i] = array[i]; } return(new List <object> { array, ArrayLiteral.CreateWithoutCopy(objectArray.Select(e => EvaluationResult.Create(e)).ToArray(), default(LineInfo), AbsolutePath.Invalid) }); }
private EvaluationResult AddIf(Context context, ModuleLiteral env, EvaluationStackFrame args) { var condition = Args.AsBool(args, 0); if (!condition) { // Return empty Array var entry = context.TopStack; return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(new EvaluationResult[0], entry.InvocationLocation, entry.Path))); } var items = Args.AsArrayLiteral(args, 1); return(EvaluationResult.Create(items)); }
public void TestAmbientEnvironmentUses() { const string Spec = @" // Any change will break Office. const newLine = Environment.newLine(); const hasVariable = Environment.hasVariable(""ProgramFiles(x86)""); const stringValue = Environment.getStringValue(""UserName""); const pathValue = Environment.getPathValue(""ProgramFiles(x86)""); const fileValue = Environment.getFileValue(""ProgramFiles(x86)""); // yes, I know it's not a file. const pathValues = Environment.getPathValues(""Path"", "";""); "; var results = EvaluateExpressionsWithNoErrors( Spec, "newLine", "hasVariable", "stringValue", "pathValue", "fileValue", "pathValues"); string programFileX86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)"); string userName = Environment.GetEnvironmentVariable("UserName"); string path = Environment.GetEnvironmentVariable("Path"); Assert.Equal(Environment.NewLine, results["newLine"]); Assert.Equal(programFileX86 != null, results["hasVariable"]); Assert.Equal(userName != null ? (object)userName : UndefinedValue.Instance, results["stringValue"]); Assert.Equal( programFileX86 != null ? (object)CreateAbsolutePath(programFileX86).Value : UndefinedValue.Instance, results["pathValue"]); Assert.Equal( programFileX86 != null ? (object)CreateSourceFile(programFileX86).Value : UndefinedValue.Instance, results["fileValue"]); if (path != null) { var paths = ArrayLiteral.CreateWithoutCopy( path.Split(';').Select(p => EvaluationResult.Create(CreateAbsolutePath(p))).ToArray(), default(LineInfo), AbsolutePath.Invalid); Assert.IsAssignableFrom <ArrayLiteral>(results["pathValues"]); CheckUnorderedArray <AbsolutePath>(paths, results["pathValues"]); } else { Assert.Equal(UndefinedValue.Instance, results["pathValues"]); } }
private EvaluationResult GlobFolders(Context context, ModuleLiteral env, EvaluationStackFrame args) { var dirPath = Args.AsPath(args, 0, false); var pathTable = context.FrontEndContext.PathTable; var path = dirPath.ToString(pathTable); // TODO:ST: add different set of function that will distinguish optional from required arguments! string pattern = Args.AsStringOptional(args, 1) ?? "*"; bool recursive = Args.AsBoolOptional(args, 2); var resultPaths = EnumerateFilesOrDirectories(context, path, pattern, directoriesToSkipRecursively: 0, isRecursive: recursive, enumerateDirectory: true); var entry = context.TopStack; return(EvaluationResult.Create(ArrayLiteral.CreateWithoutCopy(resultPaths, entry.InvocationLocation, entry.Path))); }
private static ObjectLiteral GetQualifierSpaceValue(EvaluationContext context, QualifierSpaceId qualifierSpaceId) { Contract.Requires(context != null); Contract.Requires(context.FrontEndContext.QualifierTable.IsValidQualifierSpaceId(qualifierSpaceId)); var qualifierSpace = context.FrontEndContext.QualifierTable.GetQualifierSpace(qualifierSpaceId); var bindings = new List <Binding>(qualifierSpace.Keys.Count); foreach (var kvp in qualifierSpace.AsDictionary) { var values = ArrayLiteral.CreateWithoutCopy(kvp.Value.Select(s => EvaluationResult.Create(s.ToString(context.StringTable))).ToArray(), default(LineInfo), AbsolutePath.Invalid); bindings.Add(new Binding(kvp.Key, values, default(LineInfo))); } return(ObjectLiteral.Create(bindings, default(LineInfo), AbsolutePath.Invalid)); }
private IEnumerable <Argument> ConvertArrayOfArguments(ArrayLiteral literal) { Contract.Requires(literal != null); for (int i = 0; i < literal.Length; ++i) { var l = literal[i]; if (!l.IsUndefined) { var x = ConvertArgument(l, i, literal); if (x.IsDefined) { yield return(x); } } } }
public override object Walk(ArrayLiteral node) { var array = new BikeArray(); if (node.IsRange) { var from = node.Expressions[0].Accept(this); var fromValue = ((BikeNumber)from).Value; if ((fromValue % 1) != 0) { throw ErrorFactory.CreateTypeError("Array range initializer must start with a whole number"); } var end = node.Expressions[1].Accept(this); var endValue = ((BikeNumber)end).Value; if ((endValue % 1) != 0) { throw ErrorFactory.CreateTypeError("Array range initializer must end with a whole number"); } if (fromValue <= endValue) { int index = 0; for (var i = (int)fromValue; i < (int)endValue; i++) { array.Define((index++).ToString(), new BikeNumber(i)); } } else { int index = 0; for (var i = (int)fromValue; i > (int)endValue; i--) { array.Define((index++).ToString(), new BikeNumber(i)); } } return(array); } for (int i = 0; i < node.Expressions.Count; i++) { var value = node.Expressions[i].Accept(this); array.Define(i.ToString(), value); } return(array); }
public ArrayLiteral ParseArrayLiteral() { var al = new ArrayLiteral {Token = Next()}; Match(TokenType.LeftBracket); while (Next().IsNot(TokenType.RightBracket)) { al.Expressions.Add(ParseAssignmentExpression()); if (Next().Is(TokenType.Derive)) { if (al.Expressions.Count != 1) throw Error("Invalid array definition", al.Token); Match(TokenType.Derive); al.Expressions.Add(ParseAssignmentExpression()); al.IsRange = true; break; } if (Next().Is(TokenType.Comma)) Match(TokenType.Comma); } Match(TokenType.RightBracket); return al; }
public virtual bool Enter(ArrayLiteral node) { return true; }
// $ANTLR start "arrayLiteral" // JavaScript.g:340:1: arrayLiteral : '[' ( LT )* ( elision ( ',' elision )* ( ',' )? )? ']' ; public JavaScriptParser.arrayLiteral_return arrayLiteral() // throws RecognitionException [1] { JavaScriptParser.arrayLiteral_return retval = new JavaScriptParser.arrayLiteral_return(); retval.Start = input.LT(1); object root_0 = null; IToken char_literal404 = null; IToken LT405 = null; IToken char_literal407 = null; IToken char_literal409 = null; IToken char_literal410 = null; JavaScriptParser.elision_return elision406 = default(JavaScriptParser.elision_return); JavaScriptParser.elision_return elision408 = default(JavaScriptParser.elision_return); object char_literal404_tree=null; object LT405_tree=null; object char_literal407_tree=null; object char_literal409_tree=null; object char_literal410_tree=null; try { // JavaScript.g:341:2: ( '[' ( LT )* ( elision ( ',' elision )* ( ',' )? )? ']' ) // JavaScript.g:341:4: '[' ( LT )* ( elision ( ',' elision )* ( ',' )? )? ']' { root_0 = (object)adaptor.GetNilNode(); char_literal404=(IToken)Match(input,67,FOLLOW_67_in_arrayLiteral3070); if (state.failed) return retval; if ( state.backtracking == 0 ) {char_literal404_tree = new ArrayLiteral(char_literal404) ; root_0 = (object)adaptor.BecomeRoot(char_literal404_tree, root_0); } // JavaScript.g:341:25: ( LT )* do { int alt202 = 2; int LA202_0 = input.LA(1); if ( (LA202_0 == LT) ) { alt202 = 1; } switch (alt202) { case 1 : // JavaScript.g:341:25: LT { LT405=(IToken)Match(input,LT,FOLLOW_LT_in_arrayLiteral3076); if (state.failed) return retval; } break; default: goto loop202; } } while (true); loop202: ; // Stops C# compiler whining that label 'loop202' has no statements // JavaScript.g:341:28: ( elision ( ',' elision )* ( ',' )? )? int alt205 = 2; int LA205_0 = input.LA(1); if ( ((LA205_0 >= Identifier && LA205_0 <= RegexLiteral) || (LA205_0 >= 39 && LA205_0 <= 40) || LA205_0 == 42 || (LA205_0 >= 66 && LA205_0 <= 67) || (LA205_0 >= 99 && LA205_0 <= 100) || (LA205_0 >= 104 && LA205_0 <= 114)) ) { alt205 = 1; } switch (alt205) { case 1 : // JavaScript.g:341:30: elision ( ',' elision )* ( ',' )? { PushFollow(FOLLOW_elision_in_arrayLiteral3082); elision406 = elision(); state.followingStackPointer--; if (state.failed) return retval; if ( state.backtracking == 0 ) adaptor.AddChild(root_0, elision406.Tree); // JavaScript.g:341:38: ( ',' elision )* do { int alt203 = 2; int LA203_0 = input.LA(1); if ( (LA203_0 == 43) ) { int LA203_1 = input.LA(2); if ( ((LA203_1 >= Identifier && LA203_1 <= RegexLiteral) || (LA203_1 >= 39 && LA203_1 <= 40) || LA203_1 == 42 || (LA203_1 >= 66 && LA203_1 <= 67) || (LA203_1 >= 99 && LA203_1 <= 100) || (LA203_1 >= 104 && LA203_1 <= 114)) ) { alt203 = 1; } } switch (alt203) { case 1 : // JavaScript.g:341:39: ',' elision { char_literal407=(IToken)Match(input,43,FOLLOW_43_in_arrayLiteral3085); if (state.failed) return retval; if ( state.backtracking == 0 ) {char_literal407_tree = (object)adaptor.Create(char_literal407); adaptor.AddChild(root_0, char_literal407_tree); } PushFollow(FOLLOW_elision_in_arrayLiteral3087); elision408 = elision(); state.followingStackPointer--; if (state.failed) return retval; if ( state.backtracking == 0 ) adaptor.AddChild(root_0, elision408.Tree); } break; default: goto loop203; } } while (true); loop203: ; // Stops C# compiler whining that label 'loop203' has no statements // JavaScript.g:341:53: ( ',' )? int alt204 = 2; int LA204_0 = input.LA(1); if ( (LA204_0 == 43) ) { alt204 = 1; } switch (alt204) { case 1 : // JavaScript.g:341:53: ',' { char_literal409=(IToken)Match(input,43,FOLLOW_43_in_arrayLiteral3091); if (state.failed) return retval; if ( state.backtracking == 0 ) {char_literal409_tree = (object)adaptor.Create(char_literal409); adaptor.AddChild(root_0, char_literal409_tree); } } break; } } break; } char_literal410=(IToken)Match(input,68,FOLLOW_68_in_arrayLiteral3097); if (state.failed) return retval; } retval.Stop = input.LT(-1); if ( (state.backtracking==0) ) { retval.Tree = (object)adaptor.RulePostProcessing(root_0); adaptor.SetTokenBoundaries(retval.Tree, (IToken) retval.Start, (IToken) retval.Stop);} } catch (RecognitionException re) { ReportError(re); Recover(input,re); // Conversion of the second argument necessary, but harmless retval.Tree = (object)adaptor.ErrorNode(input, (IToken) retval.Start, input.LT(-1), re); } finally { } return retval; }
public override object Walk(ArrayLiteral node) { var array = new BikeArray(); if (node.IsRange) { var from = node.Expressions[0].Accept(this); var fromValue = ((BikeNumber) from).Value; if ((fromValue % 1) != 0) throw ErrorFactory.CreateTypeError("Array range initializer must start with a whole number"); var end = node.Expressions[1].Accept(this); var endValue = ((BikeNumber)end).Value; if ((endValue % 1) != 0) throw ErrorFactory.CreateTypeError("Array range initializer must end with a whole number"); if (fromValue <= endValue) { int index = 0; for (var i = (int) fromValue; i < (int) endValue; i++) { array.Define((index++).ToString(), new BikeNumber(i)); } } else { int index = 0; for (var i = (int)fromValue; i > (int)endValue; i--) { array.Define((index++).ToString(), new BikeNumber(i)); } } return array; } for (int i = 0; i < node.Expressions.Count; i++) { var value = node.Expressions[i].Accept(this); array.Define(i.ToString(), value); } return array; }
public override void Exit(ArrayLiteral node) { level--; }
public virtual void Exit(ArrayLiteral node) { }
public virtual void PostWalk(ArrayLiteral node) { }
public void VisitArrayLiteral(ArrayLiteral arrayLiteral) { foreach (Expression e in arrayLiteral.Values) { VisitExpression(e); } ReturnValue = null; }
public virtual bool Walk(ArrayLiteral node) { return true; }
//--------------------------------------------------------------------------------------- // ParseLeftHandSideExpression // // LeftHandSideExpression : // PrimaryExpression Accessor | // 'new' LeftHandSideExpression | // FunctionExpression // // PrimaryExpression : // 'this' | // Identifier | // Literal | // '(' Expression ')' // // FunctionExpression : // 'function' OptionalFuncName '(' FormalParameterList ')' { FunctionBody } // // OptionalFuncName : // <empty> | // Identifier //--------------------------------------------------------------------------------------- private AstNode ParseLeftHandSideExpression(bool isMinus) { AstNode ast = null; bool isFunction = false; List<Context> newContexts = null; TryItAgain: // new expression while (JSToken.New == m_currentToken.Token) { if (null == newContexts) newContexts = new List<Context>(4); newContexts.Add(m_currentToken.Clone()); GetNextToken(); } JSToken token = m_currentToken.Token; switch (token) { // primary expression case JSToken.Identifier: ast = new Lookup(m_scanner.GetIdentifier(), m_currentToken.Clone(), this); break; case JSToken.ConditionalCommentStart: // skip past the start to the next token GetNextToken(); if (m_currentToken.Token == JSToken.PreprocessorConstant) { // we have /*@id ast = new ConstantWrapperPP(m_currentToken.Code, true, m_currentToken.Clone(), this); GetNextToken(); if (m_currentToken.Token == JSToken.ConditionalCommentEnd) { // skip past the closing comment GetNextToken(); } else { // we ONLY support /*@id@*/ in expressions right now. If there's not // a closing comment after the ID, then we don't support it. // throw an error, skip to the end of the comment, then ignore it and start // looking for the next token. m_currentToken.HandleError(JSError.ConditionalCompilationTooComplex); // skip to end of conditional comment while (m_currentToken.Token != JSToken.EndOfFile && m_currentToken.Token != JSToken.ConditionalCommentEnd) { GetNextToken(); } GetNextToken(); goto TryItAgain; } } else if (m_currentToken.Token == JSToken.ConditionalCommentEnd) { // empty conditional comment! Ignore. GetNextToken(); goto TryItAgain; } else { // we DON'T have "/*@IDENT". We only support "/*@IDENT @*/", so since this isn't // and id, throw the error, skip to the end of the comment, and ignore it // by looping back and looking for the NEXT token. m_currentToken.HandleError(JSError.ConditionalCompilationTooComplex); // skip to end of conditional comment while (m_currentToken.Token != JSToken.EndOfFile && m_currentToken.Token != JSToken.ConditionalCommentEnd) { GetNextToken(); } GetNextToken(); goto TryItAgain; } break; case JSToken.This: ast = new ThisLiteral(m_currentToken.Clone(), this); break; case JSToken.StringLiteral: ast = new ConstantWrapper(m_scanner.StringLiteral, PrimitiveType.String, m_currentToken.Clone(), this); break; case JSToken.IntegerLiteral: case JSToken.NumericLiteral: { Context numericContext = m_currentToken.Clone(); double doubleValue; if (ConvertNumericLiteralToDouble(m_currentToken.Code, (token == JSToken.IntegerLiteral), out doubleValue)) { // conversion worked fine // check for some boundary conditions if (doubleValue == double.MaxValue) { ReportError(JSError.NumericMaximum, numericContext, true); } else if (isMinus && -doubleValue == double.MinValue) { ReportError(JSError.NumericMinimum, numericContext, true); } // create the constant wrapper from the value ast = new ConstantWrapper(doubleValue, PrimitiveType.Number, numericContext, this); } else { // check to see if we went overflow if (double.IsInfinity(doubleValue)) { ReportError(JSError.NumericOverflow, numericContext, true); } // regardless, we're going to create a special constant wrapper // that simply echos the input as-is ast = new ConstantWrapper(m_currentToken.Code, PrimitiveType.Other, numericContext, this); } break; } case JSToken.True: ast = new ConstantWrapper(true, PrimitiveType.Boolean, m_currentToken.Clone(), this); break; case JSToken.False: ast = new ConstantWrapper(false, PrimitiveType.Boolean, m_currentToken.Clone(), this); break; case JSToken.Null: ast = new ConstantWrapper(null, PrimitiveType.Null, m_currentToken.Clone(), this); break; case JSToken.PreprocessorConstant: ast = new ConstantWrapperPP(m_currentToken.Code, false, m_currentToken.Clone(), this); break; case JSToken.DivideAssign: // normally this token is not allowed on the left-hand side of an expression. // BUT, this might be the start of a regular expression that begins with an equals sign! // we need to test to see if we can parse a regular expression, and if not, THEN // we can fail the parse. case JSToken.Divide: // could it be a regexp? String source = m_scanner.ScanRegExp(); if (source != null) { // parse the flags (if any) String flags = m_scanner.ScanRegExpFlags(); // create the literal ast = new RegExpLiteral(source, flags, m_currentToken.Clone(), this); break; } goto default; // expression case JSToken.LeftParenthesis: { // save the current context reference Context openParenContext = m_currentToken.Clone(); GetNextToken(); m_noSkipTokenSet.Add(NoSkipTokenSet.s_ParenExpressionNoSkipToken); try { // parse an expression ast = ParseExpression(); // update the expression's context with the context of the open paren ast.Context.UpdateWith(openParenContext); if (JSToken.RightParenthesis != m_currentToken.Token) { ReportError(JSError.NoRightParenthesis); } else { // add the closing paren to the expression context ast.Context.UpdateWith(m_currentToken); } } catch (RecoveryTokenException exc) { if (IndexOfToken(NoSkipTokenSet.s_ParenExpressionNoSkipToken, exc) == -1) throw; else ast = exc._partiallyComputedNode; } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ParenExpressionNoSkipToken); } if (ast == null) //this can only happen when catching the exception and nothing was sent up by the caller SkipTokensAndThrow(); } break; // array initializer case JSToken.LeftBracket: Context listCtx = m_currentToken.Clone(); AstNodeList list = new AstNodeList(m_currentToken.Clone(), this); GetNextToken(); while (JSToken.RightBracket != m_currentToken.Token) { if (JSToken.Comma != m_currentToken.Token) { m_noSkipTokenSet.Add(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet); try { list.Append(ParseExpression(true)); if (JSToken.Comma != m_currentToken.Token) { if (JSToken.RightBracket != m_currentToken.Token) ReportError(JSError.NoRightBracket); break; } else { // we have a comma -- skip it GetNextToken(); // if the next token is the closing brackets, then we need to // add a missing value to the array because we end in a comma and // we need to keep it for cross-platform compat. // TECHNICALLY, that puts an extra item into the array for most modern browsers, but not ALL. if (m_currentToken.Token == JSToken.RightBracket) { list.Append(new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this)); } } } catch (RecoveryTokenException exc) { if (exc._partiallyComputedNode != null) list.Append(exc._partiallyComputedNode); if (IndexOfToken(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet, exc) == -1) { listCtx.UpdateWith(CurrentPositionContext()); exc._partiallyComputedNode = new ArrayLiteral(listCtx, this, list); throw; } else { if (JSToken.RightBracket == m_currentToken.Token) break; } } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet); } } else { // comma -- missing array item in the list list.Append(new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this)); // skip over the comma GetNextToken(); // if the next token is the closing brace, then we end with a comma -- and we need to // add ANOTHER missing value to make sure this last comma doesn't get left off. // TECHNICALLY, that puts an extra item into the array for most modern browsers, but not ALL. if (m_currentToken.Token == JSToken.RightBracket) { list.Append(new ConstantWrapper(Missing.Value, PrimitiveType.Other, m_currentToken.Clone(), this)); } } } listCtx.UpdateWith(m_currentToken); ast = new ArrayLiteral(listCtx, this, list); break; // object initializer case JSToken.LeftCurly: Context objCtx = m_currentToken.Clone(); GetNextToken(); // we're going to keep the keys and values in separate lists, but make sure // that the indexes correlate (keyList[n] is associated with valueList[n]) List<ObjectLiteralField> keyList = new List<ObjectLiteralField>(); List<AstNode> valueList = new List<AstNode>(); if (JSToken.RightCurly != m_currentToken.Token) { for (; ; ) { ObjectLiteralField field = null; AstNode value = null; bool getterSetter = false; string ident; switch (m_currentToken.Token) { case JSToken.Identifier: field = new ObjectLiteralField(m_scanner.GetIdentifier(), PrimitiveType.String, m_currentToken.Clone(), this); break; case JSToken.StringLiteral: field = new ObjectLiteralField(m_scanner.StringLiteral, PrimitiveType.String, m_currentToken.Clone(), this); break; case JSToken.IntegerLiteral: case JSToken.NumericLiteral: { double doubleValue; if (ConvertNumericLiteralToDouble(m_currentToken.Code, (m_currentToken.Token == JSToken.IntegerLiteral), out doubleValue)) { // conversion worked fine field = new ObjectLiteralField( doubleValue, PrimitiveType.Number, m_currentToken.Clone(), this ); } else { // something went wrong and we're not sure the string representation in the source is // going to convert to a numeric value well if (double.IsInfinity(doubleValue)) { ReportError(JSError.NumericOverflow, m_currentToken.Clone(), true); } // use the source as the field name, not the numeric value field = new ObjectLiteralField( m_currentToken.Code, PrimitiveType.Other, m_currentToken.Clone(), this); } break; } case JSToken.Get: case JSToken.Set: if (m_scanner.PeekToken() == JSToken.Colon) { // the field is either "get" or "set" and isn't the special Mozilla getter/setter field = new ObjectLiteralField(m_currentToken.Code, PrimitiveType.String, m_currentToken.Clone(), this); } else { // ecma-script get/set property construct getterSetter = true; bool isGet = (m_currentToken.Token == JSToken.Get); value = ParseFunction( (JSToken.Get == m_currentToken.Token ? FunctionType.Getter : FunctionType.Setter), m_currentToken.Clone() ); FunctionObject funcExpr = value as FunctionObject; if (funcExpr != null) { // getter/setter is just the literal name with a get/set flag field = new GetterSetter( funcExpr.Name, isGet, funcExpr.IdContext.Clone(), this ); } else { ReportError(JSError.FunctionExpressionExpected); } } break; default: // NOT: identifier, string, number, or getter/setter. // see if it's a token that COULD be an identifier. ident = JSKeyword.CanBeIdentifier(m_currentToken.Token); if (ident != null) { // don't throw a warning -- it's okay to have a keyword that // can be an identifier here. field = new ObjectLiteralField(ident, PrimitiveType.String, m_currentToken.Clone(), this); } else { ReportError(JSError.NoMemberIdentifier); field = new ObjectLiteralField("_#Missing_Field#_" + s_cDummyName++, PrimitiveType.String, CurrentPositionContext(), this); } break; } if (field != null) { if (!getterSetter) { GetNextToken(); } m_noSkipTokenSet.Add(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet); try { if (!getterSetter) { // get the value if (JSToken.Colon != m_currentToken.Token) { ReportError(JSError.NoColon, true); value = ParseExpression(true); } else { GetNextToken(); value = ParseExpression(true); } } // put the pair into the list of fields keyList.Add(field); valueList.Add(value); if (JSToken.RightCurly == m_currentToken.Token) break; else { if (JSToken.Comma == m_currentToken.Token) { // skip the comma GetNextToken(); // if the next token is the right-curly brace, then we ended // the list with a comma, which is perfectly fine if (m_currentToken.Token == JSToken.RightCurly) { break; } } else { if (m_scanner.GotEndOfLine) { ReportError(JSError.NoRightCurly); } else ReportError(JSError.NoComma, true); SkipTokensAndThrow(); } } } catch (RecoveryTokenException exc) { if (exc._partiallyComputedNode != null) { // the problem was in ParseExpression trying to determine value value = exc._partiallyComputedNode; keyList.Add(field); valueList.Add(value); } if (IndexOfToken(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet, exc) == -1) { exc._partiallyComputedNode = new ObjectLiteral(objCtx, this, keyList.ToArray(), valueList.ToArray()); throw; } else { if (JSToken.Comma == m_currentToken.Token) GetNextToken(); if (JSToken.RightCurly == m_currentToken.Token) break; } } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet); } } } } objCtx.UpdateWith(m_currentToken); ast = new ObjectLiteral(objCtx, this, keyList.ToArray(), valueList.ToArray()); break; // function expression case JSToken.Function: ast = ParseFunction(FunctionType.Expression, m_currentToken.Clone()); isFunction = true; break; case JSToken.AspNetBlock: ast = ParseAspNetBlock(consumeSemicolonIfPossible: false); break; default: string identifier = JSKeyword.CanBeIdentifier(m_currentToken.Token); if (null != identifier) { ast = new Lookup(identifier, m_currentToken.Clone(), this); } else { ReportError(JSError.ExpressionExpected); SkipTokensAndThrow(); } break; } // can be a CallExpression, that is, followed by '.' or '(' or '[' if (!isFunction) GetNextToken(); return MemberExpression(ast, newContexts); }
void ArrayLiteral(Scope scope, out IExpression expr) { IExpression innerExpr; Expect(10); List<IExpression> innerExprs = new List<IExpression>(); if (StartOf(1)) { Expression(scope, out innerExpr); innerExprs.Add(innerExpr); while (la.kind == 11) { Get(); Expression(scope, out innerExpr); innerExprs.Add(innerExpr); } } Expect(12); expr = new ArrayLiteral(innerExprs); }
public override bool Enter(ArrayLiteral node) { Print("ArrayLiteral"); level++; return true; }
public override void Visit(CallNode node) { if (node != null) { // see if this is a member (we'll need it for a couple checks) Member member = node.Function as Member; if (m_parser.Settings.StripDebugStatements && m_parser.Settings.IsModificationAllowed(TreeModifications.StripDebugStatements)) { // if this is a member, and it's a debugger object, and it's a constructor.... if (member != null && member.IsDebuggerStatement && node.IsConstructor) { // we need to replace our debugger object with a generic Object node.ReplaceChild(node.Function, new Lookup("Object", node.Function.Context, m_parser)); // and make sure the node list is empty if (node.Arguments != null && node.Arguments.Count > 0) { node.ReplaceChild(node.Arguments, new AstNodeList(node.Arguments.Context, m_parser)); } } } // if this is a constructor and we want to collapse // some of them to literals... if (node.IsConstructor && m_parser.Settings.CollapseToLiteral) { // see if this is a lookup, and if so, if it's pointing to one // of the two constructors we want to collapse Lookup lookup = node.Function as Lookup; if (lookup != null) { if (lookup.Name == "Object" && m_parser.Settings.IsModificationAllowed(TreeModifications.NewObjectToObjectLiteral)) { // no arguments -- the Object constructor with no arguments is the exact same as an empty // object literal if (node.Arguments == null || node.Arguments.Count == 0) { // replace our node with an object literal ObjectLiteral objLiteral = new ObjectLiteral(node.Context, m_parser, null, null); if (node.Parent.ReplaceChild(node, objLiteral)) { // and bail now. No need to recurse -- it's an empty literal return; } } else if (node.Arguments.Count == 1) { // one argument // check to see if it's an object literal. ObjectLiteral objectLiteral = node.Arguments[0] as ObjectLiteral; if (objectLiteral != null) { // the Object constructor with an argument that is a JavaScript object merely returns the // argument. Since the argument is an object literal, it is by definition a JavaScript object // and therefore we can replace the constructor call with the object literal node.Parent.ReplaceChild(node, objectLiteral); // don't forget to recurse the object now objectLiteral.Accept(this); // and then bail -- we don't want to process this call // operation any more; we've gotten rid of it return; } } } else if (lookup.Name == "Array" && m_parser.Settings.IsModificationAllowed(TreeModifications.NewArrayToArrayLiteral)) { // Array is trickier. // If there are no arguments, then just use []. // if there are multiple arguments, then use [arg0,arg1...argN]. // but if there is one argument and it's numeric, we can't crunch it. // also can't crunch if it's a function call or a member or something, since we won't // KNOW whether or not it's numeric. // // so first see if it even is a single-argument constant wrapper. ConstantWrapper constWrapper = (node.Arguments != null && node.Arguments.Count == 1 ? node.Arguments[0] as ConstantWrapper : null); // if the argument count is not one, then we crunch. // if the argument count IS one, we only crunch if we have a constant wrapper, // AND it's not numeric. if (node.Arguments == null || node.Arguments.Count != 1 || (constWrapper != null && !constWrapper.IsNumericLiteral)) { // create the new array literal object ArrayLiteral arrayLiteral = new ArrayLiteral(node.Context, m_parser, node.Arguments); // replace ourself within our parent if (node.Parent.ReplaceChild(node, arrayLiteral)) { // recurse arrayLiteral.Accept(this); // and bail -- we don't want to recurse this node any more return; } } } } } // if we are replacing resource references with strings generated from resource files // and this is a brackets call: lookup[args] ResourceStrings resourceStrings = m_parser.ResourceStrings; if (node.InBrackets && resourceStrings != null && resourceStrings.Count > 0) { // see if the root object is a lookup that corresponds to the // global value (not a local field) for our resource object // (same name) Lookup rootLookup = node.Function as Lookup; if (rootLookup != null && rootLookup.LocalField == null && string.CompareOrdinal(rootLookup.Name, resourceStrings.Name) == 0) { // we're going to replace this node with a string constant wrapper // but first we need to make sure that this is a valid lookup. // if the parameter contains anything that would vary at run-time, // then we need to throw an error. // the parser will always have either one or zero nodes in the arguments // arg list. We're not interested in zero args, so just make sure there is one if (node.Arguments.Count == 1) { // must be a constant wrapper ConstantWrapper argConstant = node.Arguments[0] as ConstantWrapper; if (argConstant != null) { string resourceName = argConstant.Value.ToString(); // get the localized string from the resources object ConstantWrapper resourceLiteral = new ConstantWrapper( resourceStrings[resourceName], PrimitiveType.String, node.Context, m_parser); // replace this node with localized string, analyze it, and bail // so we don't anaylze the tree we just replaced node.Parent.ReplaceChild(node, resourceLiteral); resourceLiteral.Accept(this); return; } else { // error! must be a constant node.Context.HandleError( JSError.ResourceReferenceMustBeConstant, true); } } else { // error! can only be a single constant argument to the string resource object. // the parser will only have zero or one arguments, so this must be zero // (since the parser won't pass multiple args to a [] operator) node.Context.HandleError( JSError.ResourceReferenceMustBeConstant, true); } } } // and finally, if this is a backets call and the argument is a constantwrapper that can // be an identifier, just change us to a member node: obj["prop"] to obj.prop. // but ONLY if the string value is "safe" to be an identifier. Even though the ECMA-262 // spec says certain Unicode categories are okay, in practice the various major browsers // all seem to have problems with certain characters in identifiers. Rather than risking // some browsers breaking when we change this syntax, don't do it for those "danger" categories. if (node.InBrackets && node.Arguments != null) { // see if there is a single, constant argument string argText = node.Arguments.SingleConstantArgument; if (argText != null) { // see if we want to replace the name string newName; if (m_parser.Settings.HasRenamePairs && m_parser.Settings.ManualRenamesProperties && m_parser.Settings.IsModificationAllowed(TreeModifications.PropertyRenaming) && !string.IsNullOrEmpty(newName = m_parser.Settings.GetNewName(argText))) { // yes -- we are going to replace the name, either as a string literal, or by converting // to a member-dot operation. // See if we can't turn it into a dot-operator. If we can't, then we just want to replace the operator with // a new constant wrapper. Otherwise we'll just replace the operator with a new constant wrapper. if (m_parser.Settings.IsModificationAllowed(TreeModifications.BracketMemberToDotMember) && JSScanner.IsSafeIdentifier(newName) && !JSScanner.IsKeyword(newName, node.EnclosingScope.UseStrict)) { // the new name is safe to convert to a member-dot operator. // but we don't want to convert the node to the NEW name, because we still need to Analyze the // new member node -- and it might convert the new name to something else. So instead we're // just going to convert this existing string to a member node WITH THE OLD STRING, // and THEN analyze it (which will convert the old string to newName) Member replacementMember = new Member(node.Context, m_parser, node.Function, argText, node.Arguments[0].Context); node.Parent.ReplaceChild(node, replacementMember); // this analyze call will convert the old-name member to the newName value replacementMember.Accept(this); return; } else { // nope; can't convert to a dot-operator. // we're just going to replace the first argument with a new string literal // and continue along our merry way. node.Arguments.ReplaceChild(node.Arguments[0], new ConstantWrapper(newName, PrimitiveType.String, node.Arguments[0].Context, m_parser)); } } else if (m_parser.Settings.IsModificationAllowed(TreeModifications.BracketMemberToDotMember) && JSScanner.IsSafeIdentifier(argText) && !JSScanner.IsKeyword(argText, node.EnclosingScope.UseStrict)) { // not a replacement, but the string literal is a safe identifier. So we will // replace this call node with a Member-dot operation Member replacementMember = new Member(node.Context, m_parser, node.Function, argText, node.Arguments[0].Context); node.Parent.ReplaceChild(node, replacementMember); replacementMember.Accept(this); return; } } } // call the base class to recurse base.Visit(node); // might have changed member = node.Function as Member; // call this AFTER recursing to give the fields a chance to resolve, because we only // want to make this replacement if we are working on the global Date object. if (!node.InBrackets && !node.IsConstructor && (node.Arguments == null || node.Arguments.Count == 0) && member != null && string.CompareOrdinal(member.Name, "getTime") == 0 && m_parser.Settings.IsModificationAllowed(TreeModifications.DateGetTimeToUnaryPlus)) { // this is not a constructor and it's not a brackets call, and there are no arguments. // if the function is a member operation to "getTime" and the object of the member is a // constructor call to the global "Date" object (not a local), then we want to replace the call // with a unary plus on the Date constructor. Converting to numeric type is the same as // calling getTime, so it's the equivalent with much fewer bytes. CallNode dateConstructor = member.Root as CallNode; if (dateConstructor != null && dateConstructor.IsConstructor) { // lookup for the predifined (not local) "Date" field Lookup lookup = dateConstructor.Function as Lookup; if (lookup != null && string.CompareOrdinal(lookup.Name, "Date") == 0 && lookup.LocalField == null) { // this is in the pattern: (new Date()).getTime() // we want to replace it with +new Date // use the same date constructor node as the operand NumericUnary unary = new NumericUnary(node.Context, m_parser, dateConstructor, JSToken.Plus); // replace us (the call to the getTime method) with this unary operator node.Parent.ReplaceChild(node, unary); // don't need to recurse on the unary operator. The operand has already // been analyzed when we recursed, and the unary operator wouldn't do anything // special anyway (since the operand is not a numeric constant) } } } else { var isEval = false; var lookup = node.Function as Lookup; if (lookup != null && string.CompareOrdinal(lookup.Name, "eval") == 0 && lookup.VariableField is JSPredefinedField) { // call to predefined eval function isEval = true; } else if (member != null && string.CompareOrdinal(member.Name, "eval") == 0) { // if this is a window.eval call, then we need to mark this scope as unknown just as // we would if this was a regular eval call. // (unless, of course, the parser settings say evals are safe) // call AFTER recursing so we know the left-hand side properties have had a chance to // lookup their fields to see if they are local or global if (member.LeftHandSide.IsWindowLookup) { // this is a call to window.eval() isEval = true; } } else { CallNode callNode = node.Function as CallNode; if (callNode != null && callNode.InBrackets && callNode.LeftHandSide.IsWindowLookup && callNode.Arguments.IsSingleConstantArgument("eval")) { // this is a call to window["eval"] isEval = true; } } if (isEval) { if (m_parser.Settings.EvalTreatment != EvalTreatment.Ignore) { // mark this scope as unknown so we don't crunch out locals // we might reference in the eval at runtime ScopeStack.Peek().IsKnownAtCompileTime = false; } } } } }
public override void Visit(ArrayLiteral node) { // same logic for most nodes TypicalHandler(node); }
public virtual object Walk(ArrayLiteral node) { if (Enter(node)) { foreach (var exp in node.Expressions) { exp.Accept(this); } } Exit(node); return null; }