Appearance
| 1 | namespace Semantic is | |
| 2 | use Types.Type | |
| 3 | ||
| 4 | // Which types may cross the boundary into a shared library. | |
| 5 | // | |
| 6 | // A native call carries its arguments as the machine lays them out, | |
| 7 | // so the types it can carry are the ones whose layout is fixed: the | |
| 8 | // scalars, a pointer, a reference to a scalar, and a string, which | |
| 9 | // the runtime marshals to a null-terminated buffer for the duration | |
| 10 | // of the call. Anything else - a class, a tuple, an array, a | |
| 11 | // function - has a representation the runtime would have to be told | |
| 12 | // how to marshal, and is reported rather than emitted, so a program | |
| 13 | // that cannot be called says so before any IL is written. | |
| 14 | class PINVOKE_SIGNATURE is | |
| 15 | _innate_symbol_lookup: Lookups.InnateSymbolLookup | |
| 16 | ||
| 17 | init(innate_symbol_lookup: Lookups.InnateSymbolLookup) is | |
| 18 | super.init() | |
| 19 | ||
| 20 | _innate_symbol_lookup = innate_symbol_lookup | |
| 21 | si | |
| 22 | ||
| 23 | // Whether a parameter may be declared at this type. | |
| 24 | can_take(type: Type?) -> bool is | |
| 25 | if !type? then | |
| 26 | return false | |
| 27 | fi | |
| 28 | ||
| 29 | if is_scalar(type) \/ type.is_pointer then | |
| 30 | return true | |
| 31 | fi | |
| 32 | ||
| 33 | if type.is_ref then | |
| 34 | return is_scalar(type.get_element_type()) | |
| 35 | fi | |
| 36 | ||
| 37 | return type.matches(_innate_symbol_lookup.get_string_type()) | |
| 38 | si | |
| 39 | ||
| 40 | // Whether a method may return this type. A string return is not | |
| 41 | // offered: who frees the buffer the callee returned is the | |
| 42 | // library's business rather than the runtime's, and the default | |
| 43 | // marshalling would free it as if it were the runtime's own. | |
| 44 | can_return(type: Type?) -> bool is | |
| 45 | if !type? then | |
| 46 | return false | |
| 47 | fi | |
| 48 | ||
| 49 | if type.is_void \/ type.matches(_innate_symbol_lookup.get_void_type()) then | |
| 50 | return true | |
| 51 | fi | |
| 52 | ||
| 53 | return is_scalar(type) \/ type.is_pointer | |
| 54 | si | |
| 55 | ||
| 56 | // The scalars, by the symbols the compiler knows them as rather | |
| 57 | // than by what they render as. | |
| 58 | is_scalar(type: Type?) -> bool is | |
| 59 | if !type? then | |
| 60 | return false | |
| 61 | fi | |
| 62 | ||
| 63 | for scalar in _scalars() do | |
| 64 | if type.matches(scalar) then | |
| 65 | return true | |
| 66 | fi | |
| 67 | od | |
| 68 | ||
| 69 | return false | |
| 70 | si | |
| 71 | ||
| 72 | _scalars() -> Collections.List[Type] => | |
| 73 | [ | |
| 74 | _innate_symbol_lookup.get_bool_type(), | |
| 75 | _innate_symbol_lookup.get_char_type(), | |
| 76 | _innate_symbol_lookup.get_byte_type(), | |
| 77 | _innate_symbol_lookup.get_ubyte_type(), | |
| 78 | _innate_symbol_lookup.get_short_type(), | |
| 79 | _innate_symbol_lookup.get_ushort_type(), | |
| 80 | _innate_symbol_lookup.get_int_type(), | |
| 81 | _innate_symbol_lookup.get_uint_type(), | |
| 82 | _innate_symbol_lookup.get_long_type(), | |
| 83 | _innate_symbol_lookup.get_ulong_type(), | |
| 84 | _innate_symbol_lookup.get_word_type(), | |
| 85 | _innate_symbol_lookup.get_uword_type(), | |
| 86 | _innate_symbol_lookup.get_single_type(), | |
| 87 | _innate_symbol_lookup.get_double_type() | |
| 88 | ] | |
| 89 | si | |
| 90 | si |