Appearance
| 1 | namespace Semantic.DotNet is | |
| 2 | use Collections; | |
| 3 | ||
| 4 | // The ilasm textual forms for custom-attribute arguments — the | |
| 5 | // `{ ... }` body of a `.custom` directive. ilasm encodes the blob | |
| 6 | // from these, so the prolog, the compressed length prefixes and the | |
| 7 | // trailing named-argument count are all its responsibility rather | |
| 8 | // than the caller's. | |
| 9 | // | |
| 10 | // A string carrying a NUL cannot be expressed: ilasm holds a quoted | |
| 11 | // literal as a NUL-terminated string and silently drops everything | |
| 12 | // from the NUL onwards. | |
| 13 | class IL_ATTRIBUTE_ARGUMENTS is | |
| 14 | // `string('...')`, or `string(nullref)` for a null value. | |
| 15 | string_argument(value: string?) -> string static => | |
| 16 | if value? then | |
| 17 | "string({quote(value)})" | |
| 18 | else | |
| 19 | "string(nullref)" | |
| 20 | fi; | |
| 21 | ||
| 22 | // `string[N](e0 e1 ...)`, a null entry rendered as `nullref`. | |
| 23 | string_array_argument(values: List[string?]) -> string static is | |
| 24 | let buffer = System.Text.StringBuilder(); | |
| 25 | ||
| 26 | buffer.append("string[").append(values.count).append("]("); | |
| 27 | ||
| 28 | let first mut = true; | |
| 29 | ||
| 30 | for value in values do | |
| 31 | if !first then | |
| 32 | buffer.append(' '); | |
| 33 | fi | |
| 34 | ||
| 35 | first = false; | |
| 36 | ||
| 37 | if value? then | |
| 38 | buffer.append(quote(value)); | |
| 39 | else | |
| 40 | buffer.append("nullref"); | |
| 41 | fi | |
| 42 | od | |
| 43 | ||
| 44 | buffer.append(")"); | |
| 45 | ||
| 46 | return buffer.to_string(); | |
| 47 | si | |
| 48 | ||
| 49 | // `uint8(N)`. | |
| 50 | byte_argument(value: int) -> string static => | |
| 51 | "uint8({0xFF & value})"; | |
| 52 | ||
| 53 | // `uint8[N](b0 b1 ...)`. | |
| 54 | byte_array_argument(values: List[int]) -> string static is | |
| 55 | let buffer = System.Text.StringBuilder(); | |
| 56 | ||
| 57 | buffer.append("uint8[").append(values.count).append("]("); | |
| 58 | ||
| 59 | let first mut = true; | |
| 60 | ||
| 61 | for value in values do | |
| 62 | if !first then | |
| 63 | buffer.append(' '); | |
| 64 | fi | |
| 65 | ||
| 66 | first = false; | |
| 67 | ||
| 68 | buffer.append(0xFF & value); | |
| 69 | od | |
| 70 | ||
| 71 | buffer.append(")"); | |
| 72 | ||
| 73 | return buffer.to_string(); | |
| 74 | si | |
| 75 | ||
| 76 | // Wraps `value` in the ilasm single-quoted form, escaping the | |
| 77 | // delimiter, the escape character itself, and the whitespace that | |
| 78 | // a quoted literal cannot carry raw. | |
| 79 | quote(value: string) -> string static is | |
| 80 | let buffer = System.Text.StringBuilder(); | |
| 81 | ||
| 82 | buffer.append("'"); | |
| 83 | ||
| 84 | for c in value do | |
| 85 | if c == '\\' then | |
| 86 | buffer.append("\\\\"); | |
| 87 | elif c == '\'' then | |
| 88 | buffer.append("\\'"); | |
| 89 | elif c == '\n' then | |
| 90 | buffer.append("\\n"); | |
| 91 | elif c == '\r' then | |
| 92 | buffer.append("\\r"); | |
| 93 | elif c == '\t' then | |
| 94 | buffer.append("\\t"); | |
| 95 | else | |
| 96 | buffer.append(c); | |
| 97 | fi | |
| 98 | od | |
| 99 | ||
| 100 | buffer.append("'"); | |
| 101 | ||
| 102 | return buffer.to_string(); | |
| 103 | si | |
| 104 | si | |
| 105 | si |