Skip to content
← Back

src/syntax/process/compile_literals.ghul

1
namespace Syntax.Process is
2
use Logging;
3
4
use Semantic.Lookups.InnateSymbolLookup;
5
use Semantic.Types.Type;
6
7
use IR.Values;
8
9
// Lowers literal and `_` (default-value) expressions to IR values.
10
// Split out of COMPILE_EXPRESSIONS, which delegates each
11
// visit(<literal>) here.
12
class COMPILE_LITERALS is
13
_logger: Logger;
14
_innate_symbol_lookup: InnateSymbolLookup;
15
_numeric_literal_classifier: NUMERIC_LITERAL_CLASSIFIER;
16
17
init(
18
logger: Logger,
19
innate_symbol_lookup: InnateSymbolLookup,
20
numeric_literal_classifier: NUMERIC_LITERAL_CLASSIFIER
21
) is
22
super.init();
23
24
_logger = logger;
25
_innate_symbol_lookup = innate_symbol_lookup;
26
_numeric_literal_classifier = numeric_literal_classifier;
27
si
28
29
visit_integer(integer: Trees.Expressions.Literals.INTEGER) is
30
let value = _numeric_literal_classifier.classify_integer(integer.location, integer.value_string);
31
32
if !value? then
33
integer.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), integer.location);
34
return;
35
fi
36
37
integer.compile_expressions_state.value = value;
38
si
39
40
visit_float(float: Trees.Expressions.Literals.FLOAT) is
41
let value_string = float.value_string;
42
let stripped = value_string.substring(0, value_string.length -1);
43
44
if
45
value_string.ends_with('m') \/
46
value_string.ends_with('M')
47
then
48
if stripped.contains('e') \/ stripped.contains('E') then
49
_logger.error(float.location, "exponent notation not supported in decimal literal");
50
float.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), float.location);
51
return;
52
fi
53
54
let decomp = Literal.DECIMAL.decompose(stripped);
55
56
if decomp.error? then
57
_logger.error(float.location, decomp.error!);
58
float.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), float.location);
59
return;
60
fi
61
62
float.compile_expressions_state.value = Literal.DECIMAL(
63
stripped,
64
_innate_symbol_lookup.get_decimal_type(),
65
decomp.lo,
66
decomp.mid,
67
decomp.hi,
68
decomp.scale
69
);
70
return;
71
fi
72
73
let type: Type mut;
74
let suffix: string mut;
75
76
if
77
value_string.ends_with('D') \/
78
value_string.ends_with('d')
79
then
80
type = _innate_symbol_lookup.get_double_type();
81
suffix = "r8";
82
else
83
type = _innate_symbol_lookup.get_single_type();
84
suffix = "r4";
85
fi
86
87
float.compile_expressions_state.value = Literal.NUMBER(
88
stripped,
89
type,
90
suffix
91
);
92
si
93
94
visit_interpolation(interpolation: Trees.Expressions.STRING_INTERPOLATION) is
95
interpolation.compile_expressions_state.value = IR.Values.BLOCK(_innate_symbol_lookup.get_string_type());
96
si
97
98
visit_string(`string: Trees.Expressions.Literals.STRING) is
99
`string.compile_expressions_state.value = Literal.STRING(
100
`string.value_string,
101
_innate_symbol_lookup.get_string_type()
102
);
103
si
104
105
visit_character(character: Trees.Expressions.Literals.CHARACTER) is
106
let value_string = character.value_string;
107
let c: int mut = 0;
108
109
if value_string.length < 1 \/ value_string.length > 1 then
110
_logger.error(character.location, "invalid character literal");
111
else
112
c = cast int(value_string.get_chars(0));
113
fi
114
115
character.compile_expressions_state.value = Literal.NUMBER(
116
"{c}",
117
_innate_symbol_lookup.get_char_type(),
118
"i4"
119
);
120
si
121
122
visit_boolean(boolean: Trees.Expressions.Literals.BOOLEAN) is
123
let value_string = boolean.value_string;
124
125
let value: string mut;
126
127
if value_string =~ "true" then
128
value = "1";
129
elif value_string =~ "false" then
130
value = "0";
131
else
132
throw System.Exception("invalid value for boolean literal: {value_string}");
133
fi
134
135
boolean.compile_expressions_state.value = Literal.NUMBER(
136
value,
137
_innate_symbol_lookup.get_bool_type(),
138
"i4"
139
);
140
si
141
142
visit_default(`default: Trees.Expressions.DEFAULT) is
143
// `_[T]` pins the type explicitly; a bare `_` takes the
144
// type pushed in by the parent context (assignment RHS,
145
// return position, typed `let` initializer, call
146
// argument) via set_constraint.
147
let type: Semantic.Types.Type? mut = _;
148
149
if `default.type_expression? then
150
type = `default.type_expression.type;
151
elif `default.expected_type? then
152
type = `default.expected_type;
153
fi
154
155
if !type? then
156
_logger.error(`default.location, "cannot infer type of default here");
157
`default.compile_expressions_state.value = IR.Values.DUMMY(Semantic.Types.ERROR(), `default.location);
158
return;
159
fi
160
161
if type.is_error then
162
`default.compile_expressions_state.value = IR.Values.DUMMY(type, `default.location);
163
return;
164
fi
165
166
`default.compile_expressions_state.value = IR.Values.DEFAULT(type);
167
si
168
si
169
si