Skip to content
← Back

src/semantic/dotnet/reflected_constants.ghul

1
namespace Semantic.DotNet is
2
use TYPE = System.Type
3
4
use System.Reflection.FieldInfo
5
6
// What a reflected field turns out to be when asked for a constant
7
// value.
8
//
9
// A constant whose value is null is a case of its own rather than a
10
// reserved spelling inside the text: a constant string holds whatever
11
// a library author wrote, so no word is available to stand for
12
// something else.
13
union ReflectedConstant is
14
// Not a constant, or one whose value cannot be described as text
15
// - an ordinary field either way.
16
NONE
17
18
// A constant whose value is null, which is the only constant of a
19
// reference type metadata can hold.
20
ABSENT
21
22
VALUE(text: string) default
23
si
24
25
// Reads a reflected `const` field's value.
26
//
27
// A `const` is a compile-time literal: metadata carries the value and
28
// no field is emitted to hold it, because a language that inlines a
29
// constant at each use leaves nothing behind for anyone to load. So a
30
// consumer has to take the value from here rather than read the field
31
// it looks like.
32
//
33
// The value comes back as invariant-culture text, which is the form a
34
// reflected argument default is carried in too - `text_of` is what
35
// the two share, each deciding for itself what an absent value means.
36
class REFLECTED_CONSTANTS is
37
value_of(`field: FieldInfo) -> ReflectedConstant static is
38
if !`field.is_literal then
39
return ReflectedConstant.NONE
40
fi
41
42
let raw = `field.get_raw_constant_value()
43
44
if !raw? then
45
return ReflectedConstant.ABSENT
46
fi
47
48
if let text = text_of(raw, `field.field_type) then
49
return ReflectedConstant.VALUE(text)
50
fi
51
52
return ReflectedConstant.NONE
53
si
54
55
// A reflected value as invariant-culture text, or null when it is
56
// not one that can be described that way. Culture-independent
57
// because this is read back by the compiler rather than shown to
58
// anyone.
59
text_of(value: object, type: TYPE) -> string? static is
60
if
61
!type.is_primitive /\
62
!type.is_enum /\
63
type.full_name !~ "System.String"
64
then
65
return null
66
fi
67
68
let convertible = cast System.IConvertible?(value)
69
70
if !convertible? then
71
return null
72
fi
73
74
return convertible.to_string(
75
System.Globalization.CultureInfo.invariant_culture
76
)
77
si
78
si
79
si