summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono/eolian/mono/struct_definition.hh
diff options
context:
space:
mode:
authorYeongjong Lee <yj34.lee@samsung.com>2020-01-28 14:46:10 +0900
committerWooHyun Jung <wh0705.jung@samsung.com>2020-01-28 14:46:10 +0900
commit581bec9598943cc9274dfe7db1a73a4c878c3cdd (patch)
treeae52675a45025659459dfb329e73538417dc625f /src/bin/eolian_mono/eolian/mono/struct_definition.hh
parentb3c0da13d80456bcbf3954698413df5ee845b8c2 (diff)
eolian_mono: make struct immutable
Summary: Immutable value type is recommeneded for struct type in cs world. `DO NOT define mutable value types.` (see, https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/struct) Also, this patch include refactoring of generated struct types. 1. Change field type to property type that have only getter. it will fix CA1051(ref T8397). 2. Remove internal NativeStruct. there is private field for marshalling struct instead. 3. Fix some test cases that change value inside struct. because struct is immutable. Test Plan: meson build -Dbindings=mono,cxx -Dmono-beta=true Reviewers: woohyun, felipealmeida, Jaehyun_Cho Subscribers: cedric, #reviewers, #committers Tags: #efl Maniphest Tasks: T8397 Differential Revision: https://phab.enlightenment.org/D11146
Diffstat (limited to 'src/bin/eolian_mono/eolian/mono/struct_definition.hh')
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh212
1 files changed, 70 insertions, 142 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
index 48d69dc834..6f19088d52 100644
--- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
@@ -181,7 +181,6 @@ struct to_external_field_convert_generator
181 template <typename OutputIterator, typename Context> 181 template <typename OutputIterator, typename Context>
182 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 182 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
183 { 183 {
184 auto const& indent = current_indentation(context);
185 auto field_name = name_helpers::to_field_name(field.name); 184 auto field_name = name_helpers::to_field_name(field.name);
186 auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type); 185 auto regular = efl::eina::get<attributes::regular_type_def>(&field.type.original_type);
187 auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type); 186 auto klass = efl::eina::get<attributes::klass_name>(&field.type.original_type);
@@ -191,113 +190,108 @@ struct to_external_field_convert_generator
191 { 190 {
192 auto interface_name = name_helpers::klass_full_interface_name(*klass); 191 auto interface_name = name_helpers::klass_full_interface_name(*klass);
193 if (!as_generator( 192 if (!as_generator(
194 "\n" 193 "(" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(" << string << ");"
195 << indent << scope_tab << scope_tab << "_external_struct." << string
196 << " = (" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n"
197 ).generate(sink, std::make_tuple(field_name, field_name), context)) 194 ).generate(sink, std::make_tuple(field_name, field_name), context))
198 return false; 195 return false;
199 } 196 }
200 else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *") 197 else if (field.type.c_type == "Eina_Binbuf *" || field.type.c_type == "const Eina_Binbuf *")
201 { 198 {
202 if (!as_generator( 199 if (!as_generator(
203 indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false);\n") 200 "new " << type << "(" << string << ", false);")
204 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 201 .generate(sink, std::make_tuple(field.type, field_name), context))
205 return false; 202 return false;
206 } 203 }
207 else if (complex && (complex->outer.base_type == "array")) 204 else if (complex && (complex->outer.base_type == "array"))
208 { 205 {
209 // Always assumes pointer 206 // Always assumes pointer
210 if (!as_generator( 207 if (!as_generator(
211 indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(_internal_struct." << string << ");\n") 208 "Efl.Eo.Globals.NativeArrayTo" << type << "(" << string << ");")
212 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 209 .generate(sink, std::make_tuple(field.type, field_name), context))
213 return false; 210 return false;
214 } 211 }
215 else if (complex && (complex->outer.base_type == "list")) 212 else if (complex && (complex->outer.base_type == "list"))
216 { 213 {
217 // Always assumes pointer 214 // Always assumes pointer
218 if (!as_generator( 215 if (!as_generator(
219 indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.NativeListTo" << type << "(_internal_struct." << string << ");\n") 216 "Efl.Eo.Globals.NativeListTo" << type << "(" << string << ");")
220 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 217 .generate(sink, std::make_tuple(field.type, field_name), context))
221 return false; 218 return false;
222 } 219 }
223 else if (complex && complex->outer.base_type == "hash") 220 else if (complex && complex->outer.base_type == "hash")
224 { 221 {
225 if (!as_generator( 222 if (!as_generator(
226 indent << scope_tab << scope_tab << "_external_struct." << string << " = new " << type << "(_internal_struct." << string << ", false, false, false);\n") 223 "new " << type << "(" << string << ", false, false, false);")
227 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 224 .generate(sink, std::make_tuple(field.type, field_name), context))
228 return false; 225 return false;
229 } 226 }
230 else if (complex && complex->outer.base_type == "iterator") 227 else if (complex && complex->outer.base_type == "iterator")
231 { 228 {
232 if (!as_generator( 229 if (!as_generator(
233 indent << scope_tab << scope_tab << "_external_struct." << string << " = Efl.Eo.Globals.IteratorTo" << type << "(_internal_struct." << string << ");\n") 230 "Efl.Eo.Globals.IteratorTo" << type << "(" << string << ");")
234 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 231 .generate(sink, std::make_tuple(field.type, field_name), context))
235 return false; 232 return false;
236 } 233 }
237 else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular)) 234 else if (field.type.is_ptr && helpers::need_pointer_conversion(regular) && !helpers::need_struct_conversion(regular))
238 { 235 {
239 if (!as_generator( 236 if (!as_generator(
240 indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.PrimitiveConversion.PointerToManaged<" << type << ">(_internal_struct." << string << ");\n") 237 "Eina.PrimitiveConversion.PointerToManaged<" << type << ">(" << string << ");")
241 .generate(sink, std::make_tuple(field_name, field.type, field_name), context)) 238 .generate(sink, std::make_tuple(field.type, field_name), context))
242 return false; 239 return false;
243 } 240 }
244 else if (helpers::need_struct_conversion(regular)) 241 else if (helpers::need_struct_conversion(regular))
245 { 242 {
246 if (!as_generator( 243 if (!as_generator(
247 indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") 244 string << ";")
248 .generate(sink, std::make_tuple(field_name, field_name), context)) 245 .generate(sink, field_name, context))
249 return false; 246 return false;
250 } 247 }
251 else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare")) 248 else if (regular && (regular->base_type == "string" || regular->base_type == "mstring" || regular->base_type == "stringshare"))
252 { 249 {
253 if (!as_generator( 250 if (!as_generator(
254 indent << scope_tab << scope_tab << "_external_struct." << string << " = Eina.StringConversion.NativeUtf8ToManagedString(_internal_struct." << string << ");\n") 251 "Eina.StringConversion.NativeUtf8ToManagedString(" << string << ");")
255 .generate(sink, std::make_tuple(field_name, field_name), context)) 252 .generate(sink, std::make_tuple(field_name, field_name), context))
256 return false; 253 return false;
257 } 254 }
258 else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice" 255 else if (field.type.c_type == "Eina_Slice" || field.type.c_type == "const Eina_Slice"
259 || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice") 256 || field.type.c_type == "Eina_Rw_Slice" || field.type.c_type == "const Eina_Rw_Slice")
260 { 257 {
261 if (!as_generator( 258 if (!as_generator(field_name << ";")
262 "\n" <<
263 indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Len = _internal_struct." << field_name << ".Len;\n" <<
264 indent << scope_tab << scope_tab << "_external_struct." << field_name << ".Mem = _internal_struct." << field_name << ".Mem;\n")
265 .generate(sink, attributes::unused, context)) 259 .generate(sink, attributes::unused, context))
266 return false; 260 return false;
267 } 261 }
268 else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value") 262 else if (field.type.c_type == "Eina_Value" || field.type.c_type == "const Eina_Value")
269 { 263 {
270 if (!as_generator( 264 if (!as_generator(
271 indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ");\n" 265 "new Eina.Value(" << string << ");"
272 ).generate(sink, std::make_tuple(field_name, field_name), context)) 266 ).generate(sink, std::make_tuple(field_name), context))
273 return false; 267 return false;
274 } 268 }
275 else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *") 269 else if (field.type.c_type == "Eina_Value *" || field.type.c_type == "const Eina_Value *")
276 { 270 {
277 if (!as_generator( 271 if (!as_generator(
278 indent << scope_tab << scope_tab << "_external_struct." << string << " = new Eina.Value(_internal_struct." << string << ", Eina.Ownership.Unmanaged);\n" 272 "new Eina.Value(" << string << ", Eina.Ownership.Unmanaged);"
279 ).generate(sink, std::make_tuple(field_name, field_name), context)) 273 ).generate(sink, std::make_tuple(field_name), context))
280 return false; 274 return false;
281 } 275 }
282 else if (!field.type.is_ptr && regular && regular->base_type == "bool") 276 else if (!field.type.is_ptr && regular && regular->base_type == "bool")
283 { 277 {
284 if (!as_generator( 278 if (!as_generator(
285 indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << " != 0;\n" 279 string << " != 0;"
286 ).generate(sink, std::make_tuple(field_name, field_name), context)) 280 ).generate(sink, std::make_tuple(field_name), context))
287 return false; 281 return false;
288 } 282 }
289 else if (!field.type.is_ptr && regular && regular->base_type == "char") 283 else if (!field.type.is_ptr && regular && regular->base_type == "char")
290 { 284 {
291 if (!as_generator( 285 if (!as_generator(
292 indent << scope_tab << scope_tab << "_external_struct." << string << " = (char)_internal_struct." << string << ";\n" 286 "(char)" << string << ";"
293 ).generate(sink, std::make_tuple(field_name, field_name), context)) 287 ).generate(sink, std::make_tuple(field_name), context))
294 return false; 288 return false;
295 } 289 }
296 else // primitives and enums 290 else // primitives and enums
297 { 291 {
298 if (!as_generator( 292 if (!as_generator(
299 indent << scope_tab << scope_tab << "_external_struct." << string << " = _internal_struct." << string << ";\n") 293 field_name << ";"
300 .generate(sink, std::make_tuple(field_name, field_name), context)) 294 ).generate(sink, attributes::unused, context))
301 return false; 295 return false;
302 } 296 }
303 return true; 297 return true;
@@ -306,22 +300,12 @@ struct to_external_field_convert_generator
306 300
307// Internal Struct // 301// Internal Struct //
308 302
309struct struct_internal_definition_generator 303struct struct_private_property_generator
310{ 304{
311 template <typename OutputIterator, typename Context> 305 template <typename OutputIterator, typename Context>
312 bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const 306 bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
313 { 307 {
314 auto const& indent = current_indentation(context); 308 auto const& indent = current_indentation(context);
315 if (!as_generator
316 (
317 "#pragma warning disable CS1591\n\n"
318 << indent << "/// <summary>Internal wrapper for struct " << string << ".</summary>\n"
319 << indent << "[StructLayout(LayoutKind.Sequential)]\n"
320 << indent << "internal struct " << string << "\n"
321 << indent << "{\n"
322 )
323 .generate(sink, std::make_tuple<>(binding_struct_name(struct_), struct_internal_decl_name()), context))
324 return false;
325 309
326 // iterate struct fields 310 // iterate struct fields
327 for (auto const& field : struct_.fields) 311 for (auto const& field : struct_.fields)
@@ -337,7 +321,7 @@ struct struct_internal_definition_generator
337 || regular->base_type == "any_value_ref"))) 321 || regular->base_type == "any_value_ref")))
338 { 322 {
339 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" 323 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
340 << indent << scope_tab << "public System.IntPtr " << field_name << ";\n") 324 << indent << scope_tab << "private System.IntPtr " << field_name << ";\n")
341 .generate(sink, nullptr, context)) 325 .generate(sink, nullptr, context))
342 return false; 326 return false;
343 } 327 }
@@ -345,7 +329,7 @@ struct struct_internal_definition_generator
345 && regular->base_type == "bool") 329 && regular->base_type == "bool")
346 { 330 {
347 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" 331 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
348 << indent << scope_tab << "public System.Byte " << field_name << ";\n") 332 << indent << scope_tab << "private System.Byte " << field_name << ";\n")
349 .generate(sink, nullptr, context)) 333 .generate(sink, nullptr, context))
350 return false; 334 return false;
351 } 335 }
@@ -353,12 +337,12 @@ struct struct_internal_definition_generator
353 && regular->base_type == "char") 337 && regular->base_type == "char")
354 { 338 {
355 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n" 339 if (!as_generator(indent << scope_tab << "/// <summary>Internal wrapper for field " << field_name << "</summary>\n"
356 << indent << scope_tab << "public System.Byte " << field_name << ";\n") 340 << indent << scope_tab << "private System.Byte " << field_name << ";\n")
357 .generate(sink, nullptr, context)) 341 .generate(sink, nullptr, context))
358 return false; 342 return false;
359 } 343 }
360 else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n" 344 else if (!as_generator(indent << scope_tab << eolian_mono::marshall_annotation(false) << "\n"
361 << indent << scope_tab << "public " << eolian_mono::marshall_type(false) << " " << string << ";\n") 345 << indent << scope_tab << "private " << eolian_mono::marshall_type(false) << " " << string << ";\n")
362 .generate(sink, std::make_tuple(field.type, field.type, field_name), context)) 346 .generate(sink, std::make_tuple(field.type, field.type, field_name), context))
363 return false; 347 return false;
364 } 348 }
@@ -369,59 +353,18 @@ struct struct_internal_definition_generator
369 // those 'mini-amd64.c condition fields not met' crashes. 353 // those 'mini-amd64.c condition fields not met' crashes.
370 if (struct_.fields.size() == 0) 354 if (struct_.fields.size() == 0)
371 { 355 {
372 if (!as_generator(indent << scope_tab << "internal IntPtr field;\n").generate(sink, nullptr, context)) 356 if (!as_generator(indent << scope_tab << "/// <summary>Placeholder field</summary>\n"
357 << indent << scope_tab << "private IntPtr field;\n").generate(sink, nullptr, context))
373 return false; 358 return false;
374 } 359 }
375 360
376 auto external_name = binding_struct_name(struct_); 361 if(!as_generator("\n")
377 auto internal_name = binding_struct_internal_name(struct_); 362 .generate(sink, attributes::unused, context))
378
379 // to internal
380 if (!as_generator(
381 indent << scope_tab << "/// <summary>Implicit conversion to the internal/marshalling representation.</summary>\n"
382 << indent << scope_tab << "public static implicit operator " << string << "(" << string << " _external_struct)\n"
383 << indent << scope_tab << "{\n"
384 << indent << scope_tab << scope_tab << "var _internal_struct = new " << string << "();\n"
385 ).generate(sink, std::make_tuple(internal_name, external_name, internal_name), context))
386 return false;
387
388 for (auto const& field : struct_.fields)
389 {
390 if (!to_internal_field_convert.generate(sink, field, context))
391 return false;
392 }
393
394 if (!as_generator(indent << scope_tab << scope_tab << "return _internal_struct;\n"
395 << indent << scope_tab << "}\n\n").generate(sink, nullptr, context))
396 return false;
397
398 // to managed
399 if (!as_generator(
400 indent << scope_tab << "/// <summary>Implicit conversion to the managed representation.</summary>\n"
401 << indent << scope_tab << "public static implicit operator " << string << "(" << string << " _internal_struct)\n"
402 << indent << scope_tab << "{\n"
403 << indent << scope_tab << scope_tab << "var _external_struct = new " << string << "();\n"
404 ).generate(sink, std::make_tuple(external_name, internal_name, external_name), context))
405 return false;
406
407 for (auto const& field : struct_.fields)
408 {
409 if (!to_external_field_convert.generate(sink, field, context))
410 return false;
411 }
412
413 if (!as_generator(indent << scope_tab << scope_tab << "return _external_struct;\n"
414 << indent << scope_tab << "}\n").generate(sink, nullptr, context))
415 return false; 363 return false;
416 364
417 // close internal class
418 if(!as_generator(indent << "}\n"
419 << "#pragma warning restore CS1591\n"
420 ).generate(sink, attributes::unused, context)) return false;
421
422 return true; 365 return true;
423 } 366 }
424} const struct_internal_definition {}; 367} const struct_private_property {};
425 368
426// Managed Struct // 369// Managed Struct //
427 370
@@ -454,34 +397,22 @@ struct struct_definition_generator
454 return false; 397 return false;
455 398
456 if (!as_generator( 399 if (!as_generator(
457 indent << scope_tab << "public static implicit operator " << struct_name << "(\n" 400 indent << scope_tab << "public static implicit operator " << struct_name << "(("
458 << indent << scope_tab << scope_tab << "(\n" 401 << (field_argument_decl % ", ")
459 << ((indent << scope_tab << scope_tab << " " << field_argument_decl) % ",\n") << "\n" 402 << ") tuple)\n"
460 << indent << scope_tab << scope_tab << ") tuple)\n"
461 << indent << scope_tab << "{\n"
462 ).generate(sink, struct_.fields, context)) 403 ).generate(sink, struct_.fields, context))
463 return false; 404 return false;
464 405
465 // object constructor 406 // object constructor
466 if (!as_generator( 407 if (!as_generator(
467 indent << scope_tab << scope_tab << "return new " << struct_name << "{\n" 408 indent << scope_tab << scope_tab << "=> new " << struct_name << "("
468 ).generate(sink, attributes::unused, context)) 409 ).generate(sink, attributes::unused, context))
469 return false; 410 return false;
470 411
471 for (const auto& field: struct_.fields)
472 {
473 auto field_name = name_helpers::to_field_name(field.name);
474
475 if (!as_generator(
476 indent << scope_tab << scope_tab << scope_tab << field_name << " = tuple." << field_name << ",\n"
477 ).generate(sink, attributes::unused, context))
478 return false;
479 }
480
481 if (!as_generator( 412 if (!as_generator(
482 indent << scope_tab << scope_tab << "};\n" 413 (("tuple." << struct_field_name) % ", ")
483 << indent << scope_tab << "}\n" 414 << ");\n\n"
484 ).generate(sink, attributes::unused, context)) 415 ).generate(sink, struct_.fields, context))
485 return false; 416 return false;
486 417
487 return true; 418 return true;
@@ -528,10 +459,11 @@ struct struct_definition_generator
528 // assigments 459 // assigments
529 for (auto const& field : struct_.fields) 460 for (auto const& field : struct_.fields)
530 { 461 {
531 auto field_name = name_helpers::to_field_name(field.name); 462 auto field_name = name_helpers::managed_name(field.name);
463 auto param_name = name_helpers::to_field_name(field.name);
532 464
533 if (!as_generator( 465 if (!as_generator(
534 indent << scope_tab << scope_tab << field_name << " = this." << field_name << ";\n" 466 indent << scope_tab << scope_tab << param_name << " = this." << field_name << ";\n"
535 ).generate(sink, attributes::unused, context)) 467 ).generate(sink, attributes::unused, context))
536 return false; 468 return false;
537 } 469 }
@@ -561,6 +493,9 @@ struct struct_definition_generator
561 .generate(sink, attributes::unused, context)) 493 .generate(sink, attributes::unused, context))
562 return false; 494 return false;
563 495
496 if (!struct_private_property.generate(sink, struct_, change_indentation(indent, context)))
497 return false;
498
564 // iterate struct fields 499 // iterate struct fields
565 for (auto const& field : struct_.fields) 500 for (auto const& field : struct_.fields)
566 { 501 {
@@ -574,23 +509,13 @@ struct struct_definition_generator
574 return false; 509 return false;
575 } 510 }
576 511
577 if (!as_generator(indent << scope_tab << "public " << type << " " << name_helpers::to_field_name(field.name) << ";\n").generate(sink, field.type, context)) 512 if (!as_generator(indent << scope_tab << "public " << type << " " << name_helpers::managed_name(field.name) << " { get => " << to_external_field_convert << " }\n").generate(sink, std::make_tuple(field.type, field), context))
578 return false; 513 return false;
579 } 514 }
580 515
581 auto struct_name = binding_struct_name(struct_); 516 auto struct_name = binding_struct_name(struct_);
582 517
583 // Check whether this is an extern struct without declared fields in .eo file and generate a 518 if (struct_.fields.size() != 0)
584 // placeholder field if positive.
585 // Mono's JIT is picky when generating function pointer for delegates with empty structs, leading to
586 // those 'mini-amd64.c condition fields not met' crashes.
587 if (struct_.fields.size() == 0)
588 {
589 if (!as_generator(indent << scope_tab << "/// <summary>Placeholder field</summary>\n"
590 << indent << scope_tab << "public IntPtr field;\n").generate(sink, nullptr, context))
591 return false;
592 }
593 else
594 { 519 {
595 // Constructor with default parameters for easy struct initialization 520 // Constructor with default parameters for easy struct initialization
596 if(!as_generator( 521 if(!as_generator(
@@ -608,9 +533,9 @@ struct struct_definition_generator
608 << *(indent << scope_tab << field_argument_docs << "\n") 533 << *(indent << scope_tab << field_argument_docs << "\n")
609 << indent << scope_tab << "public " << string << "(\n" 534 << indent << scope_tab << "public " << string << "(\n"
610 << ((indent << scope_tab << scope_tab << field_argument_default) % ",\n") 535 << ((indent << scope_tab << scope_tab << field_argument_default) % ",\n")
611 << indent << scope_tab << ")\n" 536 << ")\n"
612 << indent << scope_tab << "{\n" 537 << indent << scope_tab << "{\n"
613 << *(indent << scope_tab << scope_tab << field_argument_assignment << ";\n") 538 << *(indent << scope_tab << scope_tab << field_argument_assignment)
614 << indent << scope_tab << "}\n\n") 539 << indent << scope_tab << "}\n\n")
615 .generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context)) 540 .generate(sink, std::make_tuple(struct_.fields, struct_name, struct_.fields, struct_.fields), context))
616 return false; 541 return false;
@@ -638,7 +563,14 @@ struct struct_definition_generator
638 ).generate(sink, attributes::unused, context)) 563 ).generate(sink, attributes::unused, context))
639 return false; 564 return false;
640 565
641 if (struct_.fields.size() != 0 ) 566 if (struct_.fields.size() == 1 )
567 {
568 if (!as_generator(
569 indent << scope_tab << scope_tab << "return " << name_helpers::managed_name(struct_.fields[0].name) << ".GetHashCode();\n"
570 ).generate(sink, attributes::unused, context))
571 return false;
572 }
573 else if (struct_.fields.size() != 0 )
642 { 574 {
643 // int hash = 17; 575 // int hash = 17;
644 // hash = 23 * fieldA.GetHashCode(); 576 // hash = 23 * fieldA.GetHashCode();
@@ -647,7 +579,7 @@ struct struct_definition_generator
647 // return hash 579 // return hash
648 if (!as_generator( 580 if (!as_generator(
649 indent << scope_tab << scope_tab << "int hash = 17;\n" 581 indent << scope_tab << scope_tab << "int hash = 17;\n"
650 << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_field_name << ".GetHashCode(" << culture_info << ");\n")) 582 << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_property_name << ".GetHashCode(" << culture_info << ");\n"))
651 << indent << scope_tab << scope_tab << "return hash;\n" 583 << indent << scope_tab << scope_tab << "return hash;\n"
652 ).generate(sink, struct_.fields, context)) 584 ).generate(sink, struct_.fields, context))
653 return false; 585 return false;
@@ -656,7 +588,7 @@ struct struct_definition_generator
656 { 588 {
657 // Just compare the place holder pointers 589 // Just compare the place holder pointers
658 if (!as_generator( 590 if (!as_generator(
659 "return field.GetHashCode();\n" 591 indent << scope_tab << scope_tab << "return field.GetHashCode();\n"
660 ).generate(sink, attributes::unused, context)) 592 ).generate(sink, attributes::unused, context))
661 return false; 593 return false;
662 } 594 }
@@ -680,7 +612,7 @@ struct struct_definition_generator
680 if (struct_.fields.size() != 0 ) 612 if (struct_.fields.size() != 0 )
681 { 613 {
682 if (!as_generator( 614 if (!as_generator(
683 grammar::attribute_reorder<-1, -1>((name_helpers::struct_field_name << " == other." << name_helpers::struct_field_name)) % " && " 615 grammar::attribute_reorder<-1, -1>((name_helpers::struct_property_name << " == other." << name_helpers::struct_property_name)) % " && "
684 ).generate(sink, struct_.fields, context)) 616 ).generate(sink, struct_.fields, context))
685 return false; 617 return false;
686 } 618 }
@@ -695,7 +627,7 @@ struct struct_definition_generator
695 627
696 628
697 if (!as_generator( 629 if (!as_generator(
698 indent << scope_tab << scope_tab << ";\n" 630 ";\n"
699 << indent << scope_tab << "}\n" 631 << indent << scope_tab << "}\n"
700 ).generate(sink, attributes::unused, context)) 632 ).generate(sink, attributes::unused, context))
701 return false; 633 return false;
@@ -745,8 +677,7 @@ struct struct_definition_generator
745 << indent << scope_tab << "/// <param name=\"ptr\">Native pointer to be converted.</param>\n" 677 << indent << scope_tab << "/// <param name=\"ptr\">Native pointer to be converted.</param>\n"
746 << indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n" 678 << indent << scope_tab << "public static implicit operator " << struct_name << "(IntPtr ptr)\n"
747 << indent << scope_tab << "{\n" 679 << indent << scope_tab << "{\n"
748 << indent << scope_tab << scope_tab << "var tmp = (" << struct_name << ".NativeStruct)Marshal.PtrToStructure(ptr, typeof(" << struct_name << ".NativeStruct));\n" 680 << indent << scope_tab << scope_tab << "return (" << struct_name << ")Marshal.PtrToStructure(ptr, typeof(" << struct_name << "));\n"
749 << indent << scope_tab << scope_tab << "return tmp;\n"
750 << indent << scope_tab << "}\n\n" 681 << indent << scope_tab << "}\n\n"
751 ).generate(sink, attributes::unused, context)) 682 ).generate(sink, attributes::unused, context))
752 return false; 683 return false;
@@ -771,9 +702,6 @@ struct struct_definition_generator
771 ).generate(sink, attributes::unused, context)) 702 ).generate(sink, attributes::unused, context))
772 return false; 703 return false;
773 704
774 if (!struct_internal_definition.generate(sink, struct_, change_indentation(indent.inc(), context)))
775 return false;
776
777 if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false; 705 if(!as_generator(indent << "}\n\n").generate(sink, attributes::unused, context)) return false;
778 706
779 return true; 707 return true;
@@ -809,9 +737,9 @@ template <>
809struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {}; 737struct is_generator< ::eolian_mono::struct_definition_generator> : std::true_type {};
810 738
811template <> 739template <>
812struct is_eager_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; 740struct is_eager_generator< ::eolian_mono::struct_private_property_generator> : std::true_type {};
813template <> 741template <>
814struct is_generator< ::eolian_mono::struct_internal_definition_generator> : std::true_type {}; 742struct is_generator< ::eolian_mono::struct_private_property_generator> : std::true_type {};
815 743
816template <> 744template <>
817struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {}; 745struct is_eager_generator< ::eolian_mono::to_internal_field_convert_generator> : std::true_type {};
@@ -833,7 +761,7 @@ template <>
833struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {}; 761struct attributes_needed< ::eolian_mono::struct_definition_generator> : std::integral_constant<int, 1> {};
834 762
835template <> 763template <>
836struct attributes_needed< ::eolian_mono::struct_internal_definition_generator> : std::integral_constant<int, 1> {}; 764struct attributes_needed< ::eolian_mono::struct_private_property_generator> : std::integral_constant<int, 1> {};
837 765
838template <> 766template <>
839struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {}; 767struct attributes_needed< ::eolian_mono::to_internal_field_convert_generator> : std::integral_constant<int, 1> {};