Skip to content

Commit

Permalink
Make sure all constants inside a module constant definition are marke…
Browse files Browse the repository at this point in the history
…d as pure
  • Loading branch information
giacomocavalieri authored and lpil committed Jul 8, 2024
1 parent e184da3 commit 4715c0a
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 34 deletions.
17 changes: 7 additions & 10 deletions compiler-core/src/javascript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
};
use camino::Utf8Path;
use ecow::EcoString;
use expression::NeedsPureAnnotation;
use expression::IsModuleConstantDefinition;
use itertools::Itertools;

use self::import::{Imports, Member};
Expand Down Expand Up @@ -466,19 +466,16 @@ impl<'a> Generator<'a> {
"export const "
};

let mut needs_pure_annotation = NeedsPureAnnotation::No;
let document =
expression::constant_expression(&mut needs_pure_annotation, &mut self.tracker, value)?;

let equals = match needs_pure_annotation {
NeedsPureAnnotation::Yes => " = /* @__PURE__ */ ",
NeedsPureAnnotation::No => " = ",
};
let document = expression::constant_expression(
IsModuleConstantDefinition::Yes,
&mut self.tracker,
value,
)?;

Ok(docvec![
head,
maybe_escape_identifier_doc(name),
equals,
" = ",
document,
";",
])
Expand Down
44 changes: 27 additions & 17 deletions compiler-core/src/javascript/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ impl<'module> Generator<'module> {
) -> Output<'a> {
match &constructor.variant {
ValueConstructorVariant::LocalConstant { literal } => {
constant_expression(&mut NeedsPureAnnotation::No, self.tracker, literal)
constant_expression(IsModuleConstantDefinition::No, self.tracker, literal)
}
ValueConstructorVariant::Record { arity, .. } => {
Ok(self.record_constructor(constructor.type_.clone(), None, name, *arity))
Expand Down Expand Up @@ -1250,17 +1250,18 @@ pub(crate) fn guard_constant_expression<'a>(
.map(|assignment| assignment.subject.clone().append(assignment.path.clone()))
.unwrap_or_else(|| maybe_escape_identifier_doc(name))),

expression => constant_expression(&mut NeedsPureAnnotation::No, tracker, expression),
expression => constant_expression(IsModuleConstantDefinition::No, tracker, expression),
}
}

pub enum NeedsPureAnnotation {
#[derive(Debug, Clone, Copy)]
pub enum IsModuleConstantDefinition {
Yes,
No,
}

pub(crate) fn constant_expression<'a>(
needs_pure_annotation: &mut NeedsPureAnnotation,
usage: IsModuleConstantDefinition,
tracker: &mut UsageTracker,
expression: &'a TypedConstant,
) -> Output<'a> {
Expand All @@ -1271,18 +1272,21 @@ pub(crate) fn constant_expression<'a>(
Constant::Tuple { elements, .. } => array(
elements
.iter()
.map(|e| constant_expression(needs_pure_annotation, tracker, e)),
.map(|e| constant_expression(usage, tracker, e)),
),

Constant::List { elements, .. } => {
tracker.list_used = true;
let result = list(
let list = list(
elements
.iter()
.map(|e| constant_expression(needs_pure_annotation, tracker, e)),
);
*needs_pure_annotation = NeedsPureAnnotation::Yes;
result
.map(|e| constant_expression(usage, tracker, e)),
)?;

match usage {
IsModuleConstantDefinition::Yes => Ok(docvec!["/* @__PURE__ */ ", list]),
IsModuleConstantDefinition::No => Ok(list),
}
}

Constant::Record { typ, name, .. } if typ.is_bool() && name == "True" => {
Expand Down Expand Up @@ -1310,18 +1314,24 @@ pub(crate) fn constant_expression<'a>(
}
let field_values: Vec<_> = args
.iter()
.map(|arg| constant_expression(needs_pure_annotation, tracker, &arg.value))
.map(|arg| constant_expression(usage, tracker, &arg.value))
.try_collect()?;

*needs_pure_annotation = NeedsPureAnnotation::Yes;
Ok(construct_record(module.as_deref(), name, field_values))
let constructor = construct_record(module.as_deref(), name, field_values);
match usage {
IsModuleConstantDefinition::Yes => Ok(docvec!["/* @__PURE__ */ ", constructor]),
IsModuleConstantDefinition::No => Ok(constructor),
}
}

Constant::BitArray { segments, .. } => {
*needs_pure_annotation = NeedsPureAnnotation::Yes;
bit_array(tracker, segments, |tracker, expr| {
constant_expression(needs_pure_annotation, tracker, expr)
})
let bit_array = bit_array(tracker, segments, |tracker, expr| {
constant_expression(usage, tracker, expr)
})?;
match usage {
IsModuleConstantDefinition::Yes => Ok(docvec!["/* @__PURE__ */ ", bit_array]),
IsModuleConstantDefinition::No => Ok(bit_array),
}
}

Constant::Var { name, module, .. } => Ok({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,9 @@ export const data = /* @__PURE__ */ toBitArray([
sizedInt(0x4, 32),
stringBits("Gleam"),
float64Bits(4.2),
toBitArray([toBitArray([1, 2, 3]).buffer, stringBits("Gleam"), 1024]).buffer,
/* @__PURE__ */ toBitArray([
/* @__PURE__ */ toBitArray([1, 2, 3]).buffer,
stringBits("Gleam"),
1024,
]).buffer,
]);
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export class X extends $CustomType {
}
}

export const x = /* @__PURE__ */ new X(1, toList(["1"]));
export const x = /* @__PURE__ */ new X(1, /* @__PURE__ */ toList(["1"]));

const y = /* @__PURE__ */ new X(1, toList([]));
const y = /* @__PURE__ */ new X(1, /* @__PURE__ */ toList([]));
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export class X extends $CustomType {
}
}

export const x = /* @__PURE__ */ toList([new X(1, toList(["1"]))]);
export const x = /* @__PURE__ */ toList([
/* @__PURE__ */ new X(1, /* @__PURE__ */ toList(["1"])),
]);

const y = /* @__PURE__ */ toList([new X(1, toList(["1"]))]);
const y = /* @__PURE__ */ toList([
/* @__PURE__ */ new X(1, /* @__PURE__ */ toList(["1"])),
]);
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ export class X extends $CustomType {
}
}

export const x = /* @__PURE__ */ [new X(1, toList(["1"]))];
export const x = [/* @__PURE__ */ new X(1, /* @__PURE__ */ toList(["1"]))];

const y = /* @__PURE__ */ [new X(1, toList(["1"]))];
const y = [/* @__PURE__ */ new X(1, /* @__PURE__ */ toList(["1"]))];

0 comments on commit 4715c0a

Please sign in to comment.