Introduce parallelization_phase to deal with the "threaded" annotation
authorBlackMinou <romain.chanoir@viacesi.fr>
Thu, 26 Mar 2015 06:30:14 +0000 (07:30 +0100)
committerBlackMinou <romain.chanoir@viacesi.fr>
Sun, 29 Mar 2015 04:21:44 +0000 (06:21 +0200)
Signed-off-by: BlackMinou <romain.chanoir@viacesi.fr>

src/frontend/parallelization_phase.nit [new file with mode: 0644]

diff --git a/src/frontend/parallelization_phase.nit b/src/frontend/parallelization_phase.nit
new file mode 100644 (file)
index 0000000..7da80ff
--- /dev/null
@@ -0,0 +1,110 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Romain Chanoir <romain.chanoir@viacesi.fr>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+# Phase generating threads for functions annotated with `threaded` annotation
+module parallelization_phase
+
+private import parser_util
+import modelize
+import astbuilder
+private import annotation
+
+redef class ToolContext
+       # Transforms a function annotated with "threaded"
+       var parallelization_phase: Phase = new ParallelizationPhase(self, null)
+end
+
+private class ParallelizationPhase
+       super Phase
+
+       redef fun process_annotated_node(nmethdef, nat)
+       do
+               if nat.n_atid.n_id.text != "threaded" then return
+
+               if not nmethdef isa AMethPropdef then
+                       toolcontext.error(nmethdef.location, "Syntax error: only a method can be threaded.")
+                       return
+               end
+               if nmethdef.n_signature.n_params.length != 0 then
+                       toolcontext.error(nmethdef.location, "Syntax error: parametrized method not supported yet.")
+                       return
+               end
+               if nmethdef.n_signature.n_type != null then
+                       toolcontext.error(nmethdef.location, "Syntax error: method with a return value not supported yet.")
+                       return
+               end
+
+               # Get the module associated with this method
+               var amod = nmethdef.parent.parent
+               assert amod isa AModule
+
+               # Construct the name of the generated class
+               var modulename = amod.n_moduledecl.n_name.n_id.text
+               var classname = "Threaded" + modulename
+
+               # Try to get the name of the class
+               if nmethdef.parent isa AStdClassdef then
+                       classname += nmethdef.parent.as(AStdClassdef).n_id.text
+               end
+
+               # Try to get the name of the method
+               if nmethdef.n_methid isa AIdMethid then
+                       classname += nmethdef.n_methid.as(AIdMethid).n_id.text
+               end
+
+               # Create a string corresponding to the threaded class
+               var s ="""
+class {{{classname}}}
+       super Thread
+
+       redef fun main do
+       end
+end
+"""
+
+               # Parse newly obtained classdef
+               var classdef = toolcontext.parse_classdef(s).as(AStdClassdef)
+
+               # Get the `main` fun of the class
+               var mainfun : nullable AMethPropdef = null
+               for prop in classdef.n_propdefs do
+                       if prop isa AMethPropdef then mainfun = prop
+               end
+               assert mainfun != null
+
+               # Make the statements from `main` fun be the statements from the "threaded" fun
+               mainfun.n_block = nmethdef.n_block
+
+               # Add "return null" to the end of the `main` function
+               var s_nullreturn = "return null"
+               var nullreturn = toolcontext.parse_something(s_nullreturn)
+               assert nullreturn isa AExpr
+               mainfun.n_block.as(ABlockExpr).n_expr.add(nullreturn)
+
+               # Create new body for the annotated fun
+               var s_newbody ="""
+var thread = new {{{classname}}}
+thread.start
+"""
+
+               var newbody = toolcontext.parse_something(s_newbody)
+               nmethdef.n_block = newbody.as(ABlockExpr)
+
+               # Add the new class to the module
+               amod.n_classdefs.add(classdef)
+       end
+end