rta: do not enter in annotations
[nit.git] / src / syntax / extern_inline.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012 <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 foreign code blocks using the Nit FFI
18 module extern_inline
19
20 intrude import mmbuilder
21 import syntax_base
22 import primitive_info
23
24 # Extern code segment
25 class ExternCode
26 var language : nullable String
27 var code : String
28 var location : nullable Location
29 end
30
31 redef class MMModule
32 # extern code blocks in module
33 var extern_code_blocks : Set[ExternCode] = new HashSet[ExternCode]
34 redef var uses_ffi : Bool = false
35 end
36
37 redef class MMLocalClass
38 # extern equivalent of class
39 var extern_type : nullable ExternCode = null
40 end
41
42 redef class MMMethod
43 # extern code bodu of extern method
44 var extern_implementation : nullable ExternCode = null
45 end
46
47 redef class TExternCodeSegment
48 # removes `{ and `} and return code of interest
49 fun code : String do
50 return text.substring( 2, text.length-4 )
51 end
52 end
53
54 redef class AExternCodeBlock
55 fun to_extern_code : ExternCode
56 do
57 var language
58 if n_in_language == null then
59 language = null
60 else
61 var text = n_in_language.n_string.text
62 language = text.substring( 1, text.length-2 )
63 end
64 return new ExternCode( language, n_extern_code_segment.code, n_extern_code_segment.location )
65 end
66 end
67
68 redef class AExternPropdef
69 redef fun accept_property_verifier(v)
70 do
71 super
72
73 # Extern method implementation
74 var n_extern_code_block = self.n_extern_code_block
75 if n_extern_code_block != null then
76 if not method.is_extern then
77 v.error( n_extern_code_block,
78 "Cannot implement the non extern method {method.full_name} with extern code" )
79 else
80 method.extern_implementation = n_extern_code_block.to_extern_code
81 method.mmmodule.uses_ffi = true
82 end
83 end
84 end
85 end
86
87 redef class AStdClassdef
88 redef fun accept_property_verifier(v)
89 do
90 super
91
92 # Extern type of extern classes
93 var extern_code_block = self.n_extern_code_block
94 if extern_code_block != null then
95 if not local_class.global.is_extern then
96 v.error( extern_code_block,
97 "Cannot define an extern equivalent in the non extern class {local_class.name}" )
98 else
99 local_class.extern_type = extern_code_block.to_extern_code
100 local_class.mmmodule.uses_ffi = true
101 end
102 end
103 end
104 end
105
106 redef class MMSrcModule
107 # Syntax analysis and MM construction for the module
108 # Require that supermodules are processed
109 redef fun do_mmbuilder(tc: ToolContext)
110 do
111 super
112
113 # extern code blocks
114 if not node.n_extern_code_blocks.is_empty then uses_ffi = true
115 for n_extern_code_block in node.n_extern_code_blocks do
116 extern_code_blocks.add( n_extern_code_block.to_extern_code )
117 end
118 end
119 end