Skip to content

Commit 33a70f5

Browse files
committed
Add tests and do some refactoring
1 parent 2c0458f commit 33a70f5

17 files changed

+487
-212
lines changed

compiler-core/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub mod visit;
99
pub use self::typed::{InvalidExpression, TypedExpr};
1010
pub use self::untyped::{FunctionLiteralKind, UntypedExpr};
1111

12-
pub use self::constant::{Constant, TypedConstant, UntypedConstant};
12+
pub use self::constant::{Constant, ConstantRecordUpdateArg, TypedConstant, UntypedConstant};
1313

1414
use crate::analyse::Inferred;
1515
use crate::bit_array;

compiler-core/src/ast/constant.rs

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,23 @@ pub enum Constant<T, RecordTag> {
4040
module: Option<(EcoString, SrcSpan)>,
4141
name: EcoString,
4242
arguments: Vec<CallArg<Self>>,
43-
spread: Option<Box<Self>>,
4443
tag: RecordTag,
4544
type_: T,
4645
field_map: Option<FieldMap>,
4746
record_constructor: Option<Box<ValueConstructor>>,
4847
},
4948

49+
RecordUpdate {
50+
location: SrcSpan,
51+
module: Option<(EcoString, SrcSpan)>,
52+
name: EcoString,
53+
record: Box<Self>,
54+
arguments: Vec<ConstantRecordUpdateArg<Self>>,
55+
tag: RecordTag,
56+
type_: T,
57+
field_map: Option<FieldMap>,
58+
},
59+
5060
BitArray {
5161
location: SrcSpan,
5262
segments: Vec<BitArraySegment<Self, T>>,
@@ -86,6 +96,7 @@ impl TypedConstant {
8696
}
8797
Constant::List { type_, .. }
8898
| Constant::Record { type_, .. }
99+
| Constant::RecordUpdate { type_, .. }
89100
| Constant::Var { type_, .. }
90101
| Constant::Invalid { type_, .. } => type_.clone(),
91102
}
@@ -105,12 +116,19 @@ impl TypedConstant {
105116
.iter()
106117
.find_map(|element| element.find_node(byte_index))
107118
.unwrap_or(Located::Constant(self)),
108-
Constant::Record {
109-
arguments, spread, ..
110-
} => arguments
119+
Constant::Record { arguments, .. } => arguments
111120
.iter()
112121
.find_map(|argument| argument.find_node(byte_index))
113-
.or_else(|| spread.as_ref().and_then(|s| s.find_node(byte_index)))
122+
.unwrap_or(Located::Constant(self)),
123+
Constant::RecordUpdate {
124+
record, arguments, ..
125+
} => record
126+
.find_node(byte_index)
127+
.or_else(|| {
128+
arguments
129+
.iter()
130+
.find_map(|arg| arg.value.find_node(byte_index))
131+
})
114132
.unwrap_or(Located::Constant(self)),
115133
Constant::BitArray { segments, .. } => segments
116134
.iter()
@@ -143,6 +161,7 @@ impl TypedConstant {
143161
} => value_constructor
144162
.as_ref()
145163
.map(|constructor| constructor.definition_location()),
164+
Constant::RecordUpdate { .. } => None,
146165
}
147166
}
148167

