@@ -110,7 +110,7 @@ pub fn translate(
110
110
return context .err ;
111
111
}
112
112
113
- try appendToken (& context , .Eof , "" );
113
+ _ = try appendToken (& context , .Eof , "" );
114
114
tree .source = source_buffer .toOwnedSlice ();
115
115
return tree ;
116
116
}
@@ -149,7 +149,7 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
149
149
}
150
150
151
151
fn visitFnDecl (c : * Context , fn_decl : * const ZigClangFunctionDecl ) Error ! void {
152
- const fn_name = c .str (ZigClangDecl_getName_bytes_begin (@ptrCast (* const ZigClangDecl , fn_decl )));
152
+ const fn_name = try c .str (ZigClangDecl_getName_bytes_begin (@ptrCast (* const ZigClangDecl , fn_decl )));
153
153
154
154
// TODO The C++ code has this:
155
155
//if (get_global(c, fn_name)) {
@@ -160,116 +160,207 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
160
160
const fn_decl_loc = ZigClangFunctionDecl_getLocation (fn_decl );
161
161
const proto_node = transQualType (c , ZigClangFunctionDecl_getType (fn_decl ), fn_decl_loc ) catch | e | switch (e ) {
162
162
error .UnsupportedType = > {
163
- try emitWarning (c , fn_decl_loc , "unable to resolve prototype of function '{}'" , fn_name );
163
+ try failDecl (c , fn_decl_loc , fn_name , "unable to resolve prototype of function" );
164
164
return ;
165
165
},
166
166
else = > return e ,
167
167
};
168
+ const semi_tok = try appendToken (c , .Semicolon , ";" );
168
169
169
- try emitWarning (c , fn_decl_loc , "TODO implement translate-c for function decls" );
170
+ try emitWarning (c , fn_decl_loc , "TODO implement more translate-c for function decls" );
171
+
172
+ try c .tree .root_node .decls .push (proto_node );
170
173
}
171
174
172
175
fn transQualType (c : * Context , qt : ZigClangQualType , source_loc : ZigClangSourceLocation ) ! * ast.Node {
173
176
return transType (c , ZigClangQualType_getTypePtr (qt ), source_loc );
174
177
}
175
178
179
+ const RestorePoint = struct {
180
+ context : * Context ,
181
+ token_index : ast.TokenIndex ,
182
+ src_buf_index : usize ,
183
+
184
+ fn activate (self : RestorePoint ) void {
185
+ self .context .tree .tokens .shrink (self .token_index );
186
+ self .context .source_buffer .shrink (self .src_buf_index );
187
+ }
188
+ };
189
+
190
+ fn makeRestorePoint (c : * Context ) RestorePoint {
191
+ return RestorePoint {
192
+ .context = c ,
193
+ .token_index = c .tree .tokens .len ,
194
+ .src_buf_index = c .source_buffer .len (),
195
+ };
196
+ }
197
+
176
198
fn transType (c : * Context , ty : * const ZigClangType , source_loc : ZigClangSourceLocation ) ! * ast.Node {
199
+ const rp = makeRestorePoint (c );
200
+
177
201
switch (ZigClangType_getTypeClass (ty )) {
178
202
.Builtin = > {
179
203
const builtin_ty = @ptrCast (* const ZigClangBuiltinType , ty );
180
204
switch (ZigClangBuiltinType_getKind (builtin_ty )) {
181
- else = > {
182
- try emitWarning (c , source_loc , "unsupported builtin type" );
183
- return error .UnsupportedType ;
184
- },
205
+ else = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported builtin type" ),
185
206
}
186
207
},
187
208
.FunctionProto = > {
188
209
const fn_ty = @ptrCast (* const ZigClangFunctionType , ty );
189
210
const cc = switch (ZigClangFunctionType_getCallConv (fn_ty )) {
190
211
.C = > CallingConvention .c ,
191
212
.X86StdCall = > CallingConvention .stdcall ,
192
- .X86FastCall = > {
193
- try emitWarning (c , source_loc , "unsupported calling convention: x86 fastcall" );
194
- return error .UnsupportedType ;
195
- },
196
- .X86ThisCall = > {
197
- try emitWarning (c , source_loc , "unsupported calling convention: x86 thiscall" );
198
- return error .UnsupportedType ;
199
- },
200
- .X86VectorCall = > {
201
- try emitWarning (c , source_loc , "unsupported calling convention: x86 vectorcall" );
202
- return error .UnsupportedType ;
203
- },
204
- .X86Pascal = > {
205
- try emitWarning (c , source_loc , "unsupported calling convention: x86 pascal" );
206
- return error .UnsupportedType ;
207
- },
208
- .Win64 = > {
209
- try emitWarning (c , source_loc , "unsupported calling convention: win64" );
210
- return error .UnsupportedType ;
211
- },
212
- .X86_64SysV = > {
213
- try emitWarning (c , source_loc , "unsupported calling convention: x86 64sysv" );
214
- return error .UnsupportedType ;
215
- },
216
- .X86RegCall = > {
217
- try emitWarning (c , source_loc , "unsupported calling convention: x86 reg" );
218
- return error .UnsupportedType ;
219
- },
220
- .AAPCS = > {
221
- try emitWarning (c , source_loc , "unsupported calling convention: aapcs" );
222
- return error .UnsupportedType ;
223
- },
224
- .AAPCS_VFP = > {
225
- try emitWarning (c , source_loc , "unsupported calling convention: aapcs-vfp" );
226
- return error .UnsupportedType ;
227
- },
228
- .IntelOclBicc = > {
229
- try emitWarning (c , source_loc , "unsupported calling convention: intel_ocl_bicc" );
230
- return error .UnsupportedType ;
231
- },
232
- .SpirFunction = > {
233
- try emitWarning (c , source_loc , "unsupported calling convention: SPIR function" );
234
- return error .UnsupportedType ;
235
- },
236
- .OpenCLKernel = > {
237
- try emitWarning (c , source_loc , "unsupported calling convention: OpenCLKernel" );
238
- return error .UnsupportedType ;
239
- },
240
- .Swift = > {
241
- try emitWarning (c , source_loc , "unsupported calling convention: Swift" );
242
- return error .UnsupportedType ;
243
- },
244
- .PreserveMost = > {
245
- try emitWarning (c , source_loc , "unsupported calling convention: PreserveMost" );
246
- return error .UnsupportedType ;
247
- },
248
- .PreserveAll = > {
249
- try emitWarning (c , source_loc , "unsupported calling convention: PreserveAll" );
250
- return error .UnsupportedType ;
251
- },
252
- .AArch64VectorCall = > {
253
- try emitWarning (c , source_loc , "unsupported calling convention: AArch64VectorCall" );
254
- return error .UnsupportedType ;
255
- },
213
+ .X86FastCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 fastcall" ),
214
+ .X86ThisCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 thiscall" ),
215
+ .X86VectorCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 vectorcall" ),
216
+ .X86Pascal = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 pascal" ),
217
+ .Win64 = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: win64" ),
218
+ .X86_64SysV = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 64sysv" ),
219
+ .X86RegCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: x86 reg" ),
220
+ .AAPCS = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: aapcs" ),
221
+ .AAPCS_VFP = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: aapcs-vfp" ),
222
+ .IntelOclBicc = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: intel_ocl_bicc" ),
223
+ .SpirFunction = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: SPIR function" ),
224
+ .OpenCLKernel = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: OpenCLKernel" ),
225
+ .Swift = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: Swift" ),
226
+ .PreserveMost = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: PreserveMost" ),
227
+ .PreserveAll = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: PreserveAll" ),
228
+ .AArch64VectorCall = > return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported calling convention: AArch64VectorCall" ),
229
+ };
230
+
231
+ const fn_proto_ty = @ptrCast (* const ZigClangFunctionProtoType , ty );
232
+ const is_var_args = ZigClangFunctionProtoType_isVariadic (fn_proto_ty );
233
+ const param_count : usize = ZigClangFunctionProtoType_getNumParams (fn_proto_ty );
234
+ var i : usize = 0 ;
235
+ while (i < param_count ) : (i += 1 ) {
236
+ return revertAndWarn (rp , error .UnsupportedType , source_loc , "TODO: implement parameters for FunctionProto in transType" );
237
+ }
238
+ // TODO check for always_inline attribute
239
+ // TODO check for align attribute
240
+
241
+ // extern fn (...) T
242
+ const cc_tok = if (cc == .stdcall ) try appendToken (c , .Keyword_stdcallcc , "stdcallcc" ) else null ;
243
+ const extern_tok = if (cc == .c ) try appendToken (c , .Keyword_extern , "extern" ) else null ;
244
+ const fn_tok = try appendToken (c , .Keyword_fn , "fn" );
245
+ const lparen_tok = try appendToken (c , .LParen , "(" );
246
+ const var_args_tok = if (is_var_args ) try appendToken (c , .Ellipsis3 , "..." ) else null ;
247
+ const rparen_tok = try appendToken (c , .RParen , ")" );
248
+
249
+ const return_type_node = blk : {
250
+ if (ZigClangFunctionType_getNoReturnAttr (fn_ty )) {
251
+ break :blk try appendIdentifier (c , "noreturn" );
252
+ } else {
253
+ return revertAndWarn (rp , error .UnsupportedType , source_loc , "TODO: non-noreturn FunctionProto return type" );
254
+ //proto_node->data.fn_proto.return_type = trans_qual_type(c,
255
+ // ZigClangFunctionType_getReturnType(fn_ty), source_loc);
256
+ //if (proto_node->data.fn_proto.return_type == nullptr) {
257
+ // emit_warning(c, source_loc, "unsupported function proto return type");
258
+ // return nullptr;
259
+ //}
260
+ //// convert c_void to actual void (only for return type)
261
+ //// we do want to look at the AstNode instead of ZigClangQualType, because
262
+ //// if they do something like:
263
+ //// typedef Foo void;
264
+ //// void foo(void) -> Foo;
265
+ //// we want to keep the return type AST node.
266
+ //if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
267
+ // proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "void");
268
+ //}
269
+ }
270
+ };
271
+
272
+ const fn_proto = try c .a ().create (ast .Node .FnProto );
273
+ fn_proto .* = ast.Node.FnProto {
274
+ .base = ast.Node { .id = ast .Node .Id .FnProto },
275
+ .doc_comments = null ,
276
+ .visib_token = null ,
277
+ .fn_token = fn_tok ,
278
+ .name_token = null ,
279
+ .params = ast .Node .FnProto .ParamList .init (c .a ()),
280
+ .return_type = ast.Node.FnProto.ReturnType { .Explicit = return_type_node },
281
+ .var_args_token = var_args_tok ,
282
+ .extern_export_inline_token = extern_tok ,
283
+ .cc_token = cc_tok ,
284
+ .async_attr = null ,
285
+ .body_node = null ,
286
+ .lib_name = null ,
287
+ .align_expr = null ,
288
+ .section_expr = null ,
256
289
};
257
- try emitWarning (c , source_loc , "TODO: implement transType for FunctionProto" );
258
- return error .UnsupportedType ;
290
+ return & fn_proto .base ;
259
291
},
292
+
260
293
else = > {
261
294
const type_name = c .str (ZigClangType_getTypeClassName (ty ));
262
- try emitWarning (c , source_loc , "unsupported type: '{}'" , type_name );
263
- return error .UnsupportedType ;
295
+ return revertAndWarn (rp , error .UnsupportedType , source_loc , "unsupported type: '{}'" , type_name );
264
296
},
265
297
}
266
298
}
267
299
300
+ fn revertAndWarn (
301
+ restore_point : RestorePoint ,
302
+ err : var ,
303
+ source_loc : ZigClangSourceLocation ,
304
+ comptime format : []const u8 ,
305
+ args : ... ,
306
+ ) (@typeOf (err ) || error {OutOfMemory }) {
307
+ restore_point .activate ();
308
+ try emitWarning (restore_point .context , source_loc , format , args );
309
+ return err ;
310
+ }
311
+
268
312
fn emitWarning (c : * Context , loc : ZigClangSourceLocation , comptime format : []const u8 , args : ... ) ! void {
269
- try appendToken (c , .LineComment , "// {}: warning: " ++ format , c .locStr (loc ), args );
313
+ _ = try appendToken (c , .LineComment , "// {}: warning: " ++ format , c .locStr (loc ), args );
314
+ }
315
+
316
+ fn failDecl (c : * Context , loc : ZigClangSourceLocation , name : []const u8 , comptime format : []const u8 , args : ... ) ! void {
317
+ // const name = @compileError(msg);
318
+ const const_tok = try appendToken (c , .Keyword_const , "const" );
319
+ const name_tok = try appendToken (c , .Identifier , "{}" , name );
320
+ const eq_tok = try appendToken (c , .Equal , "=" );
321
+ const builtin_tok = try appendToken (c , .Builtin , "@compileError" );
322
+ const lparen_tok = try appendToken (c , .LParen , "(" );
323
+ const msg_tok = try appendToken (c , .StringLiteral , "\" " ++ format ++ "\" " , args );
324
+ const rparen_tok = try appendToken (c , .RParen , ")" );
325
+ const semi_tok = try appendToken (c , .Semicolon , ";" );
326
+
327
+ const msg_node = try c .a ().create (ast .Node .StringLiteral );
328
+ msg_node .* = ast.Node.StringLiteral {
329
+ .base = ast.Node { .id = ast .Node .Id .StringLiteral },
330
+ .token = msg_tok ,
331
+ };
332
+
333
+ const call_node = try c .a ().create (ast .Node .BuiltinCall );
334
+ call_node .* = ast.Node.BuiltinCall {
335
+ .base = ast.Node { .id = ast .Node .Id .BuiltinCall },
336
+ .builtin_token = builtin_tok ,
337
+ .params = ast .Node .BuiltinCall .ParamList .init (c .a ()),
338
+ .rparen_token = rparen_tok ,
339
+ };
340
+ try call_node .params .push (& msg_node .base );
341
+
342
+ const var_decl_node = try c .a ().create (ast .Node .VarDecl );
343
+ var_decl_node .* = ast.Node.VarDecl {
344
+ .base = ast.Node { .id = ast .Node .Id .VarDecl },
345
+ .doc_comments = null ,
346
+ .visib_token = null ,
347
+ .thread_local_token = null ,
348
+ .name_token = name_tok ,
349
+ .eq_token = eq_tok ,
350
+ .mut_token = const_tok ,
351
+ .comptime_token = null ,
352
+ .extern_export_token = null ,
353
+ .lib_name = null ,
354
+ .type_node = null ,
355
+ .align_node = null ,
356
+ .section_node = null ,
357
+ .init_node = & call_node .base ,
358
+ .semicolon_token = semi_tok ,
359
+ };
360
+ try c .tree .root_node .decls .push (& var_decl_node .base );
270
361
}
271
362
272
- fn appendToken (c : * Context , token_id : Token.Id , comptime format : []const u8 , args : ... ) ! void {
363
+ fn appendToken (c : * Context , token_id : Token.Id , comptime format : []const u8 , args : ... ) ! ast.TokenIndex {
273
364
const S = struct {
274
365
fn callback (context : * Context , bytes : []const u8 ) Error ! void {
275
366
return context .source_buffer .append (bytes );
@@ -280,15 +371,28 @@ fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, arg
280
371
281
372
try std .fmt .format (c , Error , S .callback , format , args );
282
373
const end_index = c .source_buffer .len ();
374
+ const token_index = c .tree .tokens .len ;
283
375
const new_token = try c .tree .tokens .addOne ();
284
- errdefer c .tree .tokens .shrink (c . tree . tokens . len - 1 );
376
+ errdefer c .tree .tokens .shrink (token_index );
285
377
286
378
new_token .* = Token {
287
379
.id = token_id ,
288
380
.start = start_index ,
289
381
.end = end_index ,
290
382
};
291
383
try c .source_buffer .appendByte ('\n ' );
384
+
385
+ return token_index ;
386
+ }
387
+
388
+ fn appendIdentifier (c : * Context , name : []const u8 ) ! * ast.Node {
389
+ const token_index = try appendToken (c , .Identifier , "{}" , name );
390
+ const identifier = try c .a ().create (ast .Node .Identifier );
391
+ identifier .* = ast.Node.Identifier {
392
+ .base = ast.Node { .id = ast .Node .Id .Identifier },
393
+ .token = token_index ,
394
+ };
395
+ return & identifier .base ;
292
396
}
293
397
294
398
pub fn freeErrors (errors : []ClangErrMsg ) void {
0 commit comments