Skip to content

Commit 7f5b0cd

Browse files
committed
Add tests and do some refactoring
1 parent 5a3ee45 commit 7f5b0cd

18 files changed

+541
-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::ast::typed::pairwise_all;

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
@@ -317,6 +339,7 @@ impl<A, B> Constant<A, B> {
317339
| Constant::Tuple { location, .. }
318340
| Constant::String { location, .. }
319341
| Constant::Record { location, .. }
342+
| Constant::RecordUpdate { location, .. }
320343
| Constant::BitArray { location, .. }
321344
| Constant::Var { location, .. }
322345
| Constant::Invalid { location, .. }
@@ -335,6 +358,7 @@ impl<A, B> Constant<A, B> {
335358
Constant::Tuple { .. }
336359
| Constant::List { .. }
337360
| Constant::Record { .. }
361+
| Constant::RecordUpdate { .. }
338362
| Constant::BitArray { .. }
339363
| Constant::StringConcatenation { .. }
340364
| Constant::Invalid { .. } => false,
@@ -357,3 +381,26 @@ impl<A, B> bit_array::GetLiteralValue for Constant<A, B> {
357381
}
358382
}
359383
}
384+
385+
#[derive(Debug, Clone, PartialEq, Eq)]
386+
pub struct ConstantRecordUpdateArg<Constant> {
387+
pub label: EcoString,
388+
pub location: SrcSpan,
389+
pub value: Constant,
390+
}
391+
392+
impl<Constant> ConstantRecordUpdateArg<Constant> {
393+
#[must_use]
394+
pub fn uses_label_shorthand(&self) -> bool
395+
where
396+
Constant: HasLocation,
397+
{
398+
self.value.location() == self.location
399+
}
400+
}
401+
402+
impl<Constant> HasLocation for ConstantRecordUpdateArg<Constant> {
403+
fn location(&self) -> SrcSpan {
404+
self.location
405+
}
406+
}

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
@@ -1514,6 +1514,13 @@ fn const_inline<'a>(literal: &'a TypedConstant, env: &mut Env<'a>) -> Document<'
15141514
tuple(std::iter::once(tag).chain(arguments_doc))
15151515
}
15161516

1517+
Constant::RecordUpdate { .. } => {
1518+
// RecordUpdate should be expanded to Record during type checking, so this should never happen
1519+
panic!(
1520+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
1521+
)
1522+
}
1523+
15171524
Constant::Var {
15181525
name, constructor, ..
15191526
} => var(
@@ -3268,6 +3275,12 @@ fn find_referenced_private_functions(
32683275
.iter()
32693276
.for_each(|argument| find_referenced_private_functions(&argument.value, already_found)),
32703277

3278+
TypedConstant::RecordUpdate { .. } => {
3279+
panic!(
3280+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
3281+
)
3282+
}
3283+
32713284
TypedConstant::StringConcatenation { left, right, .. } => {
32723285
find_referenced_private_functions(left, already_found);
32733286
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
@@ -543,6 +543,12 @@ impl<'comments> Formatter<'comments> {
543543
.group()
544544
}
545545

546+
Constant::RecordUpdate { .. } => {
547+
panic!(
548+
"Encountered RecordUpdate in code generation - this should have been expanded during type checking"
549+
)
550+
}
551+
546552
Constant::Var {
547553
name, module: None, ..
548554
} => 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)