// Generates a class declaration for the current alt and its subtypes internal void GenerateOutput(ref LNodeList list) { bool isAbstract = _classAttrs.Any(a => a.IsIdNamed(S.Abstract)); var baseParts = new List <AdtParam>(); for (var type = ParentType; type != null; type = type.ParentType) { baseParts.InsertRange(0, type.Parts); } var allParts = baseParts.Concat(Parts); var initialization = Parts.Select(p => LNode.Call(CodeSymbols.Assign, LNode.List(LNode.Call(CodeSymbols.Dot, LNode.List(LNode.Id(CodeSymbols.This), p.NameId)).SetStyle(NodeStyle.Operator), p.NameId)).SetStyle(NodeStyle.Operator)).ToList(); if (baseParts.Count > 0) { initialization.Insert(0, F.Call(S.Base, baseParts.Select(p => p.NameId))); } var args = new LNodeList(allParts.Select(p => p.OriginalDecl)); if (!_constructorAttrs.Any(a => a.IsIdNamed(S.Public))) { _constructorAttrs.Add(F.Id(S.Public)); } LNode constructor = LNode.Call(LNode.List(_constructorAttrs), CodeSymbols.Constructor, LNode.List(LNode.Missing, _typeNameStem, LNode.Call(CodeSymbols.AltList, LNode.List(args)), LNode.Call(CodeSymbols.Braces, LNode.List().AddRange(initialization).AddRange(_extraConstrLogic)).SetStyle(NodeStyle.StatementBlock))); var outBody = new LNodeList(); outBody.Add(constructor); outBody.AddRange(Parts.Select(p => p.GetFieldDecl())); outBody.AddRange(baseParts.Select(p => GetWithFn(p, isAbstract, S.Override, allParts))); outBody.AddRange(Parts.Select(p => GetWithFn(p, isAbstract, _children.Count > 0 ? S.Virtual : null, allParts))); outBody.AddRange(Parts.WithIndexes() .Where(kvp => kvp.Value.NameId.Name.Name != "Item" + (baseParts.Count + kvp.Key + 1)) .Select(kvp => kvp.Value.GetItemDecl(baseParts.Count + kvp.Key + 1))); outBody.AddRange(_classBody); list.Add(LNode.Call(LNode.List(_classAttrs), CodeSymbols.Class, LNode.List(TypeName, LNode.Call(CodeSymbols.AltList, LNode.List(BaseTypes)), LNode.Call(CodeSymbols.Braces, LNode.List(outBody)).SetStyle(NodeStyle.StatementBlock)))); if (_genericArgs.Count > 0 && Parts.Count > 0) { var argNames = allParts.Select(p => p.NameId); list.Add(LNode.Call(LNode.List().AddRange(_classAttrs).Add(LNode.Id(CodeSymbols.Static)).Add(LNode.Id(CodeSymbols.Partial)), CodeSymbols.Class, LNode.List(_typeNameStem, LNode.Call(CodeSymbols.AltList), LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(LNode.List(LNode.Id(CodeSymbols.Public), LNode.Id(CodeSymbols.Static)), CodeSymbols.Fn, LNode.List(TypeNameWithoutAttrs, LNode.Call(CodeSymbols.Of, LNode.List().Add(LNode.Id((Symbol)"New")).AddRange(_genericArgs)).SetStyle(NodeStyle.Operator), LNode.Call(CodeSymbols.AltList, LNode.List(args)), LNode.Call(CodeSymbols.Braces, LNode.List(LNode.Call(CodeSymbols.Return, LNode.List(LNode.Call(CodeSymbols.New, LNode.List(LNode.Call(TypeNameWithoutAttrs, LNode.List(argNames)))))))).SetStyle(NodeStyle.StatementBlock))))).SetStyle(NodeStyle.StatementBlock)))); } foreach (var child in _children) { child.GenerateOutput(ref list); } }
private void AddUserAction(LNodeList actions) { int i = _target.Count; _target.AddRange(actions); if (actions.Any(stmt => stmt.Range.StartIndex > 0)) { if (LLPG.AddCsLineDirectives) { // Remove folder name. This only makes sense if the output // file and input file are in the same folder; sadly we have // no access to the output file name, but as of 2015-05 it's // always true that the output file will be in the same folder. string filename = System.IO.Path.GetFileName(_target[i].Range.Source.FileName); var newline = F.Id(S.TriviaNewline); int line = 0; for (; i < _target.Count; i++, line++) { var r = _target[i].Range; if (line != r.Start.Line) { line = r.Start.Line; if (line <= 0) // sometimes occurs for generated `return result` statement { _target.Insert(i++, F.Trivia(S.CsPPRawText, "#line default")); } else { _target.Insert(i++, F.Trivia(S.CsPPRawText, "#line " + line + " " + Ecs.EcsNodePrinter.PrintString(filename, '"'))); } } } if (line > 1) { _target.Add(F.Trivia(S.CsPPRawText, "#line default")); } } else { _target[i] = _target[i].PlusAttr(F.Trivia(S.TriviaSLComment, string.Format(" line {0}", _target[i].Range.Start.Line))); } } }
LNode MaybeQuoteList(LNodeList list, bool isAttributes = false) { if (isAttributes && _ignoreTrivia) { list = list.SmartWhere(n => !n.IsTrivia || n.IsIdNamed(S.TriviaInParens)); } if (list.IsEmpty) { return(null); } else if (_doSubstitutions && list.Any(a => VarArgExpr(a) != null)) { if (list.Count == 1) { return(F.Call(LNode_List, VarArgExpr(list[0]))); } // If you write something like quote(Foo($x, $(...y), $z)), a special // output style is used to accommodate the variable argument list. LNode argList = F.Call(LNode_List); foreach (LNode arg in list) { var vae = VarArgExpr(arg); if (vae != null) { argList = F.Call(F.Dot(argList, F.Id("AddRange")), vae); } else { argList = F.Call(F.Dot(argList, F.Id("Add")), Quote(arg)); } } return(argList); } else { return(F.Call(LNode_List, list.SmartSelect(item => Quote(item)))); } }