Skip to content

Commit 2679b11

Browse files
authored
Fix calc function (#506)
1 parent 95a9de9 commit 2679b11

File tree

9 files changed

+102
-100
lines changed

9 files changed

+102
-100
lines changed

e2e/melange/src/ui/ui.re

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module Cositas = [%styled.div
2222
display: flex;
2323
flex-direction: column;
2424
gap: $(lola);
25+
height: calc(1px * (2 + 3 / 3));
2526
|}
2627
];
2728

packages/css-property-parser/lib/Parser.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ and calc_product = [%value.rec
131131
and calc_sum = [%value.rec "<calc-product> [ [ '+' | '-' ] <calc-product> ]*"]
132132
/* and calc_value = [%value.rec "<number> | <dimension> | <extended-percentage> | <calc>"] */
133133
and calc_value = [%value.rec
134-
"<number> | <extended-length> | <extended-percentage> | <extended-angle> | <extended-time>"
134+
"<number> | <extended-length> | <extended-percentage> | <extended-angle> | <extended-time> | '(' <calc-sum> ')'"
135135
]
136136
and cf_final_image = [%value.rec "<image> | <color>"]
137137
and cf_mixing_image = [%value.rec "[ <extended-percentage> ]? && <image>"]

packages/css-property-parser/lib/Standard.re

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ open Rule.Pattern;
44

55
let keyword = string => expect(IDENT(string));
66
let comma = expect(COMMA);
7-
let delim = string => expect(DELIM(string));
7+
let delim =
8+
fun
9+
| "(" => expect(LEFT_PAREN)
10+
| ")" => expect(RIGHT_PAREN)
11+
| "[" => expect(LEFT_BRACKET)
12+
| "]" => expect(RIGHT_BRACKET)
13+
| ":" => expect(COLON)
14+
| ";" => expect(SEMI_COLON)
15+
| s => expect(DELIM(s));
816
let function_call = (name, rule) => {
917
let.bind_match () =
1018
token(

packages/ppx/src/Property_to_runtime.re

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -320,28 +320,33 @@ let render_length = (~loc) =>
320320
| `Zero => [%expr `zero];
321321

322322
let rec render_function_calc = (~loc, calc_sum) => {
323-
render_calc_sum(~loc, calc_sum);
323+
[%expr `calc([%e render_calc_sum(~loc, calc_sum)])];
324324
}
325325

326-
and render_calc_sum = (~loc, calc_sum) => {
327-
switch (calc_sum) {
328-
| (product, []) => render_product(~loc, product)
329-
| (product, list_of_sums) =>
330-
/* This isn't a great design of the types, but we need to know the operation
331-
which is in the first position of the array, we ensure that there's one value
332-
since we are on this branch of the switch */
333-
let op = pick_operation(List.hd(list_of_sums));
334-
switch (op) {
335-
| `Dash () =>
336-
let first = render_product(~loc, product);
337-
let second = render_list_of_sums(~loc, list_of_sums);
338-
[%expr `calc(`sub(([%e first], [%e second])))];
339-
| `Cross () =>
340-
let first = render_product(~loc, product);
341-
let second = render_list_of_sums(~loc, list_of_sums);
342-
[%expr `calc(`add(([%e first], [%e second])))];
326+
and render_calc_sum = (~loc, (product, sums): Types.calc_sum) => {
327+
let rec go = (left, rest) => {
328+
switch (rest) {
329+
| [] => left
330+
| [x, ...xs] =>
331+
switch (x) {
332+
| (`Cross (), calc_product) =>
333+
go(
334+
[%expr
335+
`add(([%e left], [%e render_calc_product(~loc, calc_product)]))
336+
],
337+
xs,
338+
)
339+
| (`Dash (), calc_product) =>
340+
go(
341+
[%expr
342+
`sub(([%e left], [%e render_calc_product(~loc, calc_product)]))
343+
],
344+
xs,
345+
)
346+
}
343347
};
344348
};
349+
go(render_calc_product(~loc, product), sums);
345350
}
346351
and render_function_min_or_max = (~loc, calc_sums: list(Types.calc_sum)) => {
347352
switch (calc_sums) {
@@ -357,33 +362,26 @@ and render_function_min = (~loc, calc_sums) => {
357362
and render_function_max = (~loc, calc_sums) => {
358363
[%expr `max([%e render_function_min_or_max(~loc, calc_sums)])];
359364
}
360-
and pick_operation = ((op, _)) => op
361-
and render_list_of_products = (~loc, list_of_products) => {
362-
switch (list_of_products) {
363-
| [one] => render_product_op(~loc, one)
364-
| list => render_list_of_products(~loc, list)
365-
};
366-
}
367-
and render_list_of_sums = (~loc, list_of_sums) => {
368-
switch (list_of_sums) {
369-
| [(_, one)] => render_product(~loc, one)
370-
| list => render_list_of_sums(~loc, list)
371-
};
372-
}
373-
and render_product = (~loc, product) => {
374-
switch (product) {
375-
| (calc_value, []) => render_calc_value(~loc, calc_value)
376-
| (calc_value, list_of_products) =>
377-
let first = render_calc_value(~loc, calc_value);
378-
let second = render_list_of_products(~loc, list_of_products);
379-
[%expr `calc(`mult(([%e first], [%e second])))];
380-
};
381-
}
382-
and render_product_op = (~loc, op) => {
383-
switch (op) {
384-
| `Static_0((), calc_value) => render_calc_value(~loc, calc_value)
385-
| `Static_1((), float) => [%expr `num([%e render_float(~loc, float)])]
365+
and render_calc_product = (~loc, (value, products): Types.calc_product) => {
366+
let rec go = (left, rest) => {
367+
switch (rest) {
368+
| [] => left
369+
| [x, ...xs] =>
370+
switch (x) {
371+
| `Static_0(_, value) =>
372+
go(
373+
[%expr `mult(([%e left], [%e render_calc_value(~loc, value)]))],
374+
xs,
375+
)
376+
| `Static_1(_, float_value) =>
377+
go(
378+
[%expr `div(([%e left], [%e render_float(~loc, float_value)]))],
379+
xs,
380+
)
381+
}
382+
};
386383
};
384+
go(render_calc_value(~loc, value), products);
387385
}
388386
and render_angle = (~loc) =>
389387
fun
@@ -434,6 +432,7 @@ and render_calc_value = (~loc, calc_value) => {
434432
| `Extended_percentage(p) => render_extended_percentage(~loc, p)
435433
| `Extended_angle(a) => render_extended_angle(~loc, a)
436434
| `Extended_time(t) => render_extended_time(~loc, t)
435+
| `Static(_, calc_sum, _) => render_calc_sum(~loc, calc_sum)
437436
};
438437
}
439438
and render_extended_length = (~loc) =>

packages/ppx/src/Property_to_string.re

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -133,21 +133,31 @@ let render_length =
133133
| `Vw(n) => render_number(n, "vw")
134134
| `Zero => render_string("0");
135135

136-
let rec render_function_calc = calc_sum => {
137-
render_calc_sum(calc_sum);
136+
let rec render_function_calc =
137+
(calc_sum: Css_property_parser.Parser.Types.calc_sum) => {
138+
[%expr "calc(" ++ [%e render_calc_sum(calc_sum)] ++ ")"];
139+
}
140+
and render_calc_sum = ((product, sums)) => {
141+
let rec go = (left, rest) => {
142+
switch (rest) {
143+
| [] => left
144+
| [x, ...xs] =>
145+
switch (x) {
146+
| (`Cross (), calc_product) =>
147+
go(
148+
[%expr [%e left] ++ " + " ++ [%e render_product(calc_product)]],
149+
xs,
150+
)
151+
| (`Dash (), calc_product) =>
152+
go(
153+
[%expr [%e left] ++ " - " ++ [%e render_product(calc_product)]],
154+
xs,
155+
)
156+
}
157+
};
158+
};
159+
go(render_product(product), sums);
138160
}
139-
and render_calc_sum = calc_sum =>
140-
switch (calc_sum) {
141-
| (product, []) => render_product(product)
142-
| (product, list_of_sums) =>
143-
/* This isn't a great design of the types, but we need to know the operation
144-
which is in the first position of the array, we ensure that there's one value
145-
since we are on this branch of the switch */
146-
let op = pick_operation(List.hd(list_of_sums));
147-
let first = render_product(product);
148-
let second = render_list_of_sums(list_of_sums);
149-
[%expr "calc(" ++ [%e first] ++ [%e op] ++ [%e second] ++ ")"];
150-
}
151161
and render_function_min_or_max = calc_sums => {
152162
switch (calc_sums) {
153163
| [] => raise(Invalid_value("expected at least one argument"))
@@ -162,39 +172,23 @@ and render_function_min = calc_sums => {
162172
and render_function_max = calc_sums => {
163173
render_function_min_or_max(calc_sums);
164174
}
165-
and render_sum_op = op => {
166-
switch (op) {
167-
| `Dash () => [%expr " - "]
168-
| `Cross () => [%expr " + "]
169-
};
170-
}
171-
and pick_operation = ((op, _)) => render_sum_op(op)
172-
and render_list_of_products = list_of_products => {
173-
switch (list_of_products) {
174-
| [one] => render_product_op(one)
175-
| list => render_list_of_products(list)
176-
};
177-
}
178-
and render_list_of_sums = list_of_sums => {
179-
switch (list_of_sums) {
180-
| [(_, one)] => render_product(one)
181-
| list => render_list_of_sums(list)
182-
};
183-
}
184-
and render_product = product => {
185-
switch (product) {
186-
| (calc_value, []) => render_calc_value(calc_value)
187-
| (calc_value, list_of_products) =>
188-
let first = render_calc_value(calc_value);
189-
let second = render_list_of_products(list_of_products);
190-
[%expr "calc(" ++ [%e first] ++ " * " ++ [%e second] ++ ")"];
191-
};
192-
}
193-
and render_product_op = op => {
194-
switch (op) {
195-
| `Static_0((), calc_value) => render_calc_value(calc_value)
196-
| `Static_1((), float) => render_number(float, "")
175+
and render_product = ((value, products)) => {
176+
let rec go = (left, rest) => {
177+
switch (rest) {
178+
| [] => left
179+
| [x, ...xs] =>
180+
switch (x) {
181+
| `Static_0(_, value) =>
182+
go([%expr [%e left] ++ " * " ++ [%e render_calc_value(value)]], xs)
183+
| `Static_1(_, float_value) =>
184+
go(
185+
[%expr [%e left] ++ " / " ++ [%e render_number(float_value, "")]],
186+
xs,
187+
)
188+
}
189+
};
197190
};
191+
go(render_calc_value(value), products);
198192
}
199193
and render_calc_value = calc_value => {
200194
switch (calc_value) {
@@ -203,6 +197,7 @@ and render_calc_value = calc_value => {
203197
| `Extended_percentage(p) => render_extended_percentage(p)
204198
| `Extended_angle(a) => render_extended_angle(a)
205199
| `Extended_time(t) => render_extended_time(t)
200+
| `Static(_, calc_sum, _) => render_calc_sum(calc_sum)
206201
};
207202
}
208203
and render_time_as_int =

packages/ppx/test/css-support/calc.t/run.t

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,7 @@ If this test fail means that the module is not in sync with the ppx
5353
`calc(
5454
`mult((
5555
`rem(2.),
56-
`calc(
57-
`mult((`rem(2.), `calc(`mult((`rem(2.), `num(4.)))))),
58-
),
56+
`calc(`mult((`rem(2.), `calc(`div((`rem(2.), 4.)))))),
5957
)),
6058
),
6159
)),

packages/ppx/test/css-support/color-module.t/run.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,5 +350,5 @@ If this test fail means that the module is not in sync with the ppx
350350
{js|color-mix(in lab, teal 65%, olive)|js},
351351
);
352352

353-
CSS.color(`rgba((0, 0, 0, `num(1.))));
353+
CSS.color(`rgba((0, 0, 0, `calc(`num(1.)))));
354354
CSS.color(`rgba((0, 0, 0, `calc(`sub((`num(10.), `num(1.)))))));

packages/ppx/test/native/Static_test.re

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -668,11 +668,10 @@ let properties_static_css_tests = [
668668
[%expr [%css "flex: none"]],
669669
[%expr CSS.flex1(`none)],
670670
),
671-
/* Since calc(x) -> x */
672671
(
673672
[%css "width: calc(100px)"],
674673
[%expr [%css "width: calc(100px)"]],
675-
[%expr CSS.width(`pxFloat(100.))],
674+
[%expr CSS.width(`calc(`pxFloat(100.)))],
676675
),
677676
(
678677
[%css "width: calc(100% + 32px)"],
@@ -1166,12 +1165,12 @@ let properties_static_css_tests = [
11661165
(
11671166
[%css "transition-duration: max(3s, calc(1ms))"],
11681167
[%expr [%css "transition-duration: max(3s, calc(1ms))"]],
1169-
[%expr CSS.transitionDuration(`max([|`s(3), `ms(1)|]))],
1168+
[%expr CSS.transitionDuration(`max([|`s(3), `calc(`ms(1))|]))],
11701169
),
11711170
(
11721171
[%css "transition-duration: max(+3s, calc(-0ms))"],
11731172
[%expr [%css "transition-duration: max(+3s, calc(-0ms))"]],
1174-
[%expr CSS.transitionDuration(`max([|`s(3), `ms(0)|]))],
1173+
[%expr CSS.transitionDuration(`max([|`s(3), `calc(`ms(0))|]))],
11751174
),
11761175
(
11771176
[%css "animation: 3s"],

packages/runtime/native/shared/Css_types.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ module Calc = struct
7070
{js|calc(|js} ^ fn a ^ {js| * |js} ^ fn b ^ {js|)|js}
7171
| `calc (`div (a, b)) ->
7272
{js|calc(|js} ^ fn a ^ {js| / |js} ^ Kloth.Float.to_string b ^ {js|)|js}
73+
| `calc (`num a) -> {js|calc(|js} ^ Kloth.Float.to_string a ^ {js|)|js}
7374
| `num n -> Kloth.Float.to_string n
7475
| `min xs -> {js|min(|js} ^ max_or_min_values fn xs ^ {js|)|js}
7576
| `max xs -> {js|max(|js} ^ max_or_min_values fn xs ^ {js|)|js}
@@ -1314,6 +1315,7 @@ module Color = struct
13141315
| `sub of 'a * 'a
13151316
| `mult of 'a * 'a
13161317
| `div of 'a * float
1318+
| `num of float
13171319
]
13181320
| `min of 'a array
13191321
| `max of 'a array

0 commit comments

Comments
 (0)