Beispiel #1
0
        void ParseTestCaseHeading(Actor actor, TokenRange toks)
        {
            actor.isStatic = true;

            // The parameter(s) to the TEST_CASE macro are opaque to the actor compiler
            TokenRange paramRange = toks.Last(NonWhitespace)
                                    .Assert("Unexpected tokens after test case parameter list.",
                                            t => t.Value == ")" && t.ParenDepth == toks.First().ParenDepth)
                                    .GetMatchingRangeIn(toks);

            actor.testCaseParameters = str(paramRange);

            actor.name       = "flowTestCase" + toks.First().SourceLine;
            actor.parameters = new VarDeclaration[] { };
            actor.returnType = "Void";
        }
Beispiel #2
0
        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");
                }
            }
        }
Beispiel #3
0
        IEnumerable <Token> NormalizeWhitespace(IEnumerable <Token> tokens)
        {
            bool inWhitespace = false;
            bool leading      = true;

            foreach (var tok in tokens)
            {
                if (!tok.IsWhitespace)
                {
                    if (inWhitespace && !leading)
                    {
                        yield return new Token {
                                   Value = " "
                        }
                    }
                    ;
                    inWhitespace = false;
                    yield return(tok);

                    leading = false;
                }
                else
                {
                    inWhitespace = true;
                }
            }
        }

        void ParseDeclaration(TokenRange tokens,
                              out Token name,
                              out TokenRange type,
                              out TokenRange initializer,
                              out bool constructorSyntax)
        {
            initializer = null;
            TokenRange beforeInitializer = tokens;

            constructorSyntax = false;

            Token equals = AngleBracketParser.NotInsideAngleBrackets(tokens)
                           .FirstOrDefault(t => t.Value == "=" && t.ParenDepth == tokens.First().ParenDepth);

            if (equals != null)
            {
                // type name = initializer;
                beforeInitializer = range(tokens.Begin, equals.Position);
                initializer       = range(equals.Position + 1, tokens.End);
            }
            else
            {
                Token paren = AngleBracketParser.NotInsideAngleBrackets(tokens)
                              .FirstOrDefault(t => t.Value == "(");
                if (paren != null)
                {
                    // type name(initializer);
                    constructorSyntax = true;
                    beforeInitializer = range(tokens.Begin, paren.Position);
                    initializer       =
                        range(paren.Position + 1, tokens.End)
                        .TakeWhile(t => t.ParenDepth > paren.ParenDepth);
                }
            }
            name = beforeInitializer.Last(NonWhitespace);
            if (beforeInitializer.Begin == name.Position)
            {
                throw new Error(beforeInitializer.First().SourceLine, "Declaration has no type.");
            }
            type = range(beforeInitializer.Begin, name.Position);
        }

        VarDeclaration ParseVarDeclaration(TokenRange tokens)
        {
            Token      name;
            TokenRange type, initializer;
            bool       constructorSyntax;

            ParseDeclaration(tokens, out name, out type, out initializer, out constructorSyntax);
            return(new VarDeclaration
            {
                name = name.Value,
                type = str(NormalizeWhitespace(type)),
                initializer = initializer == null ? "" : str(NormalizeWhitespace(initializer)),
                initializerConstructorSyntax = constructorSyntax
            });
        }
Beispiel #4
0
        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();
        }