pep8analysis: add copyright info for viz.js
[nit.git] / src / common_ffi / extern_classes.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 # Manages all extern classes and their associated foreign type.
18 module extern_classes
19
20 import ffi_base
21
22 redef class ToolContext
23 var extern_classes_typing_phase_ast: Phase = new ExternClassesTypingPhaseAst(self, [ffi_language_assignation_phase])
24
25 var extern_classes_typing_phase_model: Phase = new ExternClassesTypingPhaseModel(self, [extern_classes_typing_phase_ast, modelize_class_phase])
26 end
27
28 # Assigns the `ftype` to class definitions, work on the AST only
29 private class ExternClassesTypingPhaseAst
30 super Phase
31
32 redef fun process_nclassdef(nclassdef)
33 do
34 if not nclassdef isa AStdClassdef then return
35
36 var code_block = nclassdef.n_extern_code_block
37 if code_block == null then return
38
39 if nclassdef.n_kwredef != null then
40 # A redef cannot specifiy a different extern type
41 toolcontext.error(nclassdef.location, "Only the introduction of a class can specify an extern type.")
42 return
43 end
44
45 var ftype = code_block.language.get_ftype(code_block, nclassdef)
46 nclassdef.ftype_cache = ftype
47 nclassdef.ftype_computed = true
48 end
49 end
50
51 redef class AClassdef
52 private var ftype_cache: nullable ForeignType = null
53 private var ftype_computed = false
54
55 # Associated extern type when defined on this classdef
56 fun ftype: nullable ForeignType
57 do
58 return ftype_cache
59 end
60 end
61
62 private class ExternClassesTypingPhaseModel
63 super Phase
64
65 redef fun process_nclassdef(nclassdef)
66 do
67 if not nclassdef isa AStdClassdef then return
68
69 var mclassdef = nclassdef.mclassdef
70 var mclass = nclassdef.mclass
71
72 # We only need to do this once per class
73 if mclass.intro != mclassdef then return
74
75 if mclass.kind != extern_kind then return
76
77 mclass.compute_ftype(self)
78 end
79 end
80
81 redef class MClass
82 private var ftype_cache: nullable ForeignType = null
83 private var ftype_computed = false
84
85 # Extern type associated to this class according to specialisation
86 fun ftype: nullable ForeignType do return ftype_cache
87
88 redef fun ctype do return ftype_cache.ctype
89
90 # Type in C of the extern class
91 # If not defined in the intro of this class will look in super-classes
92 # FIXME this only supports type definition at intro, extend to superclasses by redef
93 private fun compute_ftype(v: ExternClassesTypingPhaseModel): nullable ForeignType
94 do
95 if ftype_computed then return ftype_cache
96 if kind != extern_kind then return null
97
98 # base case
99 if name == "Pointer" then
100 ftype_cache = new ForeignType
101 ftype_computed = true
102 return ftype_cache
103 end
104
105 var intro_nclassdef = v.toolcontext.modelbuilder.mclassdef2nclassdef[intro]
106 var ftype = intro_nclassdef.ftype
107 if ftype == null then
108 var ftype_b: nullable ForeignType = null # FIXME hack to circumvent bug where ftype is typed null
109
110 # look in super classes
111 for s in in_hierarchy(intro.mmodule).direct_greaters do
112 var super_ftype = s.compute_ftype(v)
113 if super_ftype != null then
114 if ftype_b == null then
115 ftype_b = super_ftype
116 continue
117 else
118 # detect conflict
119 if super_ftype != ftype_b then
120 v.toolcontext.error(null, "Extern type conflict in {self}")
121 return null
122 end
123 end
124 end
125 end
126
127 ftype = ftype_b
128 end
129
130 ftype_cache = ftype
131 ftype_computed = true
132 return ftype
133 end
134 end