public virtual void Visit(DMethod n) { VisitDNode(n); if (n.Parameters != null) { foreach (var par in n.Parameters) { par.Accept(this); } } if (n.In != null) { n.In.Accept(this); } if (n.Body != null) { n.Body.Accept(this); } if (n.Out != null) { n.Out.Accept(this); } if (n.OutResultVariable != null) { n.OutResultVariable.Accept(this); } }
public override void Visit(DMethod dm) { var back = ctxt.ScopedBlock; using (ctxt.Push(dm)) { if (back != ctxt.ScopedBlock) OnScopedBlockChanged(dm); base.Visit(dm); } }
public static TooltipInformation Generate(DMethod dm, bool isTemplateParamInsight=false, int currentParam=-1) { var tti = new TooltipInformation(); var sb = new StringBuilder(); sb.Append ("<i>("); string name; switch (dm.SpecialType) { case DMethod.MethodType.Constructor: sb.Append ("Constructor"); name = dm.Parent.Name; break; case DMethod.MethodType.Destructor: sb.Append ("Destructor"); name = dm.Parent.Name; break; case DMethod.MethodType.Allocator: sb.Append ("Allocator"); name = dm.Parent.Name; break; default: sb.Append ("Method"); name = dm.Name; break; } sb.Append (")</i> "); if (dm.Type != null) { sb.Append(dm.Type.ToString(true)); sb.Append(" "); } else if (dm.Attributes != null && dm.Attributes.Count != 0) { foreach (var attr in dm.Attributes) { var m = attr as Modifier; if (m != null && DTokens.StorageClass[m.Token]) { sb.Append(DTokens.GetTokenString(m.Token)); sb.Append(" "); break; } } } sb.Append(name); /*TODO: Show attributes? if (dm.Attributes != null && dm.Attributes.Count > 0) s = dm.AttributeString + ' '; */ RenderParamtersAndFooters (tti, dm, sb, isTemplateParamInsight, currentParam); return tti; }
public override void Visit(DMethod dm) { var back = ctxt.ScopedBlock; if (back != dm) { ctxt.PushNewScope (dm); OnScopedBlockChanged (dm); } base.Visit (dm); if(back != dm) ctxt.Pop (); }
public override void Visit(DMethod n) { // Format header FormatAttributedNode(n, !n.IsAnonymous && n.Type != null); VisitDNode(n); // Stick name to type if(n.Type != null) ForceSpacesBeforeRemoveNewLines(n.NameLocation, true); // Put parenthesis '(' token directly after the name var nameLength = 0; switch(n.SpecialType) { case DMethod.MethodType.Destructor: case DMethod.MethodType.Constructor: nameLength = 4; // this break; case DMethod.MethodType.Normal: nameLength = n.Name.Length; break; } if(nameLength > 0) ForceSpacesAfterRemoveLines(new CodeLocation(n.NameLocation.Column + nameLength, n.NameLocation.Line),false); // Format parameters // Find in, out(...) and body tokens if(!n.InToken.IsEmpty){ FixIndentationForceNewLine(n.InToken); } if(!n.OutToken.IsEmpty){ FixIndentationForceNewLine(n.OutToken); } if(!n.BodyToken.IsEmpty){ FixIndentationForceNewLine(n.BodyToken); } // Visit body parts if (n.In != null) n.In.Accept (this); if (n.Body != null) n.Body.Accept (this); if (n.Out != null) n.Out.Accept (this); if (!n.IsAnonymous) EnsureBlankLinesAfter (n.EndLocation, policy.LinesAfterNode); }
public virtual void Visit(DMethod n) { VisitDNode(n); foreach (var par in n.Parameters) par.Accept(this); if (n.In != null) n.In.Accept(this); if (n.Body != null) n.Body.Accept(this); if (n.Out != null) n.Out.Accept(this); if (n.OutResultVariable != null) n.OutResultVariable.Accept(this); }
/// <summary> /// /// </summary> /// <param name="dm"></param> /// <param name="args"></param> /// <param name="baseValueProvider">Required for evaluating missing default parameters.</param> public static bool AssignCallArgumentsToIC(DMethod dm, ISymbolValue[] args, AbstractSymbolValueProvider baseValueProvider, out Dictionary<DVariable,ISymbolValue> targetArgs) { targetArgs = new Dictionary<DVariable, ISymbolValue>(); var argsRemaining = args != null ? args.Length : 0; int argu = 0; for (int para = 0; para < dm.Parameters.Count; para++) { var par = dm.Parameters[para] as DVariable; if (par.Type is VarArgDecl && argsRemaining > 0) { var va_args = new ISemantic[argsRemaining]; args.CopyTo(va_args, argu); argsRemaining=0; //TODO: Assign a value tuple to par if (++para < dm.Parameters.Count) return false; } if (argsRemaining > 0) { targetArgs[par] = args[argu++]; argsRemaining--; } else if (par.Initializer != null) { targetArgs[par] = Evaluation.EvaluateValue(par.Initializer, baseValueProvider); } else return false; } return argsRemaining == 0; }
void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null) { if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null) { var pop = ctxt.ScopedBlock != dm; if (pop) ctxt.PushNewScope (dm); var t = TypeDeclarationResolver.ResolveSingle (dm.Parameters [0].Type, ctxt); if (ResultComparer.IsImplicitlyConvertible (firstArgument, t, ctxt)) { var res = alreadyResolvedMethod ?? new MemberSymbol (dm, null, sr); res.Tag = new UfcsTag{ firstArgument=firstArgument }; matches.Add (res); } if (pop) ctxt.Pop (); } }
void DeclDef(DBlockNode module) { //AttributeSpecifier while (IsAttributeSpecifier()) { AttributeSpecifier(); if (t.Kind == Colon) return; } if (laKind == Semicolon) { LastParsedObject = null; Step(); return; } //ImportDeclaration if (laKind == Import) module.Add(ImportDeclaration()); //Constructor else if (laKind == (This)) module.Add(Constructor(module is DClassLike ? ((DClassLike)module).ClassType == DTokens.Struct : false)); //Destructor else if (laKind == (Tilde) && Lexer.CurrentPeekToken.Kind == (This)) module.Add(Destructor()); //Invariant else if (laKind == (Invariant)) module.Add(_Invariant()); //UnitTest else if (laKind == (Unittest)) { Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); LastParsedObject = dbs; dbs.Location = t.Location; FunctionBody(dbs); dbs.EndLocation = t.EndLocation; module.Add(dbs); } /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ else if ((laKind == Version || laKind == Debug) && Peek(1).Kind == Assign) { Step(); var ass = new VersionDebugSpecification { Token = t.Kind, Location = t.Location }; LastParsedObject = ass; Step(); if (laKind == Literal) { Step(); ass.SpecifiedValue = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; } else if (Expect(Identifier)) ass.SpecifiedValue = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; Expect(Semicolon); ass.EndLocation = t.EndLocation; module.Add(ass); } else if (laKind == Version || laKind == Debug || laKind == If) { Step(); var c = new DeclarationCondition(t.Kind); LastParsedObject = c; /* * http://www.d-programming-language.org/version.html#VersionSpecification * VersionCondition: * version ( IntegerLiteral ) * version ( Identifier ) * version ( unittest ) */ if (c.IsVersionCondition && Expect(OpenParenthesis)) { if (laKind == Unittest) { Step(); c.Condition = new TokenExpression(Unittest) { Location = t.Location, EndLocation = t.EndLocation }; } else if (laKind == Literal) { Step(); c.Condition = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; } else if (Expect(Identifier)) c.Condition = new IdentifierExpression(t.Value, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; if (Expect(CloseParenthesis)) TrackerVariables.ExpectingIdentifier = false; } /* * DebugCondition: * debug * debug ( IntegerLiteral ) * debug ( Identifier ) */ else if (c.IsDebugCondition) { if (laKind == OpenParenthesis) { Step(); if (laKind == Literal) { Step(); c.Condition = new IdentifierExpression(t.LiteralValue, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; } else if (Expect(Identifier)) c.Condition = new IdentifierExpression(t.Value, t.LiteralFormat) { Location = t.Location, EndLocation = t.EndLocation }; Expect(CloseParenthesis); } } /* * StaticIfCondition: * static if ( AssignExpression ) */ else if (c.IsStaticIfCondition && Expect(OpenParenthesis)) { if (DAttribute.ContainsAttribute(DeclarationAttributes, Static)) DeclarationAttributes.Clear(); else SynErr(Static, "Conditional declaration checks must be static"); c.Condition = AssignExpression(); Expect(CloseParenthesis); } if (laKind == Colon) { Step(); PushAttribute(c, true); return; } else if (laKind == OpenCurlyBrace) { BlockAttributes.Push(c); ClassBody(module, true, false); BlockAttributes.Pop(); } else { DeclarationAttributes.Push(c); DeclDef(module); } if (laKind == Else) { Step(); c = c.Clone() as DeclarationCondition; c.Negate(); if (laKind == OpenCurlyBrace) { BlockAttributes.Push(c); ClassBody(module, true, false); BlockAttributes.Pop(); } else { DeclarationAttributes.Push(c); DeclDef(module); } } } //StaticAssert else if (laKind == (Assert)) { Step(); if (DAttribute.ContainsAttribute(DeclarationAttributes, Static)) { //HACK: Assume that there's only our 'static' attribute applied to the 'if'-statement DeclarationAttributes.Clear(); } else SynErr(Static, "Static assert statements must be explicitly marked as static"); if (Expect(OpenParenthesis)) { AssignExpression(); if (laKind == (Comma)) { Step(); AssignExpression(); } Expect(CloseParenthesis); } Expect(Semicolon); } //TemplateMixinDeclaration else if (laKind == Mixin) { if (Peek(1).Kind == Template) module.Add(TemplateDeclaration(module)); //TemplateMixin else if (Lexer.CurrentPeekToken.Kind == Identifier) module.Add(TemplateMixin()); //MixinDeclaration else if (Lexer.CurrentPeekToken.Kind == OpenParenthesis) module.Add(MixinDeclaration()); else { Step(); SynErr(Identifier); } } // { else if (laKind == (OpenCurlyBrace)) { int popCount = DeclarationAttributes.Count; while (DeclarationAttributes.Count > 0) BlockAttributes.Push(DeclarationAttributes.Pop()); ClassBody(module, true, false); for (int i = popCount; i > 0; i--) BlockAttributes.Pop(); } // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) else if (laKind == (New)) { Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location=t.Location }; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // Class Deallocators else if (laKind == Delete) { Step(); var dm = new DMethod(DMethod.MethodType.Deallocator) { Location=t.Location }; dm.Name = "delete"; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // else: else module.AddRange(Declaration(module)); }
public static DMethod ParseMethodDeclarationHeader(string headerCode, out ITypeDeclaration identifierChain) { using(var sr = new StringReader(headerCode)) { var p = Create(sr); p.Step(); var n = new DMethod(); p.CheckForStorageClasses(p.doc); p.ApplyAttributes(n); p.FunctionAttributes(n); n.Type = p.Type(); identifierChain = p.IdentifierList(); if(identifierChain is IdentifierDeclaration) n.NameHash = (identifierChain as IdentifierDeclaration).IdHash; n.Parameters = p.Parameters(n); return n; } }
/// <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(); dv.Type = new VarArgDecl(); dv.Parent = Parent; ret.Add(dv); } } Expect(CloseParenthesis); BlockAttributes = stk_backup; return ret; }
public override void Visit(DMethod n) { base.Visit(n); VisitChildren(n); }
void LambdaBody(DMethod anonymousMethod) { if (Expect(GoesTo)) { if (laKind == OpenCurlyBrace) anonymousMethod.Body = BlockStatement(anonymousMethod); else { anonymousMethod.Body = new BlockStatement { Location = t.EndLocation, ParentNode = anonymousMethod }; var ae = AssignExpression(anonymousMethod); // +1 due to SearchRegionAt which is enforcing < on EndLocations and not <= var endLocation = IsEOF ? new CodeLocation(la.EndColumn + 1, la.Line) : t.EndLocation; anonymousMethod.Body.Add(new ReturnStatement { Location = ae.Location, EndLocation = endLocation, ReturnExpression = ae }); anonymousMethod.Body.EndLocation = endLocation; } anonymousMethod.EndLocation = anonymousMethod.Body.EndLocation; } else // (string | -- see IsLambdaExpression() anonymousMethod.EndLocation = la.Location; }
INode Destructor() { Expect(Tilde); var dm = new DMethod{ Location = t.Location, NameLocation = la.Location }; Expect(This); ApplyAttributes (dm); dm.SpecialType = DMethod.MethodType.Destructor; dm.Name = "~this"; if (IsTemplateParameterList()) TemplateParameterList(dm); dm.Parameters = Parameters(dm); // handle post argument attributes FunctionAttributes(dm); if (laKind == If) Constraint(dm); // handle post argument attributes FunctionAttributes(dm); FunctionBody(dm); return dm; }
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 }; ApplyAttributes (dm); dm.Description = GetComments(); if (IsTemplateParameterList()) TemplateParameterList(dm); // http://dlang.org/struct.html#StructPostblit if (IsStruct && laKind == (OpenParenthesis) && Peek(1).Kind == (This)) { var dv = new DVariable { Parent = dm, Name = "this" }; dm.Parameters.Add(dv); Step(); Step(); Expect(CloseParenthesis); } else { dm.Parameters = Parameters(dm); } // handle post argument attributes FunctionAttributes(dm); if (laKind == If) Constraint(dm); // handle post argument attributes FunctionAttributes(dm); if(IsFunctionBody) FunctionBody(dm); return dm; }
/// <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; } if (laKind != TripleDot) ret.Add(Parameter(Parent)); while (laKind == (Comma)) { Step(); if (laKind == TripleDot || laKind==CloseParenthesis) break; var p = Parameter(Parent); p.Parent = Parent; ret.Add(p); } /* * 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); return ret; }
private bool TryHandleMethodArgumentTuple(ref bool add, List<ISemantic> callArguments, DMethod dm, DeducedTypeDictionary deducedTypeDict, int currentParameter,ref int currentArg) { // .. so only check if it's an identifer & if the id represents a tuple parameter var id = dm.Parameters[currentParameter].Type as IdentifierDeclaration; var curNode = dm as DNode; TemplateParameter tpar = null; while (curNode != null && !curNode.TryGetTemplateParameter(id.IdHash, out tpar)) curNode = curNode.Parent as DNode; if (!(tpar is TemplateTupleParameter)) return false; int lastArgumentToTake = -1; /* * Note: an expression tuple parameter can occur also somewhere in between the parameter list! * void write(A...)(bool b, A a, double d) {} * * can be matched by * write(true, 1.2) as well as * write(true, "asdf", 1.2) as well as * write(true, 123, true, 'c', [3,4,5], 3.4) ! */ TemplateParameterSymbol tps; DTuple tuple = null; if (deducedTypeDict.TryGetValue(tpar, out tps) && tps != null) { if (tps.Base is DTuple) { tuple = tps.Base as DTuple; lastArgumentToTake = currentParameter + (tuple.Items == null ? 0 : (tuple.Items.Length-1)); } else { // Error: Type param must be tuple! } } // - Get the (amount of) arguments that shall be put into the tuple else if (currentParameter == dm.Parameters.Count - 1) { // The usual case: A tuple of a variable length is put at the end of a parameter list.. // take all arguments from i until the end of the argument list.. lastArgumentToTake = callArguments.Count - 1; // Also accept empty tuples.. if (callArguments.Count == 0) lastArgumentToTake = 0; } else { // Get the type of the next expected parameter var nextExpectedParameter = DResolver.StripMemberSymbols(TypeDeclarationResolver.ResolveSingle(dm.Parameters[currentParameter + 1].Type, ctxt)); // Look for the first argument whose type is equal to the next parameter's type.. for (int k = currentArg; k < callArguments.Count; k++) { if (ResultComparer.IsEqual(AbstractType.Get(callArguments[k]), nextExpectedParameter)) { // .. and assume the tuple to go from i to the previous argument.. lastArgumentToTake = k - 1; break; } } } if (lastArgumentToTake < 0) { // An error occurred somewhere.. add = false; return true; } int argCountToHandle = lastArgumentToTake - currentArg; if (argCountToHandle > 0) argCountToHandle++; if (tuple != null) { // - If there's been set an explicit type tuple, compare all arguments' types with those in the tuple if(tuple.Items != null) foreach (ISemantic item in tuple.Items) { if (currentArg >= callArguments.Count || !ResultComparer.IsImplicitlyConvertible(callArguments[currentArg++], AbstractType.Get(item), ctxt)) { add = false; return true; } } } else { // - If there was no explicit initialization, put all arguments' types into a type tuple var argsToTake = new ISemantic[argCountToHandle]; callArguments.CopyTo(currentArg, argsToTake, 0, argsToTake.Length); currentArg += argsToTake.Length; var tt = new DTuple(null, argsToTake); tps = new TemplateParameterSymbol(tpar, tt); // and set the actual template tuple parameter deduction deducedTypeDict[tpar] = tps; } add = true; return true; }
/// <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); while (IsBasicType2()) { if (ret.Type == null) ret.Type = BasicType2(); else { var ttd = BasicType2(); if(ttd!=null) ttd.InnerDeclaration = ret.Type; ret.Type = ttd; } } if (laKind != (OpenParenthesis)) { // On external function declarations, no parameter names are required. // extern void Cfoo(HANDLE,char**); if (IsParam && laKind != (Identifier)) { if ((!(ret.Type is DTokenDeclaration) || (ret.Type as DTokenDeclaration).Token != DTokens.Incomplete) && IsEOF) ret.NameHash = DTokens.IncompleteIdHash; return ret; } if (Expect(Identifier)) { ret.Name = t.Value; ret.NameLocation = t.Location; // enum asdf(...) = ...; if (laKind == OpenParenthesis && OverPeekBrackets(DTokens.OpenParenthesis, true) && Lexer.CurrentPeekToken.Kind == Assign) { var eponymousTemplateDecl = new EponymousTemplate (); eponymousTemplateDecl.AssignFrom (ret); ret = eponymousTemplateDecl; TemplateParameterList (eponymousTemplateDecl); return ret; } } else { if (IsEOF) { ret.NameHash = DTokens.IncompleteIdHash; 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); DeclaratorSuffixes(dm); if (dm.Parameters != null) ret = dm; } return ret; }
void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null) { if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null) { var loc = dm.Body != null ? dm.Body.Location : dm.Location; using (alreadyResolvedMethod != null ? ctxt.Push(alreadyResolvedMethod, loc) : ctxt.Push(dm, loc)) { var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters[0].Type, ctxt); if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt)) { var res = alreadyResolvedMethod ?? TypeDeclarationResolver.HandleNodeMatch(dm, ctxt, typeBase: sr); res.Tag(UfcsTag.Id, new UfcsTag { firstArgument = firstArgument }); matches.Add(res); } } } }
void FunctionBody(DMethod par) { if (laKind == Semicolon) // Abstract or virtual functions { Step(); par.Description += CheckForPostSemicolonComment(); par.EndLocation = t.EndLocation; return; } if (laKind == GoesTo) { LambdaBody(par); return; } var stk_Backup = BlockAttributes; BlockAttributes = new Stack<DAttribute> (); while ( (laKind == In && par.In == null) || (laKind == Out && par.Out == null)) { if (laKind == In) { Step(); par.InToken = t.Location; par.In = BlockStatement(par); } if (laKind == Out) { Step(); par.OutToken = t.Location; if (laKind == OpenParenthesis) { Step(); if (Expect(Identifier)) { par.OutResultVariable = new IdentifierDeclaration(t.Value) { Location=t.Location, EndLocation=t.EndLocation }; } Expect(CloseParenthesis); } par.Out = BlockStatement(par); } } // Although there can be in&out constraints, there doesn't have to be a direct body definition. Used on abstract class/interface methods. if (laKind == Body){ Step(); par.BodyToken = t.Location; } if ((par.In==null && par.Out==null) || laKind == OpenCurlyBrace) { par.Body = BlockStatement(par); } BlockAttributes = stk_Backup; par.EndLocation = par.Body != null ? par.Body.EndLocation : t.EndLocation; }
internal void LambdaSingleStatementBody(DMethod lambdaFunction) { lambdaFunction.Body = new BlockStatement { Location= la.Location, ParentNode = lambdaFunction }; var ae = AssignExpression(lambdaFunction); lambdaFunction.Body.Add(new ReturnStatement { Location = ae.Location, EndLocation = ae.EndLocation, ReturnExpression=ae }); lambdaFunction.Body.EndLocation = t.EndLocation; }
public void DeclDef(DBlockNode module) { if (IsAttributeSpecifier) { do AttributeSpecifier (module); while(IsAttributeSpecifier); var tkind = t.Kind; if(tkind == Semicolon || tkind == CloseCurlyBrace || tkind == Colon) return; } if (laKind == Semicolon) { Step(); return; } switch (laKind) { case Import: module.Add(ImportDeclaration(module)); break; case This: module.Add(Constructor(module, module is DClassLike && ((DClassLike)module).ClassType == DTokens.Struct)); break; case Tilde: if (Lexer.CurrentPeekToken.Kind != This) goto default; module.Add(Destructor()); break; case Invariant: module.Add(_Invariant()); break; case Unittest: Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); ApplyAttributes(dbs); dbs.Location = t.Location; FunctionBody(dbs); dbs.EndLocation = t.EndLocation; module.Add(dbs); break; /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ case Version: case Debug: if (Peek(1).Kind == Assign) { DebugSpecification ds = null; VersionSpecification vs = null; if (laKind == Version) vs = new VersionSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; else ds = new DebugSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; Step(); Step(); if (laKind == Literal) { Step(); if (t.LiteralFormat != LiteralFormat.Scalar) SynErr(t.Kind, "Integer literal expected!"); try { if (vs != null) vs.SpecifiedNumber = Convert.ToInt32(t.LiteralValue); else ds.SpecifiedDebugLevel = Convert.ToInt32(t.LiteralValue); } catch { } } else if (laKind == Identifier) { Step(); if (vs != null) vs.SpecifiedId = t.Value; else ds.SpecifiedId = t.Value; } else if (ds == null) Expect(Identifier); Expect(Semicolon); ((AbstractStatement)ds ?? vs).EndLocation = t.EndLocation; module.Add(vs as StaticStatement ?? ds); } else DeclarationCondition(module); break; case Static: if (Lexer.CurrentPeekToken.Kind == If) goto case Version; goto default; case Assert: Step(); CheckForStorageClasses(module); if (!Modifier.ContainsAttribute(DeclarationAttributes, Static)) SynErr(Static, "Static assert statements must be explicitly marked as static"); var ass = new StaticAssertStatement { Attributes = GetCurrentAttributeSet_Array(), Location = t.Location }; if (Expect(OpenParenthesis)) { ass.AssertedExpression = AssignExpression(); if (laKind == (Comma)) { Step(); ass.Message = AssignExpression(); } if (Expect(CloseParenthesis)) Expect(Semicolon); } ass.EndLocation = t.EndLocation; module.Add(ass); break; case Mixin: if (Peek(1).Kind == Template) module.Add(TemplateDeclaration(module)); //TemplateMixin else if (Lexer.CurrentPeekToken.Kind == Identifier) { var tmx = TemplateMixin(module); if (tmx.MixinId == null) module.Add(tmx); else module.Add(new NamedTemplateMixinNode(tmx)); } //MixinDeclaration else if (Lexer.CurrentPeekToken.Kind == OpenParenthesis) module.Add(MixinDeclaration(module, null)); else { Step(); SynErr(Identifier); } break; case OpenCurlyBrace: AttributeBlock(module); break; // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) case New: Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location = t.Location }; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); break; case Delete: Step(); var ddm = new DMethod(DMethod.MethodType.Deallocator) { Location = t.Location }; ddm.Name = "delete"; ApplyAttributes(ddm); ddm.Parameters = Parameters(ddm); FunctionBody(ddm); ddm.EndLocation = t.EndLocation; module.Add(ddm); break; default: var decls = Declaration(module); if(module != null && decls!=null) module.AddRange(decls); break; } }
/// <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; }
DMethod _Invariant() { var inv = new DMethod { SpecialType= DMethod.MethodType.ClassInvariant }; Expect(Invariant); inv.Location = t.Location; if (laKind == OpenParenthesis) { Step(); Expect(CloseParenthesis); } if(!IsEOF) inv.Body=BlockStatement(); inv.EndLocation = t.EndLocation; return inv; }
void DeclDef(DBlockNode module) { //AttributeSpecifier while (IsAttributeSpecifier()) { AttributeSpecifier(module); if (t.Kind == Colon || laKind == CloseCurlyBrace || IsEOF) return; } if (laKind == Semicolon) { LastParsedObject = null; Step(); return; } //ImportDeclaration if (laKind == Import) module.Add(ImportDeclaration(module)); //Constructor else if (laKind == (This)) module.Add(Constructor(module, module is DClassLike ? ((DClassLike)module).ClassType == DTokens.Struct : false)); //Destructor else if (laKind == (Tilde) && Lexer.CurrentPeekToken.Kind == (This)) module.Add(Destructor()); //Invariant else if (laKind == (Invariant)) module.Add(_Invariant()); //UnitTest else if (laKind == (Unittest)) { Step(); var dbs = new DMethod(DMethod.MethodType.Unittest); ApplyAttributes(dbs); LastParsedObject = dbs; dbs.Location = t.Location; FunctionBody(dbs); dbs.EndLocation = t.EndLocation; module.Add(dbs); } /* * VersionSpecification: * version = Identifier ; * version = IntegerLiteral ; * * DebugSpecification: * debug = Identifier ; * debug = IntegerLiteral ; */ else if ((laKind == Version || laKind == Debug) && Peek(1).Kind == Assign) { DebugSpecification ds = null; VersionSpecification vs = null; if (laKind == Version) LastParsedObject = vs = new VersionSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; else LastParsedObject = ds = new DebugSpecification { Location = la.Location, Attributes = GetCurrentAttributeSet_Array() }; Step(); Step(); if (laKind == Literal) { Step(); if (t.LiteralFormat != LiteralFormat.Scalar) SynErr(t.Kind, "Integer literal expected!"); try { if (vs != null) vs.SpecifiedNumber = Convert.ToInt32(t.LiteralValue); else ds.SpecifiedDebugLevel = Convert.ToInt32(t.LiteralValue); } catch { } } else if (laKind == Identifier) { Step(); if (vs != null) vs.SpecifiedId = t.Value; else ds.SpecifiedId = t.Value; } else if (ds == null) Expect(Identifier); Expect(Semicolon); if (vs == null) ds.EndLocation = t.EndLocation; else vs.EndLocation = t.EndLocation; module.Add(vs as StaticStatement ?? ds); } else if (laKind == Version || laKind == Debug || (laKind == Static && Lexer.CurrentPeekToken.Kind == If)) DeclarationCondition(module); //StaticAssert else if (laKind == (Assert)) { Step(); if (!Modifier.ContainsAttribute(DeclarationAttributes, Static)) SynErr(Static, "Static assert statements must be explicitly marked as static"); var ass = new StaticAssertStatement { Attributes = GetCurrentAttributeSet_Array(), Location = t.Location }; if (Expect(OpenParenthesis)) { ass.AssertedExpression = AssignExpression(); if (laKind == (Comma)) { Step(); ass.Message = AssignExpression(); } if(Expect(CloseParenthesis)) Expect(Semicolon); } ass.EndLocation = t.EndLocation; module.Add(ass); } //TemplateMixinDeclaration else if (laKind == Mixin) { if (Peek(1).Kind == Template) module.Add(TemplateDeclaration(module)); //TemplateMixin else if (Lexer.CurrentPeekToken.Kind == Identifier) { var tmx = TemplateMixin(module); if(tmx.MixinId==null) module.Add(tmx); else module.Add(new NamedTemplateMixinNode(tmx)); } //MixinDeclaration else if (Lexer.CurrentPeekToken.Kind == OpenParenthesis) module.Add(MixinDeclaration(module,null)); else { Step(); SynErr(Identifier); } } // { else if (laKind == (OpenCurlyBrace)) AttributeBlock(module); // Class Allocators // Note: Although occuring in global scope, parse it anyway but declare it as semantic nonsense;) else if (laKind == (New)) { Step(); var dm = new DMethod(DMethod.MethodType.Allocator) { Location = t.Location }; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // Class Deallocators else if (laKind == Delete) { Step(); var dm = new DMethod(DMethod.MethodType.Deallocator) { Location = t.Location }; dm.Name = "delete"; ApplyAttributes(dm); dm.Parameters = Parameters(dm); FunctionBody(dm); dm.EndLocation = t.EndLocation; module.Add(dm); } // else: else { var decls = Declaration(module); if(module != null && decls!=null) module.AddRange(decls); } }
public void Visit(PostfixExpression_ArrayAccess x) {//TODO for Slices: Omit opIndex overloads if it's obvious that we don't want them -- a[1.. | if (x.Arguments != null) res.CurrentlyTypedArgumentIndex = x.Arguments.Length; res.IsMethodArguments = true; res.ParsedExpression = x; var overloads = new List<AbstractType>(); if (x.PostfixForeExpression == null) return; var b = ExpressionTypeEvaluation.EvaluateType(x.PostfixForeExpression, ctxt); var ov = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(ExpressionTypeEvaluation.OpSliceIdHash, b, ctxt, x, false); if (ov != null) overloads.AddRange(ov); ov = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(ExpressionTypeEvaluation.OpIndexIdHash, b, ctxt, x, false); if (ov != null) overloads.AddRange(ov); if (overloads.Count == 0) { b = DResolver.StripMemberSymbols(b); var toTypeDecl = new DTypeToTypeDeclVisitor(); var aa = b as AssocArrayType; if (aa != null){ var retType = aa.ValueType != null ? aa.ValueType.Accept(toTypeDecl) : null; var dm = new DMethod { Name = "opIndex", Type = retType }; dm.Parameters.Add(new DVariable { Name = "index", Type = aa.KeyType != null ? aa.KeyType.Accept(toTypeDecl) : null }); overloads.Add(new MemberSymbol(dm, aa.ValueType)); if ((aa is ArrayType) && !(aa as ArrayType).IsStaticArray) { dm = new DMethod { Name = "opSlice", Type = retType }; overloads.Add(new MemberSymbol(dm, aa.ValueType)); } } else if (b is PointerType) { b = (b as PointerType).Base; var dm = new DMethod { Name = "opIndex", Type = b != null ? b.Accept(toTypeDecl) : null }; dm.Parameters.Add(new DVariable { Name = "index", Type = new IdentifierDeclaration("size_t") }); overloads.Add(new MemberSymbol(dm, b)); } } res.ResolvedTypesOrMethods = overloads.ToArray(); }
INode Destructor() { Expect(Tilde); var dm = new DMethod{ Location = t.Location, NameLocation = la.Location }; Expect(This); LastParsedObject = dm; dm.SpecialType = DMethod.MethodType.Destructor; dm.Name = "~this"; if (IsTemplateParameterList()) TemplateParameterList(dm); dm.Parameters = Parameters(dm); if (laKind == (If)) Constraint(dm); FunctionBody(dm); return dm; }
public static IBlockNode UpdateBlockPartly(this BlockStatement bs, string code, int caretOffset, CodeLocation caretLocation, out bool isInsideNonCodeSegment) { isInsideNonCodeSegment = false; var finalParentMethod = bs.ParentNode as DMethod; var finalStmtsList = bs._Statements; var startLoc = bs.Location; int startStmtIndex; for(startStmtIndex = finalStmtsList.Count-1; startStmtIndex >= 0; startStmtIndex--) { var n = finalStmtsList [startStmtIndex]; if (n.EndLocation.Line > 0 && n.EndLocation.Line < caretLocation.Line) { startLoc = --startStmtIndex == -1 ? bs.Location : finalStmtsList [startStmtIndex].EndLocation; break; } } var startOff = startLoc.Line > 1 ? DocumentHelper.GetOffsetByRelativeLocation (code, caretLocation, caretOffset, startLoc) : 0; if (startOff >= caretOffset) return null; var tempParentBlock = new DMethod();//new DBlockNode(); var tempBlockStmt = new BlockStatement { ParentNode = tempParentBlock }; tempParentBlock.Body = tempBlockStmt; tempBlockStmt.Location = startLoc; tempParentBlock.Location = startLoc; using (var sv = new StringView (code, startOff, caretOffset - startOff)) using (var p = DParser.Create(sv)) { p.Lexer.SetInitialLocation (startLoc); p.Step (); if(p.laKind == DTokens.OpenCurlyBrace) p.Step(); while (!p.IsEOF) { if (p.laKind == DTokens.CloseCurlyBrace) { p.Step (); /*if (metaDecls.Count > 0) metaDecls.RemoveAt (metaDecls.Count - 1);*/ continue; } var stmt = p.Statement (true, false, tempParentBlock, tempBlockStmt); if (stmt != null) tempBlockStmt.Add(stmt); else p.Step(); } tempBlockStmt.EndLocation = new CodeLocation(p.la.Column+1,p.la.Line); tempParentBlock.EndLocation = tempBlockStmt.EndLocation; if(isInsideNonCodeSegment = p.Lexer.endedWhileBeingInNonCodeSequence) return null; } DoubleDeclarationSilencer.RemoveDoubles(finalParentMethod, tempParentBlock); tempParentBlock.Parent = finalParentMethod; //tempParentBlock.Add(new PseudoStaticStmt { Block = tempBlockStmt, ParentNode = tempParentBlock, Location = tempBlockStmt.Location, EndLocation = tempBlockStmt.EndLocation }); return tempParentBlock; }
public static TooltipInformation Generate(DMethod dm, bool isTemplateParamInsight=false, int currentParam=-1) { var tti = new TooltipInformation(); var sb = new StringBuilder("<i>("); string name; switch (dm.SpecialType) { case DMethod.MethodType.Constructor: sb.Append("Constructor"); name = dm.Parent.Name; break; case DMethod.MethodType.Destructor: sb.Append("Destructor"); name = dm.Parent.Name; break; case DMethod.MethodType.Allocator: sb.Append("Allocator"); name = dm.Parent.Name; break; default: sb.Append("Method"); name = dm.Name; break; } sb.Append(")</i> "); if (dm.Type != null) { sb.Append(dm.Type.ToString(true)); sb.Append(" "); } else if (dm.Attributes != null && dm.Attributes.Count != 0) { foreach (var attr in dm.Attributes) { var m = attr as Modifier; if (m != null && DTokens.StorageClass[m.Token]) { sb.Append(DTokens.GetTokenString(m.Token)); sb.Append(" "); break; } } } sb.Append(name); /*TODO: Show attributes? if (dm.Attributes != null && dm.Attributes.Count > 0) s = dm.AttributeString + ' '; */ // Template parameters if (dm.TemplateParameters != null && dm.TemplateParameters.Length > 0) { sb.Append("("); for (int i = 0; i < dm.TemplateParameters.Length; i++) { var p = dm.TemplateParameters[i]; if (isTemplateParamInsight && i == currentParam) { sb.Append("<u>"); tti.AddCategory(p.Name, p.ToString()); sb.Append(p.ToString()); sb.Append("</u>"); } else sb.Append(p.ToString()); if (i < dm.TemplateParameters.Length - 1) sb.Append(","); } sb.Append(")"); } // Parameters sb.Append("("); for (int i = 0; i < dm.Parameters.Count; i++) { var p = dm.Parameters[i] as DNode; if (!isTemplateParamInsight && i == currentParam) { sb.Append("<u>"); if (!string.IsNullOrEmpty(p.Description)) tti.AddCategory(p.Name, p.Description); sb.Append(p.ToString(true, false)); sb.Append("</u>"); } else sb.Append(p.ToString(true, false)); if (i < dm.Parameters.Count - 1) sb.Append(","); } sb.Append(")"); tti.SignatureMarkup = sb.ToString(); tti.SummaryMarkup = dm.Description; tti.FooterMarkup = dm.ToString(); return tti; }
AbstractType Type(char type = '\0') { if(type == '\0') type = (char)r.Read(); switch(type) { case 'O': var t = Type(); t.Modifier = DTokens.Shared; return t; case 'x': t = Type(); t.Modifier = DTokens.Const; return t; case 'y': t = Type(); t.Modifier = DTokens.Immutable; return t; case 'N': switch(r.Read()) { case 'g': t = Type(); t.Modifier = DTokens.InOut; return t; case 'e': // TypeNewArray ? Type(); return null; } break; case 'A': return new ArrayType(Type()); case 'G': var len = (int)Number(); return new ArrayType(Type(), len); case 'H': var keyType = Type(); t = Type(); return new AssocArrayType(t, keyType); case 'P': return new PointerType(Type()); case 'F': case 'U': case 'W': case 'V': case 'R': AbstractType ret; List<DAttribute> attrs; Dictionary<INode,AbstractType> pars; Function(out ret, out attrs, out pars, type); var dm = new DMethod(){ Parameters = pars.Keys.ToList(), Attributes = attrs }; return new MemberSymbol(dm, ret, null); case 'C': case 'S': case 'E': case 'T': case 'I': return TypeDeclarationResolver.ResolveSingle (QualifiedName (), ctxt); /* return new MemberSymbol(null,null, QualifiedName()); case 'C': return new ClassType(new DClassLike(DTokens.Class), QualifiedName(), null); case 'S': return new StructType(new DClassLike(DTokens.Struct), QualifiedName()); case 'E': return new EnumType(new DEnum(), null, QualifiedName()); case 'T': return new AliasedType(null, null, QualifiedName()); */case 'D': Function(out ret, out attrs, out pars, type); var dgArgs = new List<AbstractType>(); foreach(var kv in pars) dgArgs.Add(new MemberSymbol(kv.Key as DNode, kv.Value, null)); return new DelegateType(ret,new DelegateDeclaration{ Parameters = pars.Keys.ToList() }, dgArgs); case 'v': return new PrimitiveType(DTokens.Void); case 'g': return new PrimitiveType(DTokens.Byte); case 'h': return new PrimitiveType(DTokens.Ubyte); case 's': return new PrimitiveType(DTokens.Short); case 't': return new PrimitiveType(DTokens.Ushort); case 'i': return new PrimitiveType(DTokens.Int); case 'k': return new PrimitiveType(DTokens.Uint); case 'l': return new PrimitiveType(DTokens.Long); case 'm': return new PrimitiveType(DTokens.Ulong); case 'f': return new PrimitiveType(DTokens.Float); case 'd': return new PrimitiveType(DTokens.Double); case 'e': return new PrimitiveType(DTokens.Real); case 'o': return new PrimitiveType(DTokens.Ifloat); case 'p': return new PrimitiveType(DTokens.Idouble); case 'j': return new PrimitiveType(DTokens.Ireal); case 'q': return new PrimitiveType(DTokens.Cfloat); case 'r': return new PrimitiveType(DTokens.Cdouble); case 'c': return new PrimitiveType(DTokens.Creal); case 'b': return new PrimitiveType(DTokens.Bool); case 'a': return new PrimitiveType(DTokens.Char); case 'u': return new PrimitiveType(DTokens.Wchar); case 'w': return new PrimitiveType(DTokens.Dchar); case 'n': return null; case 'B': len = (int)Number(); var items = new AbstractType[len]; var c = (char)r.Read(); for (int i = 0; i < len; i++) { Argument(ref c, out items[i]); } return new DTuple(items); } return null; }
static StaticProperties() { var props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.Generic] = props; props.AddProp(new StaticPropertyInfo("init", "A type's or variable's static initializer expression") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType }); props.AddProp(new StaticPropertyInfo("sizeof", "Size of a type or variable in bytes", DTokens.Uint)); // Do not define it as size_t due to unnecessary recursive definition as typeof(int.sizeof) props.AddProp(new StaticPropertyInfo("alignof", "Variable offset", DTokens.Uint) { RequireThis = true }); props.AddProp(new StaticPropertyInfo("mangleof", "String representing the ‘mangled’ representation of the type", "string")); props.AddProp(new StaticPropertyInfo("stringof", "String representing the source representation of the type", "string") { ValueGetter = (vp, v) => { var t = AbstractType.Get(v); if(t == null) return new NullValue(); return new ArrayValue(Evaluation.GetStringType(vp.ResolutionContext), (t is DSymbol) ? DNode.GetNodePath((t as DSymbol).Definition,true) : t.ToCode()); } }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.Integral] = props; props.AddProp(new StaticPropertyInfo("max", "Maximum value") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType }); props.AddProp(new StaticPropertyInfo("min", "Minimum value") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.FloatingPoint] = props; props.AddProp(new StaticPropertyInfo("infinity", "Infinity value") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType }); props.AddProp(new StaticPropertyInfo("nan", "Not-a-Number value") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType }); props.AddProp(new StaticPropertyInfo("dig", "Number of decimal digits of precision", DTokens.Int)); props.AddProp(new StaticPropertyInfo("epsilon", "Smallest increment to the value 1") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType }); props.AddProp(new StaticPropertyInfo("mant_dig", "Number of bits in mantissa", DTokens.Int)); props.AddProp(new StaticPropertyInfo("max_10_exp", "Maximum int value such that 10^max_10_exp is representable", DTokens.Int)); props.AddProp(new StaticPropertyInfo("max_exp", "Maximum int value such that 2^max_exp-1 is representable", DTokens.Int)); props.AddProp(new StaticPropertyInfo("min_10_exp", "Minimum int value such that 10^max_10_exp is representable", DTokens.Int)); props.AddProp(new StaticPropertyInfo("min_exp", "Minimum int value such that 2^max_exp-1 is representable", DTokens.Int)); props.AddProp(new StaticPropertyInfo("min_normal", "Number of decimal digits of precision", DTokens.Int)); props.AddProp(new StaticPropertyInfo("re", "Real part") { TypeGetter = help_ReflectNonComplexType, ResolvedBaseTypeGetter = help_ReflectResolvedNonComplexType, RequireThis = true }); props.AddProp(new StaticPropertyInfo("im", "Imaginary part") { TypeGetter = help_ReflectNonComplexType, ResolvedBaseTypeGetter = help_ReflectResolvedNonComplexType, RequireThis = true }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.Array] = props; props.AddProp(new StaticPropertyInfo("length", "Array length", DTokens.Int) { RequireThis = true, ValueGetter = (vp, v) => { var av = v as ArrayValue; return new PrimitiveValue(av.Elements != null ? av.Elements.Length : 0); }}); props.AddProp(new StaticPropertyInfo("dup", "Create a dynamic array of the same size and copy the contents of the array into it.") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType, RequireThis = true }); props.AddProp(new StaticPropertyInfo("idup", "D2.0 only! Creates immutable copy of the array") { TypeGetter = (t,ctxt) => new MemberFunctionAttributeDecl (DTokens.Immutable) { InnerType = help_ReflectType (t,ctxt) }, RequireThis = true }); props.AddProp(new StaticPropertyInfo("reverse", "Reverses in place the order of the elements in the array. Returns the array.") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType, RequireThis = true }); props.AddProp(new StaticPropertyInfo("sort", "Sorts in place the order of the elements in the array. Returns the array.") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType, RequireThis = true }); props.AddProp(new StaticPropertyInfo("ptr", "Returns pointer to the array") { ResolvedBaseTypeGetter = (t, ctxt) => new PointerType((t as DerivedDataType).Base), TypeGetter = (t, ctxt) => new PointerDecl(DTypeToTypeDeclVisitor.GenerateTypeDecl((t as DerivedDataType).Base)), RequireThis = true }); props = new Dictionary<int, StaticPropertyInfo>(props); // Copy from arrays' properties! Properties[PropOwnerType.AssocArray] = props; props.AddProp(new StaticPropertyInfo("length", "Returns number of values in the associative array. Unlike for dynamic arrays, it is read-only.", "size_t") { RequireThis = true }); props.AddProp(new StaticPropertyInfo("keys", "Returns dynamic array, the elements of which are the keys in the associative array.") { TypeGetter = (t, ctxt) => new ArrayDecl { ValueType = DTypeToTypeDeclVisitor.GenerateTypeDecl((t as AssocArrayType).KeyType) }, RequireThis = true }); props.AddProp(new StaticPropertyInfo("values", "Returns dynamic array, the elements of which are the values in the associative array.") { TypeGetter = (t, ctxt) => new ArrayDecl { ValueType = DTypeToTypeDeclVisitor.GenerateTypeDecl((t as AssocArrayType).ValueType) }, RequireThis = true }); props.AddProp(new StaticPropertyInfo("rehash", "Reorganizes the associative array in place so that lookups are more efficient. rehash is effective when, for example, the program is done loading up a symbol table and now needs fast lookups in it. Returns a reference to the reorganized array.") { TypeGetter = help_ReflectType, ResolvedBaseTypeGetter = help_ReflectResolvedType, RequireThis = true }); props.AddProp(new StaticPropertyInfo("byKey", "Returns a delegate suitable for use as an Aggregate to a ForeachStatement which will iterate over the keys of the associative array.") { TypeGetter = (t, ctxt) => new DelegateDeclaration() { ReturnType = new ArrayDecl() { ValueType = DTypeToTypeDeclVisitor.GenerateTypeDecl((t as AssocArrayType).KeyType) } }, RequireThis = true }); props.AddProp(new StaticPropertyInfo("byValue", "Returns a delegate suitable for use as an Aggregate to a ForeachStatement which will iterate over the values of the associative array.") { TypeGetter = (t, ctxt) => new DelegateDeclaration() { ReturnType = new ArrayDecl() { ValueType = DTypeToTypeDeclVisitor.GenerateTypeDecl((t as AssocArrayType).ValueType) } }, RequireThis = true }); props.AddProp(new StaticPropertyInfo("get", null) { RequireThis = true, NodeGetter = (t, ctxt) => { var ad = t as AssocArrayType; var valueType = DTypeToTypeDeclVisitor.GenerateTypeDecl(ad.ValueType); var dm = new DMethod () { Name = "get", Description = "Looks up key; if it exists returns corresponding value else evaluates and returns defaultValue.", Type = valueType }; dm.Parameters.Add(new DVariable () { Name = "key", Type = DTypeToTypeDeclVisitor.GenerateTypeDecl(ad.KeyType) }); dm.Parameters.Add(new DVariable () { Name = "defaultValue", Type = valueType, Attributes = new List<DAttribute>{ new Modifier (DTokens.Lazy) } }); return dm; } }); props.AddProp(new StaticPropertyInfo("remove", null) { RequireThis = true, NodeGetter = (t, ctxt) => { var dm =new DMethod { Name = "remove", Description = "remove(key) does nothing if the given key does not exist and returns false. If the given key does exist, it removes it from the AA and returns true.", Type = new DTokenDeclaration (DTokens.Bool) }; dm.Parameters.Add(new DVariable { Name = "key", Type = DTypeToTypeDeclVisitor.GenerateTypeDecl((t as AssocArrayType).KeyType) }); return dm; } }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.TypeTuple] = props; props.AddProp(new StaticPropertyInfo("length", "Returns number of values in the type tuple.", "size_t") { RequireThis = true, ValueGetter = (vp, v) => { var tt = v as DTuple; if (tt == null && v is TypeValue) tt = (v as TypeValue).RepresentedType as DTuple; return tt != null ? new PrimitiveValue(tt.Items == null ? 0 : tt.Items.Length) : null; } }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.Delegate] = props; props.AddProp(new StaticPropertyInfo("ptr", "The .ptr property of a delegate will return the frame pointer value as a void*.", (ITypeDeclaration)new PointerDecl(new DTokenDeclaration(DTokens.Void))) { RequireThis = true }); props.AddProp(new StaticPropertyInfo("funcptr", "The .funcptr property of a delegate will return the function pointer value as a function type.") { RequireThis = true }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.ClassLike] = props; props.AddProp(new StaticPropertyInfo("classinfo", "Information about the dynamic type of the class", (ITypeDeclaration)new IdentifierDeclaration("TypeInfo_Class") { ExpressesVariableAccess = true, InnerDeclaration = new IdentifierDeclaration("object") }) { RequireThis = true }); props = new Dictionary<int, StaticPropertyInfo>(); Properties[PropOwnerType.Struct] = props; props.AddProp(new StaticPropertyInfo("sizeof", "Size in bytes of struct", DTokens.Uint)); props.AddProp(new StaticPropertyInfo("alignof", "Size boundary struct needs to be aligned on", DTokens.Uint)); props.AddProp(new StaticPropertyInfo("tupleof", "Gets type tuple of fields") { TypeGetter = (t, ctxt) => { var members = GetStructMembers(t as StructType, ctxt); var l = new List<IExpression>(); var vis = new DTypeToTypeDeclVisitor(); foreach (var member in members) { var mt = DResolver.StripMemberSymbols(member); if(mt == null){ l.Add(null); continue; } var td = mt.Accept(vis); if (td == null) { l.Add(null); continue; } l.Add(td as IExpression ?? new TypeDeclarationExpression(td)); } return new TemplateInstanceExpression(new IdentifierDeclaration("Tuple")) { Arguments = l.ToArray() }; }, ResolvedBaseTypeGetter = (t, ctxt) => { var members = GetStructMembers(t as StructType, ctxt); var tupleItems = new List<ISemantic>(); foreach (var member in members) { var mt = DResolver.StripMemberSymbols(member); if (mt != null) tupleItems.Add(mt); } return new DTuple(tupleItems); } }); }