From eeb2da5c9d1e017dd35147449808beed87afc8ab Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Mon, 9 Sep 2019 22:56:19 -0700 Subject: [PATCH] WIP - simple example compiles --- fdbrpc/FlowTests.actor.cpp | 15 +++++++++++++ flow/actorcompiler/ActorCompiler.cs | 33 +++++++++++++---------------- flow/actorcompiler/ActorParser.cs | 32 +++++++++++++++++++++++++--- flow/actorcompiler/ParseTree.cs | 2 ++ 4 files changed, 61 insertions(+), 21 deletions(-) diff --git a/fdbrpc/FlowTests.actor.cpp b/fdbrpc/FlowTests.actor.cpp index cb43aaed7b..f90a49d930 100644 --- a/fdbrpc/FlowTests.actor.cpp +++ b/fdbrpc/FlowTests.actor.cpp @@ -1207,3 +1207,18 @@ TEST_CASE("/fdbrpc/flow/wait_expression_after_cancel") ASSERT( a == 1 ); return Void(); } + +class Foo { +public: + explicit Foo(int x) : x(x) {} + Future foo() { return fooActor(this); } + ACTOR static Future fooActor(Foo* self); + +private: + int x; +}; + +ACTOR Future Foo::fooActor(Foo* self) { + wait(Future()); + return self->x; +} diff --git a/flow/actorcompiler/ActorCompiler.cs b/flow/actorcompiler/ActorCompiler.cs index 85437910d1..9377f8bf57 100644 --- a/flow/actorcompiler/ActorCompiler.cs +++ b/flow/actorcompiler/ActorCompiler.cs @@ -213,7 +213,6 @@ namespace actorcompiler public void Write(TextWriter writer, out int lines) { lines = 0; - //if (isTopLevel) writer.WriteLine("namespace {"); writer.WriteLine(memberIndentStr + "template<> struct Descriptor {{", descr.name); writer.WriteLine(memberIndentStr + "\tstatic StringRef typeName() {{ return LiteralStringRef(\"{0}\"); }}", descr.name); @@ -265,7 +264,6 @@ namespace actorcompiler lines++; } - //if (isTopLevel) writer.WriteLine("}"); // namespace } } @@ -276,7 +274,6 @@ namespace actorcompiler string sourceFile; List state; List callbacks = new List(); - bool isTopLevel; const string loopDepth0 = "int loopDepth=0"; const string loopDepth = "int loopDepth"; const int codeIndent = +2; @@ -287,12 +284,11 @@ namespace actorcompiler string This; bool generateProbes; - public ActorCompiler(Actor actor, string sourceFile, bool isTopLevel, bool lineNumbersEnabled, bool generateProbes) + public ActorCompiler(Actor actor, string sourceFile, bool lineNumbersEnabled, bool generateProbes) { this.actor = actor; this.sourceFile = sourceFile; - this.isTopLevel = isTopLevel; - this.LineNumbersEnabled = lineNumbersEnabled; + this.LineNumbersEnabled = false; this.generateProbes = generateProbes; FindState(); @@ -302,21 +298,13 @@ namespace actorcompiler string fullReturnType = actor.returnType != null ? string.Format("Future<{0}>", actor.returnType) : "void"; - if (actor.isForwardDeclaration) { - foreach (string attribute in actor.attributes) { - writer.Write(attribute + " "); - } - if (actor.isStatic) writer.Write("static "); - writer.WriteLine("{0} {3}{1}( {2} );", fullReturnType, actor.name, string.Join(", ", ParameterList()), actor.nameSpace==null ? "" : actor.nameSpace + "::"); - return; - } for (int i = 0; ; i++) { className = string.Format("{0}{1}Actor{2}", actor.name.Substring(0, 1).ToUpper(), actor.name.Substring(1), i!=0 ? i.ToString() : ""); - if (usedClassNames.Add(className)) + if (actor.isForwardDeclaration || usedClassNames.Add(className)) break; } @@ -326,6 +314,18 @@ namespace actorcompiler stateClassName = className + "State"; var fullStateClassName = stateClassName + GetTemplateActuals(new VarDeclaration { type = "class", name = fullClassName }); + if (actor.isForwardDeclaration) { + foreach (string attribute in actor.attributes) { + writer.Write(attribute + " "); + } + if (actor.isStatic) writer.Write("static "); + writer.WriteLine("{0} {3}{1}( {2} );", fullReturnType, actor.name, string.Join(", ", ParameterList()), actor.nameSpace==null ? "" : actor.nameSpace + "::"); + if (actor.enclosingClass.Length > 0) { + writer.WriteLine("template friend class {0};", stateClassName); + } + return; + } + var body = getFunction("", "body", loopDepth0); var bodyContext = new Context { target = body, @@ -353,8 +353,6 @@ namespace actorcompiler } bodyContext.catchFErr.WriteLine("loopDepth = 0;"); - if (isTopLevel) writer.WriteLine("namespace {"); - // The "State" class contains all state and user code, to make sure that state names are accessible to user code but // inherited members of Actor, Callback etc are not. writer.WriteLine("// This generated class is to be used only via {0}()", actor.name); @@ -399,7 +397,6 @@ namespace actorcompiler //WriteStartFunc(body, writer); WriteCancelFunc(writer); writer.WriteLine("};"); - if (isTopLevel) writer.WriteLine("}"); // namespace WriteTemplate(writer); LineNumber(writer, actor.SourceLine); foreach (string attribute in actor.attributes) { diff --git a/flow/actorcompiler/ActorParser.cs b/flow/actorcompiler/ActorParser.cs index f85e3ffa9b..2ff02fc176 100644 --- a/flow/actorcompiler/ActorParser.cs +++ b/flow/actorcompiler/ActorParser.cs @@ -255,6 +255,11 @@ namespace actorcompiler //showTokens(); } + class ClassContext { + public string name; + public int inBlocks; + } + public void Write(System.IO.TextWriter writer, string destFileName) { writer.NewLine = "\n"; @@ -266,6 +271,7 @@ namespace actorcompiler outLine++; } int inBlocks = 0; + Stack classContextStack = new Stack(); for(int i=0; i 0 ? classContextStack.Peek().name : ""; var actorWriter = new System.IO.StringWriter(); actorWriter.NewLine = "\n"; - new ActorCompiler(actor, sourceFile, inBlocks==0, LineNumbersEnabled, generateProbes).Write(actorWriter); + new ActorCompiler(actor, sourceFile, LineNumbersEnabled, generateProbes).Write(actorWriter); string[] actorLines = actorWriter.ToString().Split('\n'); bool hasLineNumber = false; @@ -322,10 +329,29 @@ namespace actorcompiler outLine++; } } + else if (tokens[i].Value == "class" || tokens[i].Value == "struct") + { + writer.Write(tokens[i].Value); + var toks = range(i+1, tokens.Length).SkipWhile(Whitespace); + if (!toks.IsEmpty) + { + classContextStack.Push(new ClassContext{name = toks.First().Value, inBlocks = inBlocks }); + } + } else { - if (tokens[i].Value == "{") inBlocks++; - else if (tokens[i].Value == "}") inBlocks--; + if (tokens[i].Value == "{") + { + inBlocks++; + } + else if (tokens[i].Value == "}") + { + inBlocks--; + if (classContextStack.Count > 0 && classContextStack.Peek().inBlocks == inBlocks) + { + classContextStack.Pop(); + } + } writer.Write(tokens[i].Value); outLine += tokens[i].Value.Count(c => c == '\n'); } diff --git a/flow/actorcompiler/ParseTree.cs b/flow/actorcompiler/ParseTree.cs index 4f69d33e6e..8c44ed7aa7 100644 --- a/flow/actorcompiler/ParseTree.cs +++ b/flow/actorcompiler/ParseTree.cs @@ -226,6 +226,8 @@ namespace actorcompiler public List attributes = new List(); public string returnType; public string name; + // "" if there is not enclosing class + public string enclosingClass; public VarDeclaration[] parameters; public VarDeclaration[] templateFormals; //< null if not a template public CodeBlock body;