RTA: force primitive types to be alive
[nit.git] / src / common_ffi / c.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2012-2014 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 # Support for nesting C code within a Nit program using its FFI
18 module c
19
20 import ffi_base
21
22 redef class FFILanguageAssignationPhase
23 var c_language: FFILanguage = new CLanguage(self)
24 end
25
26 class CLanguage
27 super FFILanguage
28
29 redef fun identify_language(n) do return n.is_c
30
31 redef fun compile_module_block(block, ecc, nmodule)
32 do
33 if block.is_c_header then
34 ecc.header_custom.add( block.location.as_line_pragma )
35 ecc.header_custom.add( block.code )
36 else if block.is_c_body then
37 ecc.body_custom.add( block.location.as_line_pragma )
38 ecc.body_impl.add( block.code )
39 end
40 end
41
42 redef fun compile_extern_method(block, m, ecc, nmodule)
43 do
44 var fc = new ExternCFunction(m, nmodule.mmodule.as(not null))
45 fc.decls.add( block.location.as_line_pragma )
46 fc.exprs.add( block.code )
47 ecc.add_exported_function( fc )
48 end
49
50 redef fun compile_extern_class(block, m, ecc, nmodule) do end
51
52 redef fun get_ftype(block, m) do return new ForeignCType(block.code)
53
54 redef fun compile_callback(callback, nmodule, mmodule, ecc)
55 do
56 callback.compile_callback_to_c(mmodule, ecc)
57 end
58 end
59
60 redef class AExternCodeBlock
61 fun is_c: Bool do return language_name == null or
62 language_name_lowered == "c" or language_name_lowered.has_prefix( "c " )
63
64 fun is_c_body: Bool do return language_name == null or
65 language_name_lowered == "c" or language_name_lowered == "c body"
66
67 fun is_c_header: Bool do return language_name_lowered == "c header"
68 end
69
70 redef class Location
71 fun as_line_pragma: String do return "#line {line_start} \"{file.filename}\"\n"
72 end
73
74 redef class AModule
75 var c_compiler_options writable = ""
76 var c_linker_options writable = ""
77 end
78
79 # An extern C file to compile
80 class ExternCFile
81 super ExternFile
82
83 init (filename, cflags: String)
84 do
85 super filename
86
87 self.cflags = cflags
88 end
89
90 # Additionnal specific CC compiler -c flags
91 var cflags: String
92
93 redef fun hash do return filename.hash
94 redef fun ==(o) do return o isa ExternCFile and filename == o.filename
95 end
96
97 class ForeignCType
98 super ForeignType
99
100 redef var ctype: String
101
102 init(ctype: String)
103 do
104 self.ctype = ctype
105 end
106 end
107
108 redef class NitniCallback
109 fun compile_callback_to_c(nmodule: MModule, ffi_ccu: CCompilationUnit) do end
110 end
111
112 redef class Object
113 # Context when calling user C code from generated code
114 fun to_c_call_context: ToCCallContext do return once new ToCCallContext
115
116 # Context when calling generated code from user C code
117 fun from_c_call_context: FromCCallContext do return once new FromCCallContext
118 end
119
120 redef class MExplicitCall
121 redef fun compile_callback_to_c(mmodule, ffi_ccu)
122 do
123 var mproperty = mproperty.as(MMethod)
124
125 var full_cname = mproperty.build_cname(recv_mtype, mmodule, null, long_signature)
126 var friendly_cname = mproperty.build_cname(recv_mtype, mmodule, null, short_signature)
127 ffi_ccu.body_decl.add("#define {friendly_cname} {full_cname}\n")
128 end
129 end
130
131 # Context when calling user C code from generated code
132 class ToCCallContext
133 super CallContext
134
135 private init do end
136
137 redef fun name_mtype(mtype)
138 do
139 if mtype isa MClassType and mtype.mclass.kind == extern_kind then return "void *"
140 return mtype.cname
141 end
142 end
143
144 # Context when calling generated code from user C code
145 class FromCCallContext
146 super CallContext
147
148 private init do end
149
150 redef fun name_mtype(mtype) do return mtype.cname
151 end
152
153 class ExternCFunction
154 super CFunction
155
156 var method: AExternPropdef
157
158 init (method: AExternPropdef, mmodule: MModule)
159 do
160 self.method = method
161
162 var recv_mtype = method.mpropdef.mclassdef.bound_mtype
163 var csignature = method.mpropdef.mproperty.build_csignature(recv_mtype, mmodule, "___impl", long_signature, from_c_call_context)
164
165 super( csignature )
166 end
167 end