void ParseActorHeading(Actor actor, TokenRange toks) { var template = toks.First(NonWhitespace); if (template.Value == "template") { var templateParams = range(template.Position + 1, toks.End) .First(NonWhitespace) .Assert("Invalid template declaration", t => t.Value == "<") .GetMatchingRangeIn(toks); actor.templateFormals = SplitParameterList(templateParams, ",") .Select(p => ParseVarDeclaration(p)) //< SOMEDAY: ? .ToArray(); toks = range(templateParams.End + 1, toks.End); } var staticKeyword = toks.First(NonWhitespace); if (staticKeyword.Value == "static") { actor.isStatic = true; toks = range(staticKeyword.Position + 1, toks.End); } var uncancellableKeyword = toks.First(NonWhitespace); if (uncancellableKeyword.Value == "UNCANCELLABLE") { actor.isUncancellable = true; toks = range(uncancellableKeyword.Position + 1, toks.End); } // Find the parameter list TokenRange paramRange = toks.Last(NonWhitespace) .Assert("Unexpected tokens after actor parameter list.", t => t.Value == ")" && t.ParenDepth == toks.First().ParenDepth) .GetMatchingRangeIn(toks); actor.parameters = SplitParameterList(paramRange, ",") .Select(p => ParseVarDeclaration(p)) .ToArray(); var name = range(toks.Begin, paramRange.Begin - 1).Last(NonWhitespace); actor.name = name.Value; // SOMEDAY: refactor? var returnType = range(toks.First().Position + 1, name.Position).SkipWhile(Whitespace); var retToken = returnType.First(); if (retToken.Value == "Future") { var ofType = returnType.Skip(1).First(NonWhitespace).Assert("Expected <", tok => tok.Value == "<").GetMatchingRangeIn(returnType); actor.returnType = str(NormalizeWhitespace(ofType)); toks = range(ofType.End + 1, returnType.End); } else if (retToken.Value == "void" /* && !returnType.Skip(1).Any(NonWhitespace)*/) { actor.returnType = null; toks = returnType.Skip(1); } else { throw new Error(actor.SourceLine, "Actor apparently does not return Future<T>"); } toks = toks.SkipWhile(Whitespace); if (!toks.IsEmpty) { if (toks.Last().Value == "::") { actor.nameSpace = str(range(toks.Begin, toks.End - 1)); } else { Console.WriteLine("Tokens: '{0}' {1} '{2}'", str(toks), toks.Count(), toks.Last().Value); throw new Error(actor.SourceLine, "Unrecognized tokens preceding parameter list in actor declaration"); } } }
void ParseActorHeading(Actor actor, TokenRange toks) { var template = toks.First(NonWhitespace); if (template.Value == "template") { var templateParams = range(template.Position + 1, toks.End) .First(NonWhitespace) .Assert("Invalid template declaration", t => t.Value == "<") .GetMatchingRangeIn(toks); actor.templateFormals = SplitParameterList(templateParams, ",") .Select(p => ParseVarDeclaration(p)) //< SOMEDAY: ? .ToArray(); toks = range(templateParams.End + 1, toks.End); } var attribute = toks.First(NonWhitespace); while (attribute.Value == "[") { var attributeContents = attribute.GetMatchingRangeIn(toks); var asArray = attributeContents.ToArray(); if (asArray.Length < 2 || asArray[0].Value != "[" || asArray[asArray.Length - 1].Value != "]") { throw new Error(actor.SourceLine, "Invalid attribute: Expected [[...]]"); } actor.attributes.Add("[" + str(NormalizeWhitespace(attributeContents)) + "]"); toks = range(attributeContents.End + 1, toks.End); attribute = toks.First(NonWhitespace); } var staticKeyword = toks.First(NonWhitespace); if (staticKeyword.Value == "static") { actor.isStatic = true; toks = range(staticKeyword.Position + 1, toks.End); } var uncancellableKeyword = toks.First(NonWhitespace); if (uncancellableKeyword.Value == "UNCANCELLABLE") { actor.SetUncancellable(); toks = range(uncancellableKeyword.Position + 1, toks.End); } // Find the parameter list TokenRange paramRange = toks.Last(NonWhitespace) .Assert("Unexpected tokens after actor parameter list.", t => t.Value == ")" && t.ParenDepth == toks.First().ParenDepth) .GetMatchingRangeIn(toks); actor.parameters = SplitParameterList(paramRange, ",") .Select(p => ParseVarDeclaration(p)) .ToArray(); var name = range(toks.Begin, paramRange.Begin - 1).Last(NonWhitespace); actor.name = name.Value; // SOMEDAY: refactor? var returnType = range(toks.First().Position + 1, name.Position).SkipWhile(Whitespace); var retToken = returnType.First(); if (retToken.Value == "Future") { var ofType = returnType.Skip(1).First(NonWhitespace).Assert("Expected <", tok => tok.Value == "<").GetMatchingRangeIn(returnType); actor.returnType = str(NormalizeWhitespace(ofType)); toks = range(ofType.End + 1, returnType.End); } else if (retToken.Value == "void" /* && !returnType.Skip(1).Any(NonWhitespace)*/) { actor.returnType = null; toks = returnType.Skip(1); } else { throw new Error(actor.SourceLine, "Actor apparently does not return Future<T>"); } toks = toks.SkipWhile(Whitespace); if (!toks.IsEmpty) { if (toks.Last().Value == "::") { actor.nameSpace = str(range(toks.Begin, toks.End - 1)); } else { Console.WriteLine("Tokens: '{0}' {1} '{2}'", str(toks), toks.Count(), toks.Last().Value); throw new Error(actor.SourceLine, "Unrecognized tokens preceding parameter list in actor declaration"); } } if (errorMessagePolicy.ActorsNoDiscardByDefault() && !actor.attributes.Contains("[[flow_allow_discard]]")) { if (actor.IsCancellable()) { actor.attributes.Add("[[nodiscard]]"); } } HashSet <string> knownFlowAttributes = new HashSet <string>(); knownFlowAttributes.Add("[[flow_allow_discard]]"); foreach (var flowAttribute in actor.attributes.Where(a => a.StartsWith("[[flow_"))) { if (!knownFlowAttributes.Contains(flowAttribute)) { throw new Error(actor.SourceLine, "Unknown flow attribute {0}", flowAttribute); } } actor.attributes = actor.attributes.Where(a => !a.StartsWith("[[flow_")).ToList(); }