Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / frontend / actors_injection_phase.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 #
6 # http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 # Injects model for the classes annotated with "is actor" so
15 # that the later generated code can be properly used for compilation
16 module actors_injection_phase
17
18 import modelize_class
19 intrude import modelize_property
20 import parser_util
21
22 redef class ModelBuilder
23 redef fun build_a_mclass(nmodule, nclassdef)
24 do
25 super
26
27 # Catch the wanted annotation
28 var at = nclassdef.get_single_annotation("actor", self)
29 if at == null then return
30
31 # Get context information
32 var mod = nmodule.mmodule
33 if mod == null then return
34 var mclass = nclassdef.mclass
35 if mclass == null then return
36 if mclass.intro_mmodule != mod then
37 error(at, "`actor` can only be used at introductions.")
38 return
39 end
40
41 var l = at.location
42
43 var injected_name = "Proxy"
44
45 # Create the actor class
46 var actor_class = new MClass(mod, injected_name + mclass.name, l, null, concrete_kind, public_visibility)
47 var actor_class_definition = new MClassDef(mod, actor_class.mclass_type, l)
48 actor_class_definition.set_supertypes([mod.object_type])
49 var proxy_classes = mclass.model.get_mclasses_by_name("Proxy")
50 assert proxy_classes != null
51 var proxy_class = proxy_classes.first
52 actor_class_definition.supertypes.add(proxy_class.mclass_type)
53
54 # Register it
55 mclass.actor = actor_class
56 end
57
58 redef fun build_properties(nclassdef)
59 do
60 if nclassdef.build_properties_is_done then return
61 super
62
63 # Get context information
64 var mclass = nclassdef.mclass
65 if mclass == null then return
66 var mclass_def = nclassdef.mclassdef
67 if mclass_def == null then return
68
69 var actor_mclass = mclass.actor
70 if actor_mclass == null then return
71 var actor_mclass_def = actor_mclass.mclassdefs.first
72
73 # Adds an `async` attribute in the worker class which is the actor class
74 if mclass_def.is_intro then
75 var async = new MMethod(mclass_def, "async", mclass.location, public_visibility)
76 var async_def = new MMethodDef(mclass_def, async, mclass.location)
77 async_def.msignature = new MSignature(new Array[MParameter], actor_mclass.mclass_type)
78 async_def.is_abstract = true
79 end
80
81 # For each introduced property
82 for method in mclass_def.mpropdefs do
83 if not method isa MMethodDef then continue
84 if not method.is_intro then continue
85 if method.name == "async" then continue
86
87 # Create a proxied method
88 var actor_method = new MMethod(actor_mclass_def, method.name, actor_mclass.location, method.mproperty.visibility)
89 var actor_method_def = new MMethodDef(actor_mclass_def, actor_method, actor_mclass.location)
90
91 # Get the signature of the method ( replacing the return value with a Future if there is one)
92 var signature = method.msignature
93 if signature != null then
94 var parameters = signature.mparameters
95 var s_return_type = signature.return_mtype
96 if s_return_type != null then
97 var future_mclasses = mclass_def.model.get_mclasses_by_name("Future")
98 assert future_mclasses != null
99 var future_mclass = future_mclasses.first
100 var return_type = future_mclass.get_mtype([s_return_type])
101 actor_method_def.msignature = new MSignature(parameters, return_type)
102 else
103 actor_method_def.msignature = new MSignature(parameters, null)
104 end
105 end
106 actor_method_def.is_abstract = true
107 end
108 end
109 end
110
111 redef class MClass
112 # Adding the actor class to a class annotated with "is actor"
113 var actor: nullable MClass = null
114 end