static bool CheckAndPushAnalysisStack(MixinStatement mx) { if(stmtsBeingAnalysed == null) stmtsBeingAnalysed = new List<MixinStatement>(); if(stmtsBeingAnalysed.Count != 0) { /* * Only accept mixins that are located somewhere BEFORE the mixin that is the last inserted one in the stack. * Also make sure mx and the peek mixin do have the same module root! */ foreach(var pk in stmtsBeingAnalysed) { if(mx.ParentNode.NodeRoot == pk.ParentNode.NodeRoot) { if(mx == pk || mx.Location > pk.Location) return false; break; } } if(stmtsBeingAnalysed.Count > 5) return false; } stmtsBeingAnalysed.Add(mx); return true; }
static bool CheckAndPushAnalysisStack(MixinStatement mx) { if (stmtsBeingAnalysed == null) { stmtsBeingAnalysed = new List <MixinStatement>(); } if (stmtsBeingAnalysed.Count != 0) { /* * Only accept mixins that are located somewhere BEFORE the mixin that is the last inserted one in the stack. * Also make sure mx and the peek mixin do have the same module root! */ foreach (var pk in stmtsBeingAnalysed) { if (mx.ParentNode.NodeRoot == pk.ParentNode.NodeRoot) { if (mx == pk || mx.Location > pk.Location) { return(false); } break; } } if (stmtsBeingAnalysed.Count > 5) { return(false); } } stmtsBeingAnalysed.Add(mx); return(true); }
static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache ,out ISyntaxRegion cachedContent) { cachedContent = null; if(!CheckAndPushAnalysisStack(mx)) return null; bool pop; if(pop = (ctxt.ScopedBlock != mx.ParentNode && mx.ParentNode != null)) ctxt.PushNewScope(mx.ParentNode as IBlockNode, mx); bool hadCachedItem; if(takeStmtCache) { BlockStatement stmt; hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt); cachedContent = stmt; } else { DModule mod; hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod); cachedContent = mod; } if(hadCachedItem) { stmtsBeingAnalysed.Remove(mx); if(pop) ctxt.Pop(); return null; } var x = mx.MixinExpression; ISemantic v = null; try // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception... { // Evaluate the mixin expression v = Evaluation.EvaluateValue(x, ctxt); } catch{} stmtsBeingAnalysed.Remove(mx); if(pop) ctxt.Pop(); // Ensure it's a string literal var av = v as ArrayValue; if(av != null && av.IsString) return av.StringValue; if(takeStmtCache) mixinStmtCache.Add(ctxt, mx, null); else mixinDeclCache.Add(ctxt, mx, null); return null; }
public static DBlockNode ParseMixinDeclaration(MixinStatement mx, ResolutionContext ctxt, out VariableValue vv) { var literal = GetMixinContent(mx, ctxt, false, out vv); if (literal == null) { return(null); } var ast = DParser.ParseDeclDefs(literal); if (ast == null) { return(null); } ast.Parent = mx.ParentNode; foreach (var ch in ast) { if (mx.Attributes != null) { var dn = ch as DNode; if (dn != null) { if (dn.Attributes == null) { dn.Attributes = new List <DAttribute>(mx.Attributes); } else { dn.Attributes.AddRange(mx.Attributes); } } } ch.Parent = mx.ParentNode; } if (mx.Attributes != null) { foreach (var ss in ast.StaticStatements) { if (ss.Attributes == null) { ss.Attributes = mx.Attributes; } else { var attrs = new DAttribute[mx.Attributes.Length + ss.Attributes.Length]; mx.Attributes.CopyTo(attrs, 0); ss.Attributes.CopyTo(attrs, mx.Attributes.Length); } } } return(ast); }
public static BlockStatement ParseMixinStatement(MixinStatement mx, ResolutionContext ctxt, out VariableValue vv) { var literal = GetMixinContent(mx, ctxt, true, out vv); if (literal == null) { return(null); } var bs = (BlockStatement)DParser.ParseBlockStatement("{" + literal + "}", mx.ParentNode); return(bs); }
public static BlockStatement ParseMixinStatement(MixinStatement mx, ResolutionContext ctxt) { ISyntaxRegion sr; var literal = GetMixinContent(mx, ctxt, true, out sr); if(sr is BlockStatement) return (BlockStatement)sr; else if(literal == null) return null; var bs = (BlockStatement)DParser.ParseBlockStatement("{"+literal+"}", mx.ParentNode); mixinStmtCache.Add(ctxt, mx, bs); return bs; }
public virtual void VisitMixinStatement(MixinStatement s) { VisitAbstractStmt(s); if (s.Attributes != null && s.Attributes.Length != 0) { foreach (var attr in s.Attributes) { attr.Accept(this); } } if (s.MixinExpression != null) { s.MixinExpression.Accept(this); } }
static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache, out VariableValue evaluatedVariable) { evaluatedVariable = null; ISemantic v; using (ctxt.Push(mx.ParentNode, mx.Location)) { var tup = ctxt.MixinCache.TryGetType(mx); if (tup != null) { evaluatedVariable = tup.Item2; return(tup.Item1); } if (!CheckAndPushAnalysisStack(mx)) { return(null); } // Evaluate the mixin expression v = Evaluation.EvaluateValue(mx.MixinExpression, ctxt, true); evaluatedVariable = v as VariableValue; if (evaluatedVariable != null) { v = Evaluation.EvaluateValue(evaluatedVariable, new StandardValueProvider(ctxt)); } stmtsBeingAnalysed.Remove(mx); } // Ensure it's a string literal var av = v as ArrayValue; if (av != null && av.IsString) { ctxt.MixinCache.Add(new Tuple <string, VariableValue>(av.StringValue, evaluatedVariable), mx); return(av.StringValue); } else if (v == null) { ctxt.MixinCache.Add(new Tuple <string, VariableValue>(null, null), mx); } return(null); }
public static DModule ParseMixinDeclaration(MixinStatement mx, ResolutionContext ctxt) { ISyntaxRegion sr; var literal = GetMixinContent(mx, ctxt, false, out sr); if(sr is DModule) return (DModule)sr; else if(literal == null) return null; var ast = (DModule)DParser.ParseString(literal, true); mixinDeclCache.Add(ctxt, mx, ast); if(ast == null) return null; foreach(var ch in ast) { if(mx.Attributes!=null) { var dn = ch as DNode; if(dn!=null) { if(dn.Attributes==null) dn.Attributes = new List<DAttribute>(mx.Attributes); else dn.Attributes.AddRange(mx.Attributes); } } ch.Parent = mx.ParentNode; } if(mx.Attributes!=null) foreach(var ss in ast.StaticStatements) { if(ss.Attributes == null) ss.Attributes = mx.Attributes; else{ var attrs = new DAttribute[mx.Attributes.Length + ss.Attributes.Length]; mx.Attributes.CopyTo(attrs,0); ss.Attributes.CopyTo(attrs,mx.Attributes.Length); } } return ast; }
public static BlockStatement ParseMixinStatement(MixinStatement mx, ResolutionContext ctxt) { ISyntaxRegion sr; var literal = GetMixinContent(mx, ctxt, true, out sr); if (sr is BlockStatement) { return((BlockStatement)sr); } else if (literal == null) { return(null); } var bs = (BlockStatement)DParser.ParseBlockStatement("{" + literal + "}", mx.ParentNode); mixinStmtCache.Add(ctxt, mx, bs); return(bs); }
/// <summary> /// Evaluates the literal given as expression and tries to parse it as a string. /// Important: Assumes all its compilation conditions to be checked already! /// </summary> bool HandleMixin(MixinStatement mx, bool parseDeclDefs, MemberFilter vis) { if (CompletionOptions.Instance.DisableMixinAnalysis) { return(false); } // If in a class/module block => MixinDeclaration if (parseDeclDefs) { var ast = MixinAnalysis.ParseMixinDeclaration(mx, ctxt); if (ast == null) { return(false); } // take ast.Endlocation because the cursor must be beyond the actual mixin expression // - and therewith _after_ each declaration if (ctxt.ScopedBlock == mx.ParentNode.NodeRoot) { return(ScanBlockUpward(ast, ast.EndLocation, vis)); } else { return(scanChildren(ast, vis, isMixinAst: true)); } } else // => MixinStatement { var bs = MixinAnalysis.ParseMixinStatement(mx, ctxt); // As above, disregard the caret position because 1) caret and parsed code do not match // and 2) the caret must be located somewhere after the mixin statement's end if (bs != null) { return(ScanStatementHierarchy(bs, CodeLocation.Empty, vis)); } } return(false); }
MixinStatement MixinDeclaration(IBlockNode Scope, IStatement StmtScope) { var mx = new MixinStatement{ Attributes = GetCurrentAttributeSet_Array(), Location = la.Location, Parent = StmtScope, ParentNode = Scope }; Expect(Mixin); if(Expect(OpenParenthesis)) { mx.MixinExpression = AssignExpression(); if(Expect(CloseParenthesis)) Expect(Semicolon); } mx.EndLocation = t.EndLocation; return mx; }
public void VisitMixinStatement(MixinStatement s) { }
/// <summary> /// Evaluates the literal given as expression and tries to parse it as a string. /// Important: Assumes all its compilation conditions to be checked already! /// </summary> bool HandleMixin(MixinStatement mx, bool parseDeclDefs, MemberFilter vis) { if (CompletionOptions.Instance.DisableMixinAnalysis) return false; // If in a class/module block => MixinDeclaration if(parseDeclDefs) { var ast = MixinAnalysis.ParseMixinDeclaration(mx, ctxt); if(ast ==null) return false; // take ast.Endlocation because the cursor must be beyond the actual mixin expression // - and therewith _after_ each declaration if(ctxt.ScopedBlock == mx.ParentNode.NodeRoot) return ScanBlockUpward(ast, ast.EndLocation, vis); else { return scanChildren(ast, vis, isMixinAst:true); } } else // => MixinStatement { var bs = MixinAnalysis.ParseMixinStatement(mx, ctxt); // As above, disregard the caret position because 1) caret and parsed code do not match // and 2) the caret must be located somewhere after the mixin statement's end if(bs!=null){ return ScanStatementHierarchy(bs, CodeLocation.Empty, vis); } } return false; }
static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache, out ISyntaxRegion cachedContent) { cachedContent = null; if (!CheckAndPushAnalysisStack(mx)) { return(null); } bool pop = ctxt.ScopedBlock != mx.ParentNode && mx.ParentNode != null; if (pop) { ctxt.PushNewScope(mx.ParentNode as IBlockNode, mx); } bool hadCachedItem; if (takeStmtCache) { BlockStatement stmt; hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt); cachedContent = stmt; } else { DModule mod; hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod); cachedContent = mod; } if (hadCachedItem) { stmtsBeingAnalysed.Remove(mx); if (pop) { ctxt.Pop(); } return(null); } var x = mx.MixinExpression; ISemantic v = null; try // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception... { // Evaluate the mixin expression v = Evaluation.EvaluateValue(x, ctxt); } catch {} stmtsBeingAnalysed.Remove(mx); if (pop) { ctxt.Pop(); } // Ensure it's a string literal var av = v as ArrayValue; if (av != null && av.IsString) { return(av.StringValue); } if (takeStmtCache) { mixinStmtCache.Add(ctxt, mx, null); } else { mixinDeclCache.Add(ctxt, mx, null); } return(null); }
IStatement Statement(bool BlocksAllowed = true, bool EmptyAllowed = true, IBlockNode Scope = null, IStatement Parent=null) { IStatement ret = null; if (EmptyAllowed && laKind == Semicolon) { Step(); return null; } if (BlocksAllowed && laKind == OpenCurlyBrace) return BlockStatement(Scope,Parent); #region LabeledStatement (loc:... goto loc;) if (laKind == Identifier && Lexer.CurrentPeekToken.Kind == Colon) { Step(); ret = (new LabeledStatement() { StartLocation = t.Location, Identifier = t.Value, Parent = Parent }); LastParsedObject = ret; Step(); ret.EndLocation = t.EndLocation; return ret; } #endregion #region IfStatement else if (laKind == (If) || (laKind == Static && Lexer.CurrentPeekToken.Kind == If)) { bool isStatic = laKind==Static; if (isStatic) Step(); Step(); var dbs = new IfStatement() { StartLocation = t.Location, IsStatic = isStatic, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // IfCondition IfCondition(dbs); Expect(CloseParenthesis); // ThenStatement dbs.ThenStatement = Statement(Scope:Scope,Parent:dbs); // ElseStatement if (laKind == (Else)) { Step(); dbs.ElseStatement = Statement(Scope: Scope, Parent: dbs); } dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region WhileStatement else if (laKind == While) { Step(); var dbs = new WhileStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); 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() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); Expect(While); Expect(OpenParenthesis); dbs.Condition = Expression(Scope); Expect(CloseParenthesis); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region ForStatement else if (laKind == (For)) { Step(); var dbs = new ForStatement { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // Initialize if (laKind != Semicolon) dbs.Initialize = Statement(false, Scope: Scope, Parent: dbs); // Against the D language theory, blocks aren't allowed here! else Step(); // Enforce a trailing semi-colon only if there hasn't been an expression (the ; gets already skipped in there) // Expect(Semicolon); // Test if (laKind != (Semicolon)) dbs.Test = Expression(Scope); Expect(Semicolon); // Increment if (laKind != (CloseParenthesis)) dbs.Increment= Expression(Scope); Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region ForeachStatement else if (laKind == (Foreach) || laKind == (Foreach_Reverse)) { Step(); var dbs = new ForeachStatement() { StartLocation = t.Location, IsReverse = t.Kind == Foreach_Reverse, Parent=Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); var tl = new List<DVariable>(); bool init = true; while (init || laKind == (Comma)) { if (!init) Step(); init = false; var forEachVar = new DVariable(); LastParsedObject = forEachVar; forEachVar.StartLocation = la.Location; if (laKind == (Ref)) { Step(); forEachVar.Attributes.Add(new DAttribute(Ref)); } if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Semicolon) || Lexer.CurrentPeekToken.Kind == Comma)) { Step(); forEachVar.Name = t.Value; } else { forEachVar.Type = Type(); if (laKind == Identifier) { Expect(Identifier); forEachVar.Name = t.Value; } } forEachVar.EndLocation = t.EndLocation; tl.Add(forEachVar); } dbs.ForeachTypeList = tl.ToArray(); Expect(Semicolon); dbs.Aggregate = Expression(Scope); // ForeachRangeStatement if (laKind == DoubleDot) { Step(); //TODO: Put this in the expression variable Expression(); } Expect(CloseParenthesis); dbs.ScopedStatement = Statement(Scope: Scope, Parent: dbs); dbs.EndLocation = t.EndLocation; return dbs; } #endregion #region [Final] SwitchStatement else if ((laKind == (Final) && Lexer.CurrentPeekToken.Kind == (Switch)) || laKind == (Switch)) { var dbs = new SwitchStatement { StartLocation = la.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (Final)) { dbs.IsFinal = true; Step(); } Step(); Expect(OpenParenthesis); dbs.SwitchExpression = Expression(Scope); Expect(CloseParenthesis); 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() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = dbs; dbs.ArgumentList = Expression(Scope); Expect(Colon); // CaseRangeStatement if (laKind == DoubleDot) { Step(); Expect(Case); dbs.LastExpression = AssignExpression(); 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 Default else if (laKind == (Default)) { Step(); var dbs = new SwitchStatement.DefaultStatement() { StartLocation = 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() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } else if (laKind == (Break)) { Step(); var s = new BreakStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == (Identifier)) { Step(); s.Identifier = t.Value; } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region Return else if (laKind == (Return)) { Step(); var s = new ReturnStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind != (Semicolon)) s.ReturnExpression = Expression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region Goto else if (laKind == (Goto)) { Step(); var s = new GotoStatement() { StartLocation = 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); } Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region WithStatement else if (laKind == (With)) { Step(); var dbs = new WithStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; Expect(OpenParenthesis); // Symbol dbs.WithExpression = Expression(Scope); Expect(CloseParenthesis); 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() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = dbs; if (laKind == (OpenParenthesis)) { Step(); dbs.SyncExpression = Expression(Scope); Expect(CloseParenthesis); } 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() { StartLocation = 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() { StartLocation = t.Location, Parent = s }; LastParsedObject = c; // CatchParameter if (laKind == (OpenParenthesis)) { Step(); if (laKind == CloseParenthesis) { SemErr(CloseParenthesis, "Catch parameter expected, not ')'"); Step(); } else { var catchVar = new DVariable(); LastParsedObject = catchVar; var tt = la; //TODO? catchVar.Type = BasicType(); if (laKind != Identifier) { la = tt; catchVar.Type = new IdentifierDeclaration("Exception"); } Expect(Identifier); catchVar.Name = t.Value; Expect(CloseParenthesis); c.CatchParameter = catchVar; } } 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() { StartLocation = 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() { StartLocation = 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) && Lexer.CurrentPeekToken.Kind==OpenParenthesis) { Step(); var s = new ScopeGuardStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == OpenParenthesis) { Expect(OpenParenthesis); if(Expect(Identifier) && t.Value!=null) // exit, failure, success { s.GuardedScope = t.Value.ToLower(); } Expect(CloseParenthesis); } s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region AsmStmt else if (laKind == (Asm)) { Step(); var s = new AsmStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; Expect(OpenCurlyBrace); var l=new List<string>(); var curInstr = ""; while (!IsEOF && laKind != (CloseCurlyBrace)) { if (laKind == Semicolon) { l.Add(curInstr.Trim()); curInstr = ""; } else curInstr += laKind==Identifier? la.Value: DTokens.GetTokenString(laKind); Step(); } Expect(CloseCurlyBrace); s.EndLocation = t.EndLocation; return s; } #endregion #region PragmaStatement else if (laKind == (Pragma)) { var s=_Pragma(); s.Parent = Parent; s.ScopedStatement = Statement(Scope: Scope, Parent: s); s.EndLocation = t.EndLocation; return s; } #endregion #region MixinStatement //TODO: Handle this one in terms of adding it to the node structure else if (laKind == (Mixin)) { // TemplateMixin if (Peek(1).Kind != OpenParenthesis) return TemplateMixin(); else { Step(); var s = new MixinStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; Expect(OpenParenthesis); s.MixinExpression = AssignExpression(Scope); Expect(CloseParenthesis); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } } #endregion #region Conditions if (laKind == Debug) { Step(); var s = new ConditionStatement.DebugStatement() { StartLocation = t.Location, Parent = Parent }; LastParsedObject = s; if (laKind == OpenParenthesis) { Step(); if (laKind == Identifier || laKind == Literal) { Step(); if (laKind == Literal) s.DebugIdentifierOrLiteral = t.LiteralValue; else s.DebugIdentifierOrLiteral = t.Value; } else SynErr(t.Kind, "Identifier or Literal expected, "+DTokens.GetTokenString(t.Kind)+" found"); Expect(CloseParenthesis); } s.ScopedStatement = Statement(Scope: Scope, Parent: s); if (laKind == Else) { Step(); s.ElseStatement = Statement(Scope: Scope,Parent:s); } s.EndLocation = t.EndLocation; return s; } if (laKind == Version) { Step(); var s = new ConditionStatement.VersionStatement() { StartLocation = t.Location, Parent = Parent }; if (laKind == OpenParenthesis) { Step(); if (laKind == Identifier || laKind == Literal || laKind==Unittest) { Step(); if(laKind==Unittest) s.VersionIdentifierOrLiteral = "unittest"; else if(laKind==Literal) s.VersionIdentifierOrLiteral=t.LiteralValue; else s.VersionIdentifierOrLiteral=t.Value; } else SynErr(t.Kind, "Identifier or Literal expected, " + DTokens.GetTokenString(t.Kind) + " found"); Expect(CloseParenthesis); } s.ScopedStatement = Statement(Parent:s); if (laKind == Else) { Step(); s.ElseStatement = Statement(Parent:s); } s.EndLocation = t.EndLocation; return s; } #endregion #region (Static) AssertExpression else if (laKind == Assert || (laKind == Static && PK(Assert))) { var s = new AssertStatement() { StartLocation = la.Location, IsStatic = laKind == Static, Parent = Parent }; LastParsedObject = s; if (s.IsStatic) Step(); s.AssertExpression = AssignExpression(Scope); Expect(Semicolon); s.EndLocation = t.EndLocation; return s; } #endregion #region D1: VolatileStatement else if (laKind == Volatile) { Step(); var s = new VolatileStatement() { StartLocation = 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) ImportDeclaration(); else if (!(ClassLike[laKind] || BasicTypes[laKind] || laKind == Enum || Modifiers[laKind] || laKind==PropertyAttribute || laKind == Alias || laKind == Typedef) && IsAssignExpression()) { var s = new ExpressionStatement() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = s; // a==b, a=9; is possible -> Expressions can be there, not only single AssignExpressions! s.Expression = Expression(Scope); if (Expect(Semicolon)) LastParsedObject = null; s.EndLocation = t.EndLocation; return s; } else { var s = new DeclarationStatement() { StartLocation = la.Location, Parent = Parent }; LastParsedObject = s; s.Declarations = Declaration(Scope); if (Scope != null && s.Declarations != null && s.Declarations.Length > 0) foreach (var decl in s.Declarations) decl.Parent = Scope; s.EndLocation = t.EndLocation; return s; } return null; }
/// <summary> /// Visits the specified mixin statement. /// </summary> /// <param name="mixinStatement">The mixin statement.</param> public override void Visit(MixinStatement mixinStatement) { Expression mixinName; AssignmentExpression assignExpression; var genericParameters = new List <Expression>(); switch (mixinStatement.Type) { case MixinStatementType.Default: ExtractGenericParameters(mixinStatement.Value, out mixinName, genericParameters); WriteLinkLine(mixinStatement); Write("context.Mixin(mixin, "); WriteMixinName(mixinName); WriteGenericParameters(genericParameters); WriteLine(");"); break; case MixinStatementType.Child: // mixin child can come in 2 flavour: // 1) mixin child MyEffect => equivalent to mixin child MyEffect = MyEffect // 2) mixin child MyGenericEffectName = MyEffect var targetExpression = mixinStatement.Value; assignExpression = mixinStatement.Value as AssignmentExpression; if (assignExpression != null) { targetExpression = assignExpression.Value; } ExtractGenericParameters(targetExpression, out mixinName, genericParameters); var childName = assignExpression != null ? assignExpression.Target : mixinName; { WriteLinkLine(mixinStatement); Write("if (context.ChildEffectName == "); WriteMixinName(childName); Write(")"); OpenBrace(); WriteLinkLine(mixinStatement); Write("context.Mixin(mixin, "); WriteMixinName(mixinName); WriteGenericParameters(genericParameters); WriteLine(");"); WriteLine("return;"); CloseBrace(); } break; case MixinStatementType.Remove: ExtractGenericParameters(mixinStatement.Value, out mixinName, genericParameters); WriteLinkLine(mixinStatement); Write("context.RemoveMixin(mixin, "); WriteMixinName(mixinName); if (genericParameters.Count > 0) { logging.Error("Removing with generic parameters is not supported", mixinStatement.Span); } WriteLine(");"); break; case MixinStatementType.Macro: WriteLinkLine(mixinStatement); var context = (ShaderBlockContext)currentBlock.GetTag(BlockContextTag); assignExpression = mixinStatement.Value as AssignmentExpression; Expression macroName; Expression macroValue; if (assignExpression != null) { macroName = assignExpression.Target; if (macroName is VariableReferenceExpression) { macroName = new LiteralExpression(macroName.ToString()); } macroValue = assignExpression.Value; } else { var variableReference = mixinStatement.Value as MemberReferenceExpression; if (variableReference == null || !(variableReference.Target is VariableReferenceExpression) || !context.DeclaredParameters.Contains((((VariableReferenceExpression)variableReference.Target).Name.Text))) { logging.Error("Invalid syntax. Expecting: mixin macro Parameters.NameOfProperty or mixin macro nameOfProperty = value", mixinStatement.Span); macroName = new LiteralExpression("#INVALID_MACRO_NAME"); macroValue = mixinStatement.Value; } else { macroName = new LiteralExpression(variableReference.Member.Text); macroValue = mixinStatement.Value; } } Write("mixin.AddMacro("); VisitDynamic(macroName); Write(", "); VisitDynamic(macroValue); WriteLine(");"); break; case MixinStatementType.Compose: assignExpression = mixinStatement.Value as AssignmentExpression; if (assignExpression == null) { logging.Error("Expecting assign expression for composition", mixinStatement.Value.Span); return; } var addCompositionFunction = "PushComposition"; // If it's a +=, let's create or complete a ShaderArraySource if (assignExpression.Operator == AssignmentOperator.Addition) { addCompositionFunction = "PushCompositionArray"; } ExtractGenericParameters(assignExpression.Value, out mixinName, genericParameters); { OpenBrace(); WriteLinkLine(mixinStatement); Write("var __mixinToCompose__ = "); WriteMixinName(mixinName); WriteLine(";"); WriteLine("var __subMixin = new ShaderMixinSource();"); WriteLinkLine(mixinStatement); Write("context.").Write(addCompositionFunction).Write("(mixin, "); WriteStringOrExpression(assignExpression.Target); WriteLine(", __subMixin);"); WriteLinkLine(mixinStatement); Write("context.Mixin(__subMixin, __mixinToCompose__"); WriteGenericParameters(genericParameters); WriteLine(");"); WriteLinkLine(mixinStatement); WriteLine("context.PopComposition();"); CloseBrace(); } break; } }
public virtual void VisitMixinStatement(MixinStatement s) { VisitAbstractStmt (s); if(s.Attributes!=null && s.Attributes.Length != 0) foreach(var attr in s.Attributes) attr.Accept(this); if(s.MixinExpression != null) s.MixinExpression.Accept(this); }
public static DModule ParseMixinDeclaration(MixinStatement mx, ResolutionContext ctxt) { ISyntaxRegion sr; var literal = GetMixinContent(mx, ctxt, false, out sr); if (sr is DModule) { return((DModule)sr); } else if (literal == null) { return(null); } var ast = (DModule)DParser.ParseString(literal, true); mixinDeclCache.Add(ctxt, mx, ast); if (ast == null) { return(null); } foreach (var ch in ast) { if (mx.Attributes != null) { var dn = ch as DNode; if (dn != null) { if (dn.Attributes == null) { dn.Attributes = new List <DAttribute>(mx.Attributes); } else { dn.Attributes.AddRange(mx.Attributes); } } } ch.Parent = mx.ParentNode; } if (mx.Attributes != null) { foreach (var ss in ast.StaticStatements) { if (ss.Attributes == null) { ss.Attributes = mx.Attributes; } else { var attrs = new DAttribute[mx.Attributes.Length + ss.Attributes.Length]; mx.Attributes.CopyTo(attrs, 0); ss.Attributes.CopyTo(attrs, mx.Attributes.Length); } } } return(ast); }