@@ -160,17 +179,20 @@ impl TypedConstant {
160179
.map(|element| element.referenced_variables())
161180
.fold(im::hashset![], im::HashSet::union),
162181

163-
Constant::Record {
164-
arguments, spread, ..
182+
Constant::Record { arguments, .. } => arguments
183+
.iter()
184+
.map(|argument| argument.value.referenced_variables())
185+
.fold(im::hashset![], im::HashSet::union),
186+
187+
Constant::RecordUpdate {
188+
record, arguments, ..
165189
} => {
190+
let record_vars = record.referenced_variables();
166191
let arg_vars = arguments
167192
.iter()
168-
.map(|argument| argument.value.referenced_variables())
193+
.map(|arg| arg.value.referenced_variables())
169194
.fold(im::hashset![], im::HashSet::union);
170-
match spread {
171-
Some(spread) => arg_vars.union(spread.referenced_variables()),
172-
None => arg_vars,
173-
}
195+
record_vars.union(arg_vars)
174196
}
175197

176198
Constant::BitArray { segments, .. } => segments
@@ -206,6 +228,7 @@ impl<A, B> Constant<A, B> {
206228
| Constant::Tuple { location, .. }
207229
| Constant::String { location, .. }
208230
| Constant::Record { location, .. }
231+
| Constant::RecordUpdate { location, .. }
209232
| Constant::BitArray { location, .. }
210233
| Constant::Var { location, .. }
211234
| Constant::Invalid { location, .. }
@@ -224,6 +247,7 @@ impl<A, B> Constant<A, B> {
224247
Constant::Tuple { .. }
225248
| Constant::List { .. }
226249
| Constant::Record { .. }
250+
| Constant::RecordUpdate { .. }
227251
| Constant::BitArray { .. }
228252
| Constant::StringConcatenation { .. }
229253
| Constant::Invalid { .. } => false,
@@ -246,3 +270,26 @@ impl<A, B> bit_array::GetLiteralValue for Constant<A, B> {
246270
}
247271
}
248272
}
273+
274+
#[derive(Debug, Clone, PartialEq, Eq)]
275+
pub struct ConstantRecordUpdateArg<Constant> {
276+
pub label: EcoString,
277+
pub location: SrcSpan,
278+
pub value: Constant,
279+
}
280+
281+
impl<Constant> ConstantRecordUpdateArg<Constant> {
282+
#[must_use]
283+
pub fn uses_label_shorthand(&self) -> bool
284+
where
285+
Constant: HasLocation,
286+
{
287+
self.value.location() == self.location
288+
}
289+
}
290+
291+
impl<Constant> HasLocation for ConstantRecordUpdateArg<Constant> {
292+
fn location(&self) -> SrcSpan {
293+
self.location
294+
}
295+
}

compiler-core/src/ast_folder.rs

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ use vec1::Vec1;
66
use crate::{
77
analyse::Inferred,
88
ast::{
9-
Assert, AssignName, Assignment, BinOp, BitArraySize, CallArg, Constant, Definition,
10-
FunctionLiteralKind, Pattern, RecordBeingUpdated, SrcSpan, Statement, TailPattern,
11-
TargetedDefinition, TodoKind, TypeAst, TypeAstConstructor, TypeAstFn, TypeAstHole,
12-
TypeAstTuple, TypeAstVar, UntypedArg, UntypedAssert, UntypedAssignment, UntypedClause,
13-
UntypedConstant, UntypedConstantBitArraySegment, UntypedCustomType, UntypedDefinition,
14-
UntypedExpr, UntypedExprBitArraySegment, UntypedFunction, UntypedImport, UntypedModule,
15-
UntypedModuleConstant, UntypedPattern, UntypedPatternBitArraySegment,
16-
UntypedRecordUpdateArg, UntypedStatement, UntypedTailPattern, UntypedTypeAlias, UntypedUse,
17-
UntypedUseAssignment, Use, UseAssignment,
9+
Assert, AssignName, Assignment, BinOp, BitArraySize, CallArg, Constant,
10+
ConstantRecordUpdateArg, Definition, FunctionLiteralKind, Pattern, RecordBeingUpdated,
11+
SrcSpan, Statement, TailPattern, TargetedDefinition, TodoKind, TypeAst, TypeAstConstructor,
12+
TypeAstFn, TypeAstHole, TypeAstTuple, TypeAstVar, UntypedArg, UntypedAssert,
13+
UntypedAssignment, UntypedClause, UntypedConstant, UntypedConstantBitArraySegment,
14+
UntypedCustomType, UntypedDefinition, UntypedExpr, UntypedExprBitArraySegment,
15+
UntypedFunction, UntypedImport, UntypedModule, UntypedModuleConstant, UntypedPattern,
16+
UntypedPatternBitArraySegment, UntypedRecordUpdateArg, UntypedStatement,
17+
UntypedTailPattern, UntypedTypeAlias, UntypedUse, UntypedUseAssignment, Use, UseAssignment,
1818
},
1919
build::Target,
2020
parse::LiteralFloatValue,
@@ -972,12 +972,22 @@ pub trait UntypedConstantFolder {
972972
module,
973973
name,
974974
arguments,
975-
spread,
976975
tag: (),
977976
type_: (),
978977
field_map: _,
979978
record_constructor: _,
980-
} => self.fold_constant_record(location, module, name, arguments, spread),
979+
} => self.fold_constant_record(location, module, name, arguments),
980+
981+
Constant::RecordUpdate {
982+
location,
983+
module,
984+
name,
985+
record,
986+
arguments,
987+
tag: (),
988+
type_: (),
989+
field_map: _,
990+
} => self.fold_constant_record_update(location, module, name, record, arguments),
981991

982992
Constant::BitArray { location, segments } => {
983993
self.fold_constant_bit_array(location, segments)
@@ -1060,21 +1070,39 @@ pub trait UntypedConstantFolder {
10601070
module: Option<(EcoString, SrcSpan)>,
10611071
name: EcoString,
10621072
arguments: Vec<CallArg<UntypedConstant>>,
1063-
spread: Option<Box<UntypedConstant>>,
10641073
) -> UntypedConstant {
10651074
Constant::Record {
10661075
location,
10671076
module,
10681077
name,
10691078
arguments,
1070-
spread,
10711079
tag: (),
10721080
type_: (),
10731081
field_map: None,
10741082
record_constructor: None,
10751083
}
10761084
}
10771085

1086+
fn fold_constant_record_update(
1087+
&mut self,
1088+
location: SrcSpan,
1089+
module: Option<(EcoString, SrcSpan)>,
1090+
name: EcoString,
1091+
record: Box<UntypedConstant>,
1092+
arguments: Vec<ConstantRecordUpdateArg<UntypedConstant>>,
1093+
) -> UntypedConstant {
1094+
Constant::RecordUpdate {
1095+
location,
1096+
module,
1097+
name,
1098+
record,
1099+
arguments,
1100+
tag: (),
1101+
type_: (),
1102+
field_map: None,
1103+
}
1104+
}
1105+
10781106
fn fold_constant_bit_array(
10791107
&mut self,
10801108
location: SrcSpan,
@@ -1149,7 +1177,6 @@ pub trait UntypedConstantFolder {
11491177
module,
11501178
name,
11511179
arguments,
1152-
spread,
11531180
tag,
11541181
type_,
11551182
field_map,
@@ -1162,20 +1189,49 @@ pub trait UntypedConstantFolder {
11621189
argument
11631190
})
11641191
.collect();
1165-
let spread = spread.map(|s| Box::new(self.fold_constant(*s)));
11661192
Constant::Record {
11671193
location,
11681194
module,
11691195
name,
11701196
arguments,
1171-
spread,
11721197
tag,
11731198
type_,
11741199
field_map,
11751200
record_constructor,
11761201
}
11771202
}
11781203

1204+
Constant::RecordUpdate {
1205+
location,
1206+
module,
1207+
name,
1208+
record,
1209+
arguments,
1210+
tag,
1211+
type_,
1212+
field_map,
1213+
} => {
1214+
let record = Box::new(self.fold_constant(*record));
1215+
let arguments = arguments
1216+
.into_iter()
1217+
.map(|arg| ConstantRecordUpdateArg {
1218+
label: arg.label,
1219+
location: arg.location,
1220+
value: self.fold_constant(arg.value),
1221+
})
1222+
.collect();
1223+
Constant::RecordUpdate {
1224+
location,
1225+
module,
1226+
name,
1227+
record,
1228+
arguments,
1229+
tag,
1230+
type_,
1231+
field_map,
1232+
}
1233+
}
1234+
11791235
Constant::BitArray { location, segments } => {
11801236
let segments = segments
11811237
.into_iter()

compiler-core/src/call_graph.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,17 @@ impl<'a> CallGraphBuilder<'a> {
494494
}
495495
}
496496

497+
Constant::RecordUpdate {
498+
record, arguments, ..
499+
} => {
500+
// Visit the record being updated
501+
self.constant(record);
502+
// Visit the update arguments
503+
for argument in arguments {
504+
self.constant(&argument.value);
505+
}
506+
}
507+
497508
Constant::Var {
498509
module: None, name, ..
499510
} => self.referenced(name),

compiler-core/src/erlang.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,13 @@ fn const_inline<'a>(literal: &'a TypedConstant, env: &mut Env<'a>) -> Document<'
15501550
tuple(std::iter::once(tag).chain(arguments_doc))
15511551
}
15521552

1553+
Constant::RecordUpdate { .. } => {
1554+
// RecordUpdate should be expanded to Record during type checking, so this should never happen
1555+
panic!(
1556+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
1557+
)
1558+
}
1559+
15531560
Constant::Var {
15541561
name, constructor, ..
15551562
} => var(
@@ -3306,6 +3313,12 @@ fn find_referenced_private_functions(
33063313
.iter()
33073314
.for_each(|argument| find_referenced_private_functions(&argument.value, already_found)),
33083315

3316+
TypedConstant::RecordUpdate { .. } => {
3317+
panic!(
3318+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
3319+
)
3320+
}
3321+
33093322
TypedConstant::StringConcatenation { left, right, .. } => {
33103323
find_referenced_private_functions(left, already_found);
33113324
find_referenced_private_functions(right, already_found);

compiler-core/src/format.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,12 @@ impl<'comments> Formatter<'comments> {
539539
.group()
540540
}
541541

542+
Constant::RecordUpdate { .. } => {
543+
panic!(
544+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
545+
)
546+
}
547+
542548
Constant::Var {
543549
name, module: None, ..
544550
} => name.to_doc(),

compiler-core/src/javascript/expression.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,12 @@ impl<'module, 'a> Generator<'module, 'a> {
18561856
}
18571857
}
18581858

1859+
Constant::RecordUpdate { .. } => {
1860+
panic!(
1861+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
1862+
)
1863+
}
1864+
18591865
Constant::BitArray { segments, .. } => {
18601866
let bit_array = self.constant_bit_array(segments, context);
18611867
match context {

compiler-core/src/metadata/module_decoder.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,6 @@ impl ModuleDecoder {
437437
module: Default::default(),
438438
name: Default::default(),
439439
arguments,
440-
spread: None,
441440
tag,
442441
type_,
443442
field_map: None,

compiler-core/src/metadata/module_encoder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,12 @@ impl<'a> ModuleEncoder<'a> {
541541
self.build_type(builder.reborrow().init_type(), type_);
542542
}
543543

544+
Constant::RecordUpdate { .. } => {
545+
panic!(
546+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
547+
)
548+
}
549+
544550
Constant::Var {
545551
module,
546552
name,

compiler-core/src/metadata/tests.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,6 @@ fn constant_record() {
11641164
},
11651165
},
11661166
],
1167-
spread: None,
11681167
tag: "thetag".into(),
11691168
type_: type_::int(),
11701169
field_map: None,

0 commit comments

Comments
 (0)