/// <summary> /// Adds init, max, min to the completion list /// </summary> public static void AddIntegralTypeProperties(int TypeToken, ResolveResult rr, ICompletionDataGenerator cdg, INode relatedNode = null, bool DontAddInitProperty = false) { var intType = new DTokenDeclaration(TypeToken); if (!DontAddInitProperty) { var prop_Init = new DVariable() { Type = intType, Initializer = new IdentifierExpression(0, LiteralFormat.Scalar) }; if (relatedNode != null) { prop_Init.AssignFrom(relatedNode); } // Override the initializer variable's name and description prop_Init.Name = "init"; prop_Init.Description = "A type's or variable's static initializer expression"; cdg.Add(prop_Init); } CreateArtificialProperties(IntegralProps, cdg, intType); }
public static string ScriptExtractValue(ILegacyLogger i_Logger, string i_sVmcId, ISubdocContext i_SubdocContext, string i_sString) { string sRet = ""; // FIX - Should also check for integers if ((i_sString[0] == '\"') || (i_sString[0] == '\'')) { sRet = ScriptExtractStringValue(i_sString); } else { DVariable dvTmp = DialogEngine.DialogEngine.FindVariableByName(i_SubdocContext, i_sString); if (dvTmp == null) { i_Logger.Log(Level.Exception, String.Format("[{0}]DialogEngine.ScriptExtractValue - Couldn't find variable named '{1}' in {2} '{3}'.", i_sVmcId, i_sString, ((i_SubdocContext.GetType() == typeof(DForm)) ? "form" : "field"), i_SubdocContext.ID)); } else { sRet = dvTmp.SValue; } } return(sRet); }
DVariable Argument(ref char c, out AbstractType parType) { bool scoped; if (scoped = (c == 'M')) { c = (char)r.Read(); //TODO: Handle scoped } var par = new DVariable { Attributes = new List <DAttribute>() }; if (c == 'J' || c == 'K' || c == 'L') { switch (c) { case 'J': par.Attributes.Add(new Modifier(DTokens.Out)); break; case 'K': par.Attributes.Add(new Modifier(DTokens.Ref)); break; case 'L': par.Attributes.Add(new Modifier(DTokens.Lazy)); break; } c = (char)r.Read(); } parType = Type(c); par.Type = DTypeToTypeDeclVisitor.GenerateTypeDecl(parType); return(par); }
DVariable Argument(ref char c, out AbstractType parType) { bool scoped; if (scoped = (c == 'M')) { c = (char)r.Read(); //TODO: Handle scoped } var par = new DVariable { Attributes = new List <DAttribute>() }; if (c == 'J' || c == 'K' || c == 'L') { if (c == 'J') { par.Attributes.Add(new Modifier(DTokens.Out)); } else if (c == 'K') { par.Attributes.Add(new Modifier(DTokens.Ref)); } else if (c == 'L') { par.Attributes.Add(new Modifier(DTokens.Lazy)); } c = (char)r.Read(); } parType = Type(c); par.Type = parType.TypeDeclarationOf; return(par); }
public override ISymbolValue this[DVariable n] { get { if (n == null) { throw new ArgumentNullException("There must be a valid variable node given in order to retrieve its value"); } if (n.IsConst) { // .. resolve it's pre-compile time value and make the returned value the given argument var val = Evaluation.EvaluateValue(n.Initializer, this); // If it's null, then the initializer is null - which is equal to e.g. 0 or null !; if (val != null) { return(val); } } throw new ArgumentException(n + " must have a constant initializer"); } set { throw new NotImplementedException(); } }
public static void AddFloatingTypeProperties(int TypeToken, ResolveResult rr, ICompletionDataGenerator cdg, INode relatedNode = null, bool DontAddInitProperty = false) { var intType = new DTokenDeclaration(TypeToken); if (!DontAddInitProperty) { var prop_Init = new DVariable() { Type = intType, Initializer = new PostfixExpression_Access() { PostfixForeExpression = new TokenExpression(TypeToken), TemplateOrIdentifier = new IdentifierDeclaration("nan") } }; if (relatedNode != null) { prop_Init.AssignFrom(relatedNode); } // Override the initializer variable's name and description prop_Init.Name = "init"; prop_Init.Description = "A type's or variable's static initializer expression"; cdg.Add(prop_Init); } CreateArtificialProperties(FloatingTypeProps, cdg, intType); }
public override void Visit(DVariable n) { FormatAttributedNode(n, n.NameLocation != n.Location); if (n.Type != null) { n.Type.Accept(this); } if (!n.NameLocation.IsEmpty) { // Check if we're inside a multi-declaration like int a,b,c; var lastNonWs = SearchWhitespaceStart(document.ToOffset(n.NameLocation)) - 1; if (lastNonWs > 0 && document[lastNonWs] == ',') { switch (policy.MultiVariableDeclPlacement) { case NewLinePlacement.NewLine: curIndent.Push(IndentType.Continuation); FixIndentationForceNewLine(n.NameLocation); curIndent.Pop(); break; case NewLinePlacement.SameLine: ForceSpacesBeforeRemoveNewLines(n.NameLocation, true); break; } } else { if (policy.ForceNodeNameOnSameLine) { ForceSpacesBeforeRemoveNewLines(n.NameLocation, true); } } if (n.Initializer != null) { // place '=' token ForceSpacesAfterRemoveLines(new CodeLocation(n.NameLocation.Column + n.Name.Length, n.NameLocation.Line), true); if (policy.ForceVarInitializerOnSameLine) { ForceSpacesBeforeRemoveNewLines(n.Initializer.Location, true); n.Initializer.Accept(this); } else { curIndent.Push(IndentType.Block); if (n.NameLocation.Line != n.Initializer.Location.Line) { FixStatementIndentation(n.Initializer.Location); } n.Initializer.Accept(this); curIndent.Pop(); } } } }
public AliasedType(DVariable AliasDefinition, AbstractType Type, ISyntaxRegion td, IEnumerable <TemplateParameterSymbol> deducedTypes) : base(AliasDefinition, Type, td, deducedTypes) { if (Type != null) { Type.NonStaticAccess = false; } }
public static string GeneratePrototype(DVariable dv) { var sb = new StringBuilder("Variable in "); sb.Append(AbstractNode.GetNodePath(dv, false)); sb.Append(": "); sb.Append(dv.ToString(false)); return(sb.ToString()); }
public string VisitDVariable(DVariable dVariable) { if (dVariable.IsAlias) { return("ALIA"); } if (dVariable.IsStaticProperty) { return("SPRP"); } return("VAR"); }
static AbstractVisitor() { __ctfe = new DVariable { Name = "__ctfe", Type = new DTokenDeclaration(DTokens.Bool), Initializer = new TokenExpression(DTokens.True), Description = @"Булева псевдопеременная __ctfe, оцениваемая в true во время компиляции, на в false во время выполнения, может использоваться для предоставления альтернативного пути выполнения во избежание операций, запрещённых во время компиляции.", Attributes = new List<DAttribute>{new Modifier(DTokens.Static),new Modifier(DTokens.Const)} }; }
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { float height = LINE_HEIGHT; if (!property.isExpanded) { return(height); } height += LINE_HEIGHT; DVariable dVariable = GetObject(property); height += LINE_HEIGHT * dVariable.DecoratorCount; return(height); }
// Associative Arrays' properties have to be inserted manually static void CreateArtificialProperties(StaticProperty[] Properties, ICompletionDataGenerator cdg, ITypeDeclaration DefaultPropType = null) { foreach (var prop in Properties) { var p = new DVariable() { Name = prop.Name, Description = prop.Description, Type = prop.OverrideType != null ? prop.OverrideType : DefaultPropType }; cdg.Add(p); } }
static AbstractVisitor() { __ctfe = new DVariable { Name = "__ctfe", Type = new DTokenDeclaration(DTokens.Bool), Initializer = new TokenExpression(DTokens.True), Description = @"The __ctfe boolean pseudo-variable, which evaluates to true at compile time, but false at run time, can be used to provide an alternative execution path to avoid operations which are forbidden at compile time.", Attributes = new List <DAttribute> { new Modifier(DTokens.Static), new Modifier(DTokens.Const) } }; }
public override ISymbolValue this[DVariable n] { get { var dv = n as DebugVariable; if (dv != null) { return(Backtrace.EvaluateSymbol(dv.Symbol)); } return(base[n]); } set { //TODO? base[n] = value; } }
public AbstractType Visit(DVariable variable) { AbstractType bt; if (CanResolveBase(variable)) { var bts = TypeDeclarationResolver.Resolve(variable.Type, ctxt); if (bts != null && bts.Length != 0) { bt = bts[0]; } // For auto variables, use the initializer to get its type else if (variable.Initializer != null) { bt = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(variable.Initializer, ctxt)); } else { bt = null; } // Check if inside an foreach statement header if (bt == null && ctxt.ScopedStatement != null) { bt = GetForeachIteratorType(variable); } if (bt == null) { ctxt.CheckForSingleResult(bts, variable.Type as ISyntaxRegion ?? variable.Initializer); } } else { bt = null; } // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type return(variable.IsAlias ? new AliasedType(variable, bt, typeBase) : new MemberSymbol(variable, bt, typeBase)); }
public override void Visit(DVariable n) { if (n.NameHash == 0 && n.ContainsAttribute(DTokens.Override)) { prv = new MethodOverrideCompletionProvider(n, cdgen); halt = true; return; } if (n.IsAlias) { // alias | // alias id = | // NOT alias Type | if (IsIncompleteDeclaration(n.Type)) { prv = new CtrlSpaceCompletionProvider(cdgen, scopedBlock, MemberFilter.All | MemberFilter.BlockKeywords); halt = true; return; } } else if (n.Initializer != null) { initializedNode = n; handlesInitializer = true; n.Initializer.Accept(this); handlesInitializer = false; } if (!halt) { VisitDNode(n); } // auto | if (!halt && n.NameHash == 0 && (n.ContainsAttribute(DTokens.Auto) || DParser.ContainsStorageClass(n.Attributes) != Modifier.Empty)) { halt = true; explicitlyNoCompletion = true; } }
public override ISymbolValue this[DVariable variable] { get { ISymbolValue v; if (Locals.TryGetValue(variable, out v)) { return(v); } throw new CtfeException("Variable " + variable.ToString() + " not set yet!"); } set { if (variable == null) { throw new CtfeException("Can't set non-existent variable"); } Locals[variable] = value; } }
/// <summary> /// Adds init, sizeof, alignof, mangleof, stringof to the completion list /// </summary> public static void AddGenericProperties(ResolveResult rr, ICompletionDataGenerator cdg, INode relatedNode = null, bool DontAddInitProperty = false) { if (!DontAddInitProperty) { var prop_Init = new DVariable(); if (relatedNode != null) { prop_Init.AssignFrom(relatedNode); } // Override the initializer variable's name and description prop_Init.Name = "init"; prop_Init.Description = "A type's or variable's static initializer expression"; cdg.Add(prop_Init); } CreateArtificialProperties(GenericProps, cdg); }
public override ISymbolValue this[DVariable variable] { get { ISymbolValue v; if (Locals.TryGetValue(variable, out v)) { return(v); } // Assign a default value to the variable var t = TypeResolution.TypeDeclarationResolver.HandleNodeMatch(variable, base.ResolutionContext) as MemberSymbol; if (t != null) { if (t.Base is PrimitiveType) { v = new PrimitiveValue(0M, t.Base as PrimitiveType); } else { v = new NullValue(t.Base); } } else { v = new NullValue(); } Locals[variable] = v; return(v); } set { if (variable == null) { throw new CtfeException("variable must not be null"); } Locals[variable] = value; } }
public override ISymbolValue this[DVariable n] { get { if (n == null) { return(new ErrorValue(new EvaluationException("There must be a valid variable node given in order to retrieve its value"))); } if (n.IsConst) { if (varsBeingResolved.Contains(n)) { return(new ErrorValue(new EvaluationException("Cannot reference itself"))); } varsBeingResolved.Add(n); // .. resolve it's pre-compile time value and make the returned value the given argument ISymbolValue val; try{ val = Evaluation.EvaluateValue(n.Initializer, this); } finally{ varsBeingResolved.Remove(n); } // If it's null, then the initializer is null - which is equal to e.g. 0 or null !; if (val != null) { return(val); } } return(new ErrorValue(new EvaluationException(n + " must have a constant initializer"))); } set { throw new NotImplementedException(); } }
public override void Visit(DVariable n) { if (n.NameHash == 0 && n.ContainsAttribute(DTokens.Override)) { prv = new MethodOverrideCompletionProvider(n, cdgen); halt = true; return; } if (n.IsAlias) { // alias | // alias id = | // NOT alias Type | if (IsIncompleteDeclaration(n.Type)) { prv = new CtrlSpaceCompletionProvider(cdgen, scopedBlock, scopedStatement); halt = true; } } else if (n.Initializer != null) { handlesInitializer = true; n.Initializer.Accept(this); handlesInitializer = false; } if (!halt) { VisitDNode(n); } // auto | if (!halt && n.NameHash == 0 && n.ContainsAttribute(DTokens.Auto)) { halt = true; explicitlyNoCompletion = true; } }
public abstract ISymbolValue this[DVariable variable] { get; set; }
public AliasedType(DVariable AliasDefinition, AbstractType Type, ISyntaxRegion td, ReadOnlyCollection<TemplateParameterSymbol> deducedTypes=null) : base(AliasDefinition,Type, td, deducedTypes) {}
public StaticVariableValue(DVariable artificialVariable, AbstractType propType) : base(new MemberSymbol(artificialVariable, propType, null)) { }
public AssocArrayPointer(DVariable accessedArray, AssocArrayType arrayType, ISymbolValue accessedItemKey) : base(new MemberSymbol(accessedArray, arrayType, null)) { Key = accessedItemKey; }
public string Visit(DVariable dVariable) { return(VisitDVariable(dVariable)); }
public AliasedType(DVariable AliasDefinition, AbstractType Type, ISyntaxRegion td, ReadOnlyCollection <TemplateParameterSymbol> deducedTypes = null) : base(AliasDefinition, Type, td, deducedTypes) { }
/// <summary> /// string[] s; /// /// foreach(i;s) /// { /// // i is of type 'string' /// writeln(i); /// } /// </summary> public static AbstractType GetForeachIteratorType(DVariable i, ResolutionContext ctxt) { var r = new List<AbstractType>(); var curStmt = ctxt.ScopedStatement; bool init = true; // Walk up statement hierarchy -- note that foreach loops can be nested while (curStmt != null) { if (init) init = false; else curStmt = curStmt.Parent; if (curStmt is ForeachStatement) { var fe = (ForeachStatement)curStmt; if (fe.ForeachTypeList == null) continue; // If the searched variable is declared in the header int iteratorIndex = -1; for (int j = 0; j < fe.ForeachTypeList.Length; j++) if (fe.ForeachTypeList[j] == i) { iteratorIndex = j; break; } if (iteratorIndex == -1) continue; bool keyIsSearched = iteratorIndex == 0 && fe.ForeachTypeList.Length > 1; // foreach(var k, var v; 0 .. 9) if (keyIsSearched && fe.IsRangeStatement) { // -- it's static type int, of course(?) return new PrimitiveType(DTokens.Int); } var aggregateType = Evaluation.EvaluateType(fe.Aggregate, ctxt); aggregateType = DResolver.StripMemberSymbols(aggregateType); if (aggregateType == null) return null; // The most common way to do a foreach if (aggregateType is AssocArrayType) { var ar = (AssocArrayType)aggregateType; return keyIsSearched ? ar.KeyType : ar.ValueType; } else if (aggregateType is UserDefinedType) { var tr = (UserDefinedType)aggregateType; if (keyIsSearched || !(tr.Definition is IBlockNode)) continue; bool foundIterPropertyMatch = false; #region Foreach over Structs and Classes with Ranges // Enlist all 'back'/'front' members var t_l = new List<AbstractType>(); foreach (var n in (IBlockNode)tr.Definition) if (fe.IsReverse ? n.Name == "back" : n.Name == "front") t_l.Add(HandleNodeMatch(n, ctxt)); // Remove aliases var iterPropertyTypes = DResolver.StripAliasSymbols(t_l); foreach (var iterPropType in iterPropertyTypes) if (iterPropType is MemberSymbol) { foundIterPropertyMatch = true; var itp = (MemberSymbol)iterPropType; // Only take non-parameterized methods if (itp.Definition is DMethod && ((DMethod)itp.Definition).Parameters.Count != 0) continue; // Handle its base type [return type] as iterator type if (itp.Base != null) r.Add(itp.Base); foundIterPropertyMatch = true; } if (foundIterPropertyMatch) continue; #endregion #region Foreach over Structs and Classes with opApply t_l.Clear(); r.Clear(); foreach (var n in (IBlockNode)tr.Definition) if (n is DMethod && (fe.IsReverse ? n.Name == "opApplyReverse" : n.Name == "opApply")) t_l.Add(HandleNodeMatch(n, ctxt)); iterPropertyTypes = DResolver.StripAliasSymbols(t_l); foreach (var iterPropertyType in iterPropertyTypes) if (iterPropertyType is MemberSymbol) { var mr = (MemberSymbol)iterPropertyType; var dm = mr.Definition as DMethod; if (dm == null || dm.Parameters.Count != 1) continue; var dg = dm.Parameters[0].Type as DelegateDeclaration; if (dg == null || dg.Parameters.Count != fe.ForeachTypeList.Length) continue; var paramType = Resolve(dg.Parameters[iteratorIndex].Type, ctxt); if (paramType != null && paramType.Length > 0) r.Add(paramType[0]); } #endregion } if (r.Count > 1) ctxt.LogError(new ResolutionError(curStmt, "Ambigous iterator type")); return r.Count != 0 ? r[0] : null; } } return null; }
public VariableValue(MemberSymbol mr) : base(mr.Base) { this.Member = mr; this.Variable = mr.Definition as DVariable; }
public AssocArrayPointer(DVariable accessedArray, AssocArrayType arrayType, ISymbolValue accessedItemKey) : base(new MemberSymbol(accessedArray, arrayType,null)) { Key = accessedItemKey; }
/// <summary> /// Array ctor. /// </summary> /// <param name="accessedItem">0 - the array's length-1; -1 when adding the item is wished.</param> public ArrayPointer(DVariable accessedArray, ArrayType arrayType, int accessedItem) : base(new MemberSymbol(accessedArray, arrayType, null)) { ItemNumber = accessedItem; }
List<INode> Decl(bool HasStorageClassModifiers,IBlockNode Scope, DAttribute StorageClass = null) { var startLocation = la.Location; var initialComment = GetComments(); ITypeDeclaration ttd = null; CheckForStorageClasses(Scope as DBlockNode); // Autodeclaration if(StorageClass == null) StorageClass = DTokens.ContainsStorageClass(DeclarationAttributes); if (laKind == Enum) { Step(); PushAttribute(StorageClass = new Modifier(Enum) { Location = t.Location, EndLocation = t.EndLocation },false); } // If there's no explicit type declaration, leave our node's type empty! if ((StorageClass != Modifier.Empty && laKind == (Identifier) && (DeclarationAttributes.Count > 0 || Lexer.CurrentPeekToken.Kind == OpenParenthesis))) // public auto var=0; // const foo(...) {} { if (Lexer.CurrentPeekToken.Kind == Assign || Lexer.CurrentPeekToken.Kind ==OpenParenthesis) { } else if (Lexer.CurrentPeekToken.Kind == Semicolon) { SemErr(t.Kind, "Initializer expected for auto type, semicolon found!"); } else ttd = BasicType(); } else ttd = BasicType(); if (IsEOF) { /* * T! -- tix.Arguments == null * T!(int, -- last argument == null * T!(int, bool, -- ditto * T!(int) -- now every argument is complete */ var tix=ttd as TemplateInstanceExpression; if (tix != null) { if (tix.Arguments == null || tix.Arguments.Length == 0 || (tix.Arguments [tix.Arguments.Length - 1] is TokenExpression && (tix.Arguments [tix.Arguments.Length - 1] as TokenExpression).Token == DTokens.INVALID)) { LastParsedObject = ttd; return null; } } else if (ttd is MemberFunctionAttributeDecl && (ttd as MemberFunctionAttributeDecl).InnerType == null) { LastParsedObject = ttd; return null; } } // Declarators var firstNode = Declarator(ttd,false, Scope); if (firstNode == null) return null; firstNode.Description = initialComment; firstNode.Location = startLocation; // Check for declaration constraints if (laKind == (If)) Constraint(firstNode); // BasicType Declarators ; if (laKind==Assign || laKind==Comma || laKind==Semicolon) { // DeclaratorInitializer if (laKind == (Assign)) { TrackerVariables.InitializedNode = firstNode; var dv = firstNode as DVariable; if(dv!=null) dv.Initializer = Initializer(Scope); } firstNode.EndLocation = t.EndLocation; var ret = new List<INode>(); ret.Add(firstNode); // DeclaratorIdentifierList while (laKind == Comma) { Step(); if (Expect(Identifier)) { var otherNode = new DVariable(); LastParsedObject = otherNode; /// Note: In DDoc, all declarations that are made at once (e.g. int a,b,c;) get the same pre-declaration-description! otherNode.Description = initialComment; otherNode.AssignFrom(firstNode); otherNode.Location = t.Location; otherNode.Name = t.Value; otherNode.NameLocation = t.Location; if (laKind == (Assign)) { TrackerVariables.InitializedNode = otherNode; otherNode.Initializer = Initializer(Scope); } otherNode.EndLocation = t.EndLocation; ret.Add(otherNode); } else break; } if (Expect(Semicolon)) LastParsedObject = null; // Note: In DDoc, only the really last declaration will get the post semicolon comment appended if (ret.Count > 0) ret[ret.Count - 1].Description += CheckForPostSemicolonComment(); return ret; } // BasicType Declarator FunctionBody else if (firstNode is DMethod && (IsFunctionBody || IsEOF)) { firstNode.Description += CheckForPostSemicolonComment(); FunctionBody((DMethod)firstNode); firstNode.Description += CheckForPostSemicolonComment(); var ret = new List<INode> (); ret.Add (firstNode); return ret; } else SynErr(OpenCurlyBrace, "; or function body expected after declaration stub."); return null; }
DVariable AliasThisDeclaration(DVariable initiallyParsedNode, IBlockNode Scope) { var dv = new DVariable { Description = initiallyParsedNode.Description, Location=t.Location, IsAlias=true, IsAliasThis = true, NameHash = DVariable.AliasThisIdentifierHash, Parent = Scope, Attributes = initiallyParsedNode.Attributes }; LastParsedObject = dv; if(!(Scope is DClassLike)) SemErr(DTokens.This, "alias this declarations are only allowed in structs and classes!"); // alias this = Identifier if(laKind == This && Lexer.CurrentPeekToken.Kind == Assign) { Step(); // Step beyond 'this' dv.NameLocation=t.Location; Step(); // Step beyond '=' if(Expect(Identifier)) { dv.Type= new IdentifierDeclaration(t.Value) { Location = t.Location, EndLocation = t.EndLocation }; } } else { Step(); // Step beyond Identifier dv.Type = new IdentifierDeclaration(t.Value) { Location=dv.NameLocation =t.Location, EndLocation=t.EndLocation }; Step(); // Step beyond 'this' dv.NameLocation=t.Location; } dv.EndLocation = t.EndLocation; Expect(Semicolon); dv.Description += CheckForPostSemicolonComment(); return dv; }
INode[] AliasDeclaration(IBlockNode Scope, bool HasStorageClassModifiers) { Step(); // _t is just a synthetic node which holds possible following attributes var _t = new DVariable(); ApplyAttributes(_t); _t.Description = GetComments(); List<INode> decls; // AliasThis if ((laKind == Identifier && Lexer.CurrentPeekToken.Kind == This) || (laKind == This && Lexer.CurrentPeekToken.Kind == Assign)) return new[]{AliasThisDeclaration(_t, Scope)}; // AliasInitializerList else if(laKind == Identifier && Lexer.CurrentPeekToken.Kind == Assign) { decls = new List<INode>(); do{ if(laKind == Comma) Step(); if(!Expect(Identifier)) break; var dv = new DVariable{ IsAlias = true, Attributes = _t.Attributes, Description = _t.Description, Name = t.Value, NameLocation = t.Location, Location = t.Location, Parent = Scope }; if(Expect(Assign)) { Lexer.PushLookAheadBackup(); dv.Type = Type(); if(!(laKind == Comma || laKind == Semicolon)) { Lexer.RestoreLookAheadBackup(); dv.Initializer = AssignExpression(Scope); } else Lexer.PopLookAheadBackup(); } decls.Add(dv); } while(laKind == Comma); Expect(Semicolon); decls[decls.Count-1].Description += CheckForPostSemicolonComment(); return decls.ToArray(); } // alias BasicType Declarator decls=Decl(HasStorageClassModifiers,Scope, laKind != Identifier || Lexer.CurrentPeekToken.Kind != OpenParenthesis ? null : new Modifier(DTokens.Alias)); if(decls!=null){ foreach (var n in decls) if (n is DVariable){ ((DNode)n).Attributes.AddRange(_t.Attributes); ((DVariable)n).IsAlias = true; } decls[decls.Count-1].Description += CheckForPostSemicolonComment(); return decls.ToArray (); } return null; }
private INode[] EnumDeclaration(INode Parent) { Expect(Enum); var ret = new List<INode>(); var mye = new DEnum() { Location = t.Location, Description = GetComments(), Parent=Parent }; LastParsedObject = mye; ApplyAttributes(mye); if (laKind != Identifier && IsBasicType()) mye.Type = Type(); else if (laKind == Auto) { Step(); mye.Attributes.Add(new Modifier(Auto)); } if (laKind == (Identifier)) { // Normal enum identifier if (Lexer.CurrentPeekToken.Kind == (Assign) || // enum e = 1234; Lexer.CurrentPeekToken.Kind == (OpenCurlyBrace) || // enum e { A,B,C, } Lexer.CurrentPeekToken.Kind == (Semicolon) || // enum e; Lexer.CurrentPeekToken.Kind == Colon) { // enum e : uint {..} Step (); mye.Name = t.Value; mye.NameLocation = t.Location; } else { if (mye.Type == null) mye.Type = Type(); if (Expect(Identifier)) { mye.Name = t.Value; mye.NameLocation = t.Location; } } } else if (IsEOF) ExpectingNodeName = true; if (IsDeclaratorSuffix) { DeclaratorSuffixes(mye); } // Enum inhertance type if (laKind == (Colon)) { Step(); mye.Type = Type(); } // Variables with 'enum' as base type if (laKind == (Assign) || laKind == (Semicolon)) { do { var enumVar = new DVariable(); LastParsedObject = enumVar; enumVar.AssignFrom(mye); enumVar.Attributes.Add(new Modifier(Enum)); if (mye.Type != null) enumVar.Type = mye.Type; else enumVar.Type = new DTokenDeclaration(Enum); if (laKind == (Comma)) { Step(); Expect(Identifier); enumVar.Name = t.Value; enumVar.NameLocation = t.Location; } if (laKind == (Assign)) { //Step(); -- expected by initializer enumVar.Initializer = Initializer(); // Seems to be specified wrongly - theoretically there must be an AssignExpression(); } enumVar.EndLocation = t.Location; ret.Add(enumVar); } while (laKind == Comma); Expect(Semicolon); } else if (laKind == OpenCurlyBrace) // Normal enum block { EnumBody(mye); ret.Add(mye); } mye.Description += CheckForPostSemicolonComment(); return ret.ToArray(); }
public override void Visit(DVariable n) { FormatAttributedNode(n, n.NameLocation != n.Location); if(n.Type != null) n.Type.Accept(this); if(!n.NameLocation.IsEmpty) { // Check if we're inside a multi-declaration like int a,b,c; var lastNonWs = SearchWhitespaceStart(document.ToOffset(n.NameLocation)) - 1; if(lastNonWs > 0 && document[lastNonWs] == ','){ switch(policy.MultiVariableDeclPlacement) { case NewLinePlacement.NewLine: curIndent.Push(IndentType.Continuation); FixIndentationForceNewLine(n.NameLocation); curIndent.Pop(); break; case NewLinePlacement.SameLine: ForceSpacesBeforeRemoveNewLines(n.NameLocation, true); break; } } else{ if(policy.ForceNodeNameOnSameLine) ForceSpacesBeforeRemoveNewLines(n.NameLocation, true); } if(n.Initializer != null) { // place '=' token ForceSpacesAfterRemoveLines(new CodeLocation(n.NameLocation.Column+n.Name.Length,n.NameLocation.Line),true); if(policy.ForceVarInitializerOnSameLine) { ForceSpacesBeforeRemoveNewLines(n.Initializer.Location,true); n.Initializer.Accept(this); } else { curIndent.Push(IndentType.Block); if (n.NameLocation.Line != n.Initializer.Location.Line) { FixStatementIndentation(n.Initializer.Location); } n.Initializer.Accept(this); curIndent.Pop (); } } } }
ForeachStatement ForeachStatement(IBlockNode Scope,IStatement Parent) { Step(); var dbs = new ForeachStatement() { Location = t.Location, IsReverse = t.Kind == Foreach_Reverse, Parent = Parent }; LastParsedObject = dbs; if(!Expect(OpenParenthesis)) return dbs; var tl = new List<DVariable>(); bool init=true; while(init || laKind == Comma) { if (init) init = false; else Step(); var forEachVar = new DVariable{ Parent = Scope }; forEachVar.Location = la.Location; if (laKind == Ref || laKind == InOut) { Step(); if(forEachVar.Attributes == null) forEachVar.Attributes = new List<DAttribute>(); forEachVar.Attributes.Add(new Modifier(t.Kind)); } if(IsEOF){ TrackerVariables.ExpectingIdentifier = true; SynErr(t.Kind,"Basic type or iteration variable identifier expected."); return dbs; } LastParsedObject = forEachVar; if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Semicolon) || Lexer.CurrentPeekToken.Kind == Comma)) { Step(); forEachVar.NameLocation = t.Location; forEachVar.Name = t.Value; } else { var type = BasicType(); var tnode = Declarator(type, false, Scope); if (tnode == null) break; if(forEachVar.Attributes != null) if(tnode.Attributes == null) tnode.Attributes = new List<DAttribute>(forEachVar.Attributes); else tnode.Attributes.AddRange(forEachVar.Attributes); tnode.Location = forEachVar.Location; forEachVar = (DVariable)tnode; } forEachVar.EndLocation = t.EndLocation; tl.Add(forEachVar); } dbs.ForeachTypeList = tl.ToArray(); if(Expect(Semicolon)) dbs.Aggregate = Expression(Scope); // ForeachRangeStatement if (laKind == DoubleDot) { Step(); dbs.UpperAggregate = Expression(); } if(Expect(CloseParenthesis)) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; }
public IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null) { if (EmptyAllowed && laKind == Semicolon) { LastParsedObject = null; Step(); return null; } if (BlocksAllowed && laKind == OpenCurlyBrace) return BlockStatement(Scope,Parent); #region LabeledStatement (loc:... goto loc;) if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon) { Step(); var ret = new LabeledStatement() { Location = t.Location, Identifier = t.Value, Parent = Parent }; LastParsedObject = null; Step(); ret.EndLocation = t.EndLocation; return ret; } #endregion #region IfStatement else if (laKind == (If)) { Step(); var dbs = new IfStatement{ Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // IfCondition IfCondition(dbs); // ThenStatement if(Expect(CloseParenthesis)) dbs.ThenStatement = Statement(Scope: Scope, Parent: dbs); // ElseStatement if (laKind == (Else)) { Step(); dbs.ElseStatement = Statement(Scope: Scope, Parent: dbs); } if(t != null) dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Conditions else if ((laKind == Static && Lexer.CurrentPeekToken.Kind == If) || laKind == Version || laKind == Debug) return StmtCondition(Parent, Scope); #endregion #region WhileStatement else if (laKind == While) { Step(); var dbs = new WhileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) { dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; } return dbs; } #endregion #region DoStatement else if (laKind == (Do)) { Step(); var dbs = new WhileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if(!IsEOF) dbs.ScopedStatement = Statement(true, false, Scope, dbs); if(Expect(While) && Expect(OpenParenthesis)) { dbs.Condition = Expression(Scope); Expect(CloseParenthesis); if (Expect(Semicolon)) LastParsedObject = null; dbs.EndLocation = t.EndLocation; } return dbs; } #endregion #region ForStatement else if (laKind == (For)) return ForStatement(Scope, Parent); #endregion #region ForeachStatement else if (laKind == Foreach || laKind == Foreach_Reverse) return ForeachStatement(Scope, Parent); #endregion #region [Final] SwitchStatement else if ((laKind == (Final) && Lexer.CurrentPeekToken.Kind == (Switch)) || laKind == (Switch)) { var dbs = new SwitchStatement { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (Final)) { dbs.IsFinal = true; Step(); } Step(); Expect(OpenParenthesis); dbs.SwitchExpression = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region CaseStatement else if (laKind == (Case)) { Step(); var dbs = new SwitchStatement.CaseStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ArgumentList = Expression(Scope); if (Expect(Colon)) LastParsedObject = null; // CaseRangeStatement if (laKind == DoubleDot) { Step(); Expect(Case); dbs.LastExpression = AssignExpression(); if (Expect(Colon)) LastParsedObject = null; } var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Default else if (laKind == (Default)) { Step(); var dbs = new SwitchStatement.DefaultStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = dbs; Expect(Colon); var sl = new List<IStatement>(); while (laKind != Case && laKind != Default && laKind != CloseCurlyBrace && !IsEOF) { var stmt = Statement(Scope: Scope, Parent: dbs); if (stmt != null) { stmt.Parent = dbs; sl.Add(stmt); } } dbs.ScopeStatementList = sl.ToArray(); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region Continue | Break else if (laKind == (Continue)) { Step(); var s = new ContinueStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } else if (laKind == (Break)) { Step(); var s = new BreakStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } #endregion #region Return else if (laKind == (Return)) { Step(); var s = new ReturnStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind != (Semicolon)) s.ReturnExpression = Expression(Scope); if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } #endregion #region Goto else if (laKind == (Goto)) { Step(); var s = new GotoStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Identifier; s.LabelIdentifier = t.Value; } else if (laKind == Default) { Step(); s.StmtType = GotoStatement.GotoStmtType.Default; } else if (laKind == (Case)) { Step(); s.StmtType = GotoStatement.GotoStmtType.Case; if (laKind != (Semicolon)) s.CaseExpression = Expression(Scope); } if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } #endregion #region WithStatement else if (laKind == (With)) { Step(); var dbs = new WithStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if(Expect(OpenParenthesis)) { // Symbol dbs.WithExpression = Expression(Scope); Expect(CloseParenthesis); if(!IsEOF) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); } dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region SynchronizedStatement else if (laKind == (Synchronized)) { Step(); var dbs = new SynchronizedStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (OpenParenthesis)) { Step(); dbs.SyncExpression = Expression(Scope); Expect(CloseParenthesis); } if(!IsEOF) dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region TryStatement else if (laKind == (Try)) { Step(); var s = new TryStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (!(laKind == (Catch) || laKind == (Finally))) SemErr(Catch, "At least one catch or a finally block expected!"); var catches = new List<TryStatement.CatchStatement>(); // Catches while (laKind == (Catch)) { Step(); var c = new TryStatement.CatchStatement() { Location = t.Location, Parent = s }; LastParsedObject = c; // CatchParameter if (laKind == (OpenParenthesis)) { Step(); if (laKind == CloseParenthesis || IsEOF) { SemErr(CloseParenthesis, "Catch parameter expected, not ')'"); Step(); } else { var catchVar = new DVariable { Parent = Scope, Location = t.Location }; LastParsedObject = catchVar; Lexer.PushLookAheadBackup(); catchVar.Type = BasicType(); if (laKind == CloseParenthesis) { Lexer.RestoreLookAheadBackup(); catchVar.Type = new IdentifierDeclaration("Exception"); } else Lexer.PopLookAheadBackup(); if (Expect(Identifier)) { catchVar.Name = t.Value; catchVar.NameLocation = t.Location; Expect(CloseParenthesis); } else if(IsEOF) ExpectingNodeName = true; catchVar.EndLocation = t.EndLocation; c.CatchParameter = catchVar; } } if(!IsEOF) c.ScopedStatement = Statement(Scope: Scope, Parent: c); c.EndLocation = t.EndLocation; catches.Add(c); } if (catches.Count > 0) s.Catches = catches.ToArray(); if (laKind == (Finally)) { Step(); var f = new TryStatement.FinallyStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = f; f.ScopedStatement = Statement(); f.EndLocation = t.EndLocation; s.FinallyStmt = f; } s.EndLocation = t.EndLocation; return s; } #endregion #region ThrowStatement else if (laKind == (Throw)) { Step(); var s = new ThrowStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ThrowExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region ScopeGuardStatement else if (laKind == DTokens.Scope) { Step(); if (laKind == OpenParenthesis) { var s = new ScopeGuardStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; Step(); if (Expect(Identifier) && t.Value != null) // exit, failure, success s.GuardedScope = t.Value.ToLower(); if (Expect(CloseParenthesis)) TrackerVariables.ExpectingIdentifier = false; if (!IsEOF) s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } else PushAttribute(new Modifier(DTokens.Scope), false); } #endregion #region AsmStmt else if (laKind == Asm) return AsmStatement(Parent); #endregion #region PragmaStatement else if (laKind == (Pragma)) { var s = new PragmaStatement { Location = la.Location }; s.Pragma = _Pragma(); s.Parent = Parent; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region MixinStatement else if (laKind == (Mixin)) { if (Peek(1).Kind == OpenParenthesis) { OverPeekBrackets(OpenParenthesis); if (Lexer.CurrentPeekToken.Kind != Semicolon) return ExpressionStatement(Scope, Parent); return MixinDeclaration(Scope, Parent); } else { var tmx = TemplateMixin(Scope, Parent); if (tmx.MixinId == null) return tmx; else return new DeclarationStatement { Declarations = new[] { new NamedTemplateMixinNode(tmx) }, Parent = Parent }; } } #endregion #region (Static) AssertExpression else if (laKind == Assert || (laKind == Static && Lexer.CurrentPeekToken.Kind == Assert)) { var isStatic = laKind == Static; AssertStatement s; if (isStatic) { Step(); s = new StaticAssertStatement { Location = la.Location, Parent = Parent }; } else s = new AssertStatement() { Location = la.Location, Parent = Parent }; LastParsedObject = s; Step(); if (Expect(OpenParenthesis)) { s.AssertedExpression = Expression(Scope); if(Expect(CloseParenthesis) && Expect(Semicolon)) LastParsedObject = null; } s.EndLocation = t.EndLocation; return s; } #endregion #region D1: VolatileStatement else if (laKind == Volatile) { Step(); var s = new VolatileStatement() { Location = t.Location, Parent = Parent }; LastParsedObject = s; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion // ImportDeclaration else if (laKind == Import || (laKind == Static && Lexer.CurrentPeekToken.Kind == Import)) { if(laKind == Static) Step(); // Will be handled in ImportDeclaration return ImportDeclaration(Scope); } else if (!(ClassLike[laKind] || BasicTypes[laKind] || laKind == Enum || Modifiers[laKind] || IsAtAttribute || laKind == Alias || laKind == Typedef) && IsAssignExpression()) return ExpressionStatement(Scope, Parent); var ds = new DeclarationStatement() { Location = la.Location, Parent = Parent, ParentNode = Scope }; LastParsedObject = ds; ds.Declarations = Declaration(Scope); ds.EndLocation = t.EndLocation; return ds; }
public override ISymbolValue this[DVariable n] { get { if (n == null){ return new ErrorValue(new EvaluationException("There must be a valid variable node given in order to retrieve its value")); } if (n.IsConst) { if(varsBeingResolved.Contains(n)){ return new ErrorValue(new EvaluationException("Cannot reference itself")); } varsBeingResolved.Add(n); // .. resolve it's pre-compile time value and make the returned value the given argument ISymbolValue val; try{ val = Evaluation.EvaluateValue(n.Initializer,this); } finally{ varsBeingResolved.Remove(n); } // If it's null, then the initializer is null - which is equal to e.g. 0 or null !; if (val != null) return val; } return new ErrorValue(new EvaluationException(n+" must have a constant initializer")); } set { throw new NotImplementedException(); } }
FunctionLiteral LambaExpression(IBlockNode Scope=null) { var fl = new FunctionLiteral(true); fl.Location = fl.AnonymousMethod.Location = la.Location; if(laKind == Function || laKind == Delegate) { fl.LiteralToken = laKind; Step(); } if (laKind == Identifier) { Step(); var p = new DVariable { Name = t.Value, Location = t.Location, EndLocation = t.EndLocation, Attributes = new List<DAttribute>{new Modifier(Auto)} }; fl.AnonymousMethod.Parameters.Add(p); } else if (laKind == OpenParenthesis) fl.AnonymousMethod.Parameters = Parameters(fl.AnonymousMethod); if (Expect(GoesTo)) { if (laKind == OpenCurlyBrace) fl.AnonymousMethod.Body = BlockStatement (fl.AnonymousMethod); else LambdaSingleStatementBody (fl.AnonymousMethod); } fl.EndLocation = fl.AnonymousMethod.EndLocation = t.EndLocation; if (Scope != null) Scope.Add(fl.AnonymousMethod); return fl; }
/// <summary> /// Parse parameters /// </summary> List<INode> Parameters(DMethod Parent) { var ret = new List<INode>(); Expect(OpenParenthesis); // Empty parameter list if (laKind == (CloseParenthesis)) { Step(); return ret; } var stk_backup = BlockAttributes; BlockAttributes = new Stack<DAttribute>(); DNode p; if (laKind != TripleDot && (p = Parameter(Parent)) != null) { p.Parent = Parent; ret.Add(p); } while (laKind == (Comma)) { Step(); if (laKind == TripleDot || laKind==CloseParenthesis || (p = Parameter(Parent)) == null) break; p.Parent = Parent; ret.Add(p); } // It's not specified in the official D syntax spec, but we treat id-only typed anonymous parameters as non-typed id-full parameters if(Parent != null && Parent.SpecialType == DMethod.MethodType.AnonymousDelegate) { foreach(var r in ret) if (r.NameHash == 0 && r.Type is IdentifierDeclaration && r.Type.InnerDeclaration == null) { r.NameHash = (r.Type as IdentifierDeclaration).IdHash; r.Type = null; } } /* * There can be only one '...' in every parameter list */ if (laKind == TripleDot) { // If it doesn't have a comma, add a VarArgDecl to the last parameter bool HadComma = t.Kind == (Comma); Step(); if (!HadComma && ret.Count > 0) { // Put a VarArgDecl around the type of the last parameter ret[ret.Count - 1].Type = new VarArgDecl(ret[ret.Count - 1].Type); } else { var dv = new DVariable(); LastParsedObject = dv; dv.Type = new VarArgDecl(); dv.Parent = Parent; ret.Add(dv); } } Expect(CloseParenthesis); BlockAttributes = stk_backup; return ret; }
/// <summary> /// string[] s; /// /// foreach(i;s) /// { /// // i is of type 'string' /// writeln(i); /// } /// </summary> public AbstractType GetForeachIteratorType(DVariable i) { var r = new List <AbstractType>(); var curStmt = ctxt.ScopedStatement; bool init = true; // Walk up statement hierarchy -- note that foreach loops can be nested while (curStmt != null) { if (init) { init = false; } else { curStmt = curStmt.Parent; } if (curStmt is ForeachStatement) { var fe = (ForeachStatement)curStmt; if (fe.ForeachTypeList == null) { continue; } // If the searched variable is declared in the header int iteratorIndex = -1; for (int j = 0; j < fe.ForeachTypeList.Length; j++) { if (fe.ForeachTypeList[j] == i) { iteratorIndex = j; break; } } if (iteratorIndex == -1) { continue; } bool keyIsSearched = iteratorIndex == 0 && fe.ForeachTypeList.Length > 1; // foreach(var k, var v; 0 .. 9) if (keyIsSearched && fe.IsRangeStatement) { // -- it's static type int, of course(?) return(new PrimitiveType(DTokens.Int)); } var aggregateType = ExpressionTypeEvaluation.EvaluateType(fe.Aggregate, ctxt); aggregateType = DResolver.StripMemberSymbols(aggregateType); if (aggregateType == null) { return(null); } // The most common way to do a foreach if (aggregateType is AssocArrayType) { var ar = (AssocArrayType)aggregateType; return(keyIsSearched ? ar.KeyType : ar.ValueType); } else if (aggregateType is UserDefinedType) { var tr = (UserDefinedType)aggregateType; if (keyIsSearched || !(tr.Definition is IBlockNode)) { continue; } bool foundIterPropertyMatch = false; #region Foreach over Structs and Classes with Ranges // Enlist all 'back'/'front' members var t_l = new List <AbstractType>(); foreach (var n in (IBlockNode)tr.Definition) { if (fe.IsReverse ? n.Name == "back" : n.Name == "front") { t_l.Add(HandleNodeMatch(n, ctxt)); } } // Remove aliases var iterPropertyTypes = DResolver.StripAliasSymbols(t_l); foreach (var iterPropType in iterPropertyTypes) { if (iterPropType is MemberSymbol) { foundIterPropertyMatch = true; var itp = (MemberSymbol)iterPropType; // Only take non-parameterized methods if (itp.Definition is DMethod && ((DMethod)itp.Definition).Parameters.Count != 0) { continue; } // Handle its base type [return type] as iterator type if (itp.Base != null) { r.Add(itp.Base); } foundIterPropertyMatch = true; } } if (foundIterPropertyMatch) { continue; } #endregion #region Foreach over Structs and Classes with opApply t_l.Clear(); r.Clear(); foreach (var n in (IBlockNode)tr.Definition) { if (n is DMethod && (fe.IsReverse ? n.Name == "opApplyReverse" : n.Name == "opApply")) { t_l.Add(HandleNodeMatch(n, ctxt)); } } iterPropertyTypes = DResolver.StripAliasSymbols(t_l); foreach (var iterPropertyType in iterPropertyTypes) { if (iterPropertyType is MemberSymbol) { var mr = (MemberSymbol)iterPropertyType; var dm = mr.Definition as DMethod; if (dm == null || dm.Parameters.Count != 1) { continue; } var dg = dm.Parameters[0].Type as DelegateDeclaration; if (dg == null || dg.Parameters.Count != fe.ForeachTypeList.Length) { continue; } var paramType = Resolve(dg.Parameters[iteratorIndex].Type, ctxt); if (paramType != null && paramType.Length > 0) { r.Add(paramType[0]); } } } #endregion } if (r.Count > 1) { ctxt.LogError(new ResolutionError(curStmt, "Ambigous iterator type")); } return(r.Count != 0 ? r[0] : null); } } return(null); }
protected void SerializeDNode(DNode node, StringBuilder sb, int level) { StringBuilder indent = new StringBuilder(); for (int i = 0; i < level; i++) { indent.Append('\t'); } SerializeCodeLocation(node.StartLocation, sb); sb.Append("-"); SerializeCodeLocation(node.EndLocation, sb); sb.Append(" "); if (node is DModule) { DModule module = node as DModule; sb.Append(indent).Append("ML:").Append(module.ModuleName); foreach (ITypeDeclaration td in module.Imports.Keys) { sb.Append(indent).Append("~IM:").Append(td.ToString()); } sb.AppendLine(); } else if (node is DMethod) { DMethod method = node as DMethod; sb.Append(indent).Append("MD:").Append(method.Type != null ? method.Type.ToString() : "<NULL>").Append("~").AppendLine(method.Name); foreach (DNode paramNode in method.Parameters) { SerializeDNode(paramNode, sb, level + 1); } } else if (node is DClassLike) { DClassLike clss = node as DClassLike; sb.Append(indent).Append("CLS:").Append(clss.ClassType).Append("~").AppendLine(clss.Name); } else if (node is DVariable) { DVariable variable = node as DVariable; sb.Append(indent).Append("VAR:").Append((variable.Type == null) ? "<NULL>" : variable.Type.ToString()).Append("~").Append(variable.Name); if (variable.Initializer != null) { sb.Append(indent).Append("~INIT:").Append(variable.Initializer.ToString()); } sb.AppendLine(); } else { object o = node; } if (node is DStatementBlock) { DStatementBlock block = node as DStatementBlock; //if (block.Expression != null) // sb.Append(indent).Append("EXP:").Append(block.Expression.ToString()); foreach (DNode childNode in block) { SerializeDNode(childNode, sb, level + 1); } } else if (node is DBlockStatement) { DBlockStatement block = node as DBlockStatement; foreach (DNode childNode in block.Children) { SerializeDNode(childNode, sb, level + 1); } } }
/// <summary> /// http://www.digitalmars.com/d/2.0/declaration.html#Declarator2 /// The next bug: Following the definition strictly, this function would end up in an endless loop of requesting another Declarator2 /// /// So here I think that a Declarator2 only consists of a couple of BasicType2's and some DeclaratorSuffixes /// </summary> /// <returns></returns> ITypeDeclaration Declarator2() { ITypeDeclaration td = null; if (laKind == (OpenParenthesis)) { Step(); td = Declarator2(); if (AllowWeakTypeParsing && (td == null||(t.Kind==OpenParenthesis && laKind==CloseParenthesis) /* -- means if an argumentless function call has been made, return null because this would be an expression */|| laKind!=CloseParenthesis)) return null; Expect(CloseParenthesis); // DeclaratorSuffixes if (laKind == (OpenSquareBracket)) { var dn = new DVariable(); dn.Type = td; DeclaratorSuffixes(dn); td = dn.Type; if(dn.Attributes!= null && dn.Attributes.Count != 0) foreach(var attr in dn.Attributes) DeclarationAttributes.Push(attr); } return td; } while (IsBasicType2()) { var ttd = BasicType2(); if (AllowWeakTypeParsing && ttd == null) return null; if(ttd!=null) ttd.InnerDeclaration = td; td = ttd; } return td; }
public virtual void Visit(DVariable n) { if (n.Initializer != null) n.Initializer.Accept(this); VisitDNode(n); }
/// <summary> /// Parses a type declarator /// </summary> /// <returns>A dummy node that contains the return type, the variable name and possible parameters of a function declaration</returns> DNode Declarator(ITypeDeclaration basicType,bool IsParam, INode parent) { DNode ret = new DVariable() { Type=basicType, Location = la.Location, Parent = parent }; ApplyAttributes (ret); LastParsedObject = ret; while (IsBasicType2()) { if (ret.Type == null) ret.Type = BasicType2(); else { var ttd = BasicType2(); if(ttd!=null) ttd.InnerDeclaration = ret.Type; ret.Type = ttd; } } // Only return no variable if the BasicType2 wasn't parsed properly to ensure good code completion if (IsEOF && ret != LastParsedObject) return null; if (laKind != (OpenParenthesis)) { // On external function declarations, no parameter names are required. // extern void Cfoo(HANDLE,char**); if (IsParam && laKind != (Identifier)) { if(ret.Type!=null && IsEOF) ExpectingNodeName = true; return ret; } if (Expect(Identifier)) { ret.Name = t.Value; ret.NameLocation = t.Location; if (laKind == OpenParenthesis && ret.Type == null) { OverPeekBrackets (DTokens.OpenParenthesis, true); var k = Lexer.LastToken.Kind; if (k == DTokens.Alias || k == DTokens.Enum) { if (ret.Attributes == null) ret.Attributes = new List<DAttribute> (); ret.Attributes.Add (new Modifier (k)); } // enum asdf(...) = ...; if (Lexer.CurrentPeekToken.Kind == Assign) { var eponymousTemplateDecl = new EponymousTemplate (); eponymousTemplateDecl.AssignFrom (ret); ret = eponymousTemplateDecl; TemplateParameterList (eponymousTemplateDecl); return ret; } } } else { if (IsEOF || IsParam) { ExpectingNodeName = true; return ret; } return null; // Code error! - to prevent infinite declaration loops, step one token forward anyway! if(laKind != CloseCurlyBrace && laKind != CloseParenthesis) Step(); return null; } } else OldCStyleFunctionPointer(ret, IsParam); if (IsDeclaratorSuffix || IsFunctionAttribute) { var dm = new DMethod { Parent = parent, Parameters = null }; dm.AssignFrom(ret); LastParsedObject = dm; DeclaratorSuffixes(dm); if (dm.Parameters != null) ret = dm; else LastParsedObject = ret; } return ret; }
DVariable Argument(ref char c, out AbstractType parType) { bool scoped; if(scoped = (c == 'M')) c = (char)r.Read(); //TODO: Handle scoped var par = new DVariable{ Attributes = new List<DAttribute>() }; if(c == 'J' || c == 'K' ||c == 'L') { if(c == 'J') par.Attributes.Add(new Modifier(DTokens.Out)); else if(c == 'K') par.Attributes.Add(new Modifier(DTokens.Ref)); else if(c == 'L') par.Attributes.Add(new Modifier(DTokens.Lazy)); c = (char)r.Read(); } parType = Type(c); par.Type = parType.TypeDeclarationOf; return par; }
INode Constructor(DBlockNode scope,bool IsStruct) { Expect(This); var dm = new DMethod(){ Parent = scope, SpecialType = DMethod.MethodType.Constructor, Location = t.Location, Name = DMethod.ConstructorIdentifier, NameLocation = t.Location }; dm.Description = GetComments(); LastParsedObject = dm; if (IsTemplateParameterList()) TemplateParameterList(dm); // http://dlang.org/struct.html#StructPostblit if (IsStruct && laKind == (OpenParenthesis) && Peek(1).Kind == (This)) { var dv = new DVariable(); LastParsedObject = dv; dv.Parent = dm; dv.Name = "this"; dm.Parameters.Add(dv); Step(); Step(); Expect(CloseParenthesis); } else { dm.Parameters = Parameters(dm); } // handle post argument attributes FunctionAttributes(dm); if (!IsEOF) LastParsedObject = dm; if (laKind == If) Constraint(dm); // handle post argument attributes FunctionAttributes(dm); if(IsFunctionBody) FunctionBody(dm); return dm; }