Skip to content

Commit bc9e99c

Browse files
Add rule to compute expressions and improve evaluator
1 parent eccc572 commit bc9e99c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1346
-180
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "darklua"
3-
version = "0.3.5"
3+
version = "0.3.6"
44
authors = ["jeparlefrancais <jeparlefrancais21@gmail.com>"]
55
edition = "2018"
66
readme = "README.md"

RULES.md

+25
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
You can find the available rules and their properties here. The default rule stack is:
44

5+
- [Compute expressions](#compute-expressions)
56
- [Convert local functions to assignments](#convert-local-functions-to-assignments)
67
- [Group local assignments](#group-local-assignments)
78
- [Remove empty do statements](#remove-empty-do-statements)
@@ -17,6 +18,30 @@ There are also other rules available for more processing:
1718

1819
---
1920

21+
## Compute expression
22+
```compute_expression```
23+
24+
This rule computes expressions and replaces them with their result. An expression will not be replaced if it has any side-effects. This rule is influenced by the evaluation system of darklua. As its capacity increases, the rule will be able to compute more complex expressions. For example, if you use this rule on the following code:
25+
26+
```lua
27+
return 1 + 1
28+
```
29+
30+
Will produce the following code:
31+
32+
```lua
33+
return 2
34+
```
35+
36+
### Examples
37+
```json5
38+
{
39+
rule: 'compute_expression',
40+
}
41+
```
42+
43+
---
44+
2045
## Convert local functions to assignments
2146
```convert_local_function_to_assign```
2247

src/nodes/expressions/binary.rs

+199-11
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl BinaryOperator {
2727
}
2828

2929
#[inline]
30-
pub fn preceeds_unary_expression(&self) -> bool {
30+
pub fn precedes_unary_expression(&self) -> bool {
3131
match self {
3232
Self::Caret => true,
3333
_ => false,
@@ -50,6 +50,36 @@ impl BinaryOperator {
5050
}
5151
}
5252

53+
pub fn left_needs_parentheses(&self, left: &Expression) -> bool {
54+
match left {
55+
Expression::Binary(left) => {
56+
if self.is_left_associative() {
57+
self.precedes(left.operator())
58+
} else {
59+
!left.operator().precedes(*self)
60+
}
61+
}
62+
Expression::Unary(_) => {
63+
self.precedes_unary_expression()
64+
}
65+
_ => false,
66+
}
67+
}
68+
69+
pub fn right_needs_parentheses(&self, right: &Expression) -> bool {
70+
match right {
71+
Expression::Binary(right) => {
72+
if self.is_right_associative() {
73+
self.precedes(right.operator())
74+
} else {
75+
!right.operator().precedes(*self)
76+
}
77+
}
78+
Expression::Unary(_) => false,
79+
_ => false,
80+
}
81+
}
82+
5383
fn get_precedence(&self) -> u8 {
5484
match self {
5585
Self::Or => 0,
@@ -113,32 +143,51 @@ impl BinaryExpression {
113143
}
114144
}
115145

146+
#[inline]
116147
pub fn mutate_left(&mut self) -> &mut Expression {
117148
&mut self.left
118149
}
119150

151+
#[inline]
120152
pub fn mutate_right(&mut self) -> &mut Expression {
121153
&mut self.right
122154
}
123155

156+
#[inline]
124157
pub fn left(&self) -> &Expression {
125158
&self.left
126159
}
127160

161+
#[inline]
128162
pub fn right(&self) -> &Expression {
129163
&self.right
130164
}
131165

166+
#[inline]
132167
pub fn operator(&self) -> BinaryOperator {
133168
self.operator
134169
}
135170
}
136171

137172
impl ToLua for BinaryExpression {
138173
fn to_lua(&self, generator: &mut LuaGenerator) {
139-
self.left.to_lua(generator);
174+
if self.operator.left_needs_parentheses(&self.left) {
175+
generator.push_char('(');
176+
self.left.to_lua(generator);
177+
generator.push_char(')');
178+
} else {
179+
self.left.to_lua(generator);
180+
}
181+
140182
self.operator.to_lua(generator);
141-
self.right.to_lua(generator);
183+
184+
if self.operator.right_needs_parentheses(&self.right) {
185+
generator.push_char('(');
186+
self.right.to_lua(generator);
187+
generator.push_char(')');
188+
} else {
189+
self.right.to_lua(generator);
190+
}
142191
}
143192
}
144193

@@ -168,7 +217,7 @@ mod test {
168217
assert!(Caret.precedes(Percent));
169218
assert!(Caret.precedes(Concat));
170219
assert!(!Caret.precedes(Caret));
171-
assert!(Caret.preceeds_unary_expression());
220+
assert!(Caret.precedes_unary_expression());
172221
}
173222

174223
#[test]
@@ -188,7 +237,7 @@ mod test {
188237
assert!(!Asterisk.precedes(Percent));
189238
assert!(Asterisk.precedes(Concat));
190239
assert!(!Asterisk.precedes(Caret));
191-
assert!(!Asterisk.preceeds_unary_expression());
240+
assert!(!Asterisk.precedes_unary_expression());
192241
}
193242

194243
#[test]
@@ -208,7 +257,7 @@ mod test {
208257
assert!(!Slash.precedes(Percent));
209258
assert!(Slash.precedes(Concat));
210259
assert!(!Slash.precedes(Caret));
211-
assert!(!Slash.preceeds_unary_expression());
260+
assert!(!Slash.precedes_unary_expression());
212261
}
213262

214263
#[test]
@@ -228,7 +277,7 @@ mod test {
228277
assert!(!Percent.precedes(Percent));
229278
assert!(Percent.precedes(Concat));
230279
assert!(!Percent.precedes(Caret));
231-
assert!(!Percent.preceeds_unary_expression());
280+
assert!(!Percent.precedes_unary_expression());
232281
}
233282

234283
#[test]
@@ -248,7 +297,7 @@ mod test {
248297
assert!(!Plus.precedes(Percent));
249298
assert!(Plus.precedes(Concat));
250299
assert!(!Plus.precedes(Caret));
251-
assert!(!Plus.preceeds_unary_expression());
300+
assert!(!Plus.precedes_unary_expression());
252301
}
253302

254303
#[test]
@@ -268,7 +317,7 @@ mod test {
268317
assert!(!Minus.precedes(Percent));
269318
assert!(Minus.precedes(Concat));
270319
assert!(!Minus.precedes(Caret));
271-
assert!(!Minus.preceeds_unary_expression());
320+
assert!(!Minus.precedes_unary_expression());
272321
}
273322

274323
#[test]
@@ -288,7 +337,7 @@ mod test {
288337
assert!(!Concat.precedes(Percent));
289338
assert!(!Concat.precedes(Concat));
290339
assert!(!Concat.precedes(Caret));
291-
assert!(!Concat.preceeds_unary_expression());
340+
assert!(!Concat.precedes_unary_expression());
292341
}
293342

294343
#[test]
@@ -308,7 +357,146 @@ mod test {
308357
assert!(!And.precedes(Percent));
309358
assert!(!And.precedes(Concat));
310359
assert!(!And.precedes(Caret));
311-
assert!(!And.preceeds_unary_expression());
360+
assert!(!And.precedes_unary_expression());
361+
}
362+
}
363+
364+
mod to_lua {
365+
use super::*;
366+
367+
use crate::nodes::{DecimalNumber, UnaryExpression, UnaryOperator};
368+
369+
#[test]
370+
fn left_associative_wraps_left_operand_if_has_lower_precedence() {
371+
let expression = BinaryExpression::new(
372+
BinaryOperator::Asterisk,
373+
DecimalNumber::new(2.0).into(),
374+
BinaryExpression::new(
375+
BinaryOperator::Plus,
376+
DecimalNumber::new(1.0).into(),
377+
DecimalNumber::new(3.0).into(),
378+
).into(),
379+
);
380+
381+
assert_eq!("2*(1+3)", expression.to_lua_string());
382+
}
383+
384+
#[test]
385+
fn left_associative_wraps_right_operand_if_has_lower_precedence() {
386+
let expression = BinaryExpression::new(
387+
BinaryOperator::And,
388+
Expression::False,
389+
BinaryExpression::new(
390+
BinaryOperator::Or,
391+
Expression::False,
392+
Expression::True,
393+
).into(),
394+
);
395+
396+
assert_eq!("false and(false or true)", expression.to_lua_string());
397+
}
398+
399+
#[test]
400+
fn left_associative_wraps_right_operand_if_has_same_precedence() {
401+
let expression = BinaryExpression::new(
402+
BinaryOperator::Equal,
403+
Expression::True,
404+
BinaryExpression::new(
405+
BinaryOperator::LowerThan,
406+
DecimalNumber::new(1.0).into(),
407+
DecimalNumber::new(2.0).into(),
408+
).into(),
409+
);
410+
411+
assert_eq!("true==(1<2)", expression.to_lua_string());
412+
}
413+
414+
#[test]
415+
fn right_associative_wrap_unary_left_operand_if_has_lower_precedence() {
416+
let expression = BinaryExpression::new(
417+
BinaryOperator::Caret,
418+
UnaryExpression::new(
419+
UnaryOperator::Minus,
420+
DecimalNumber::new(2.0).into(),
421+
).into(),
422+
DecimalNumber::new(2.0).into(),
423+
);
424+
425+
assert_eq!("(-2)^2", expression.to_lua_string());
426+
}
427+
428+
#[test]
429+
fn right_associative_wraps_left_operand_if_has_lower_precedence() {
430+
let expression = BinaryExpression::new(
431+
BinaryOperator::Caret,
432+
BinaryExpression::new(
433+
BinaryOperator::Plus,
434+
DecimalNumber::new(1.0).into(),
435+
DecimalNumber::new(2.0).into(),
436+
).into(),
437+
DecimalNumber::new(3.0).into(),
438+
);
439+
440+
assert_eq!("(1+2)^3", expression.to_lua_string());
441+
}
442+
443+
#[test]
444+
fn right_associative_wraps_left_operand_if_has_same_precedence() {
445+
let expression = BinaryExpression::new(
446+
BinaryOperator::Caret,
447+
BinaryExpression::new(
448+
BinaryOperator::Caret,
449+
DecimalNumber::new(2.0).into(),
450+
DecimalNumber::new(2.0).into(),
451+
).into(),
452+
DecimalNumber::new(3.0).into(),
453+
);
454+
455+
assert_eq!("(2^2)^3", expression.to_lua_string());
456+
}
457+
458+
#[test]
459+
fn right_associative_does_not_wrap_right_operand_if_unary() {
460+
let expression = BinaryExpression::new(
461+
BinaryOperator::Caret,
462+
DecimalNumber::new(2.0).into(),
463+
UnaryExpression::new(
464+
UnaryOperator::Minus,
465+
DecimalNumber::new(2.0).into(),
466+
).into(),
467+
);
468+
469+
assert_eq!("2^-2", expression.to_lua_string());
470+
}
471+
472+
#[test]
473+
fn right_associative_does_not_wrap_right_operand_if_has_same_precedence() {
474+
let expression = BinaryExpression::new(
475+
BinaryOperator::Caret,
476+
DecimalNumber::new(2.0).into(),
477+
BinaryExpression::new(
478+
BinaryOperator::Caret,
479+
DecimalNumber::new(2.0).into(),
480+
DecimalNumber::new(3.0).into(),
481+
).into(),
482+
);
483+
484+
assert_eq!("2^2^3", expression.to_lua_string());
485+
}
486+
487+
#[test]
488+
fn right_associative_does_not_wrap_right_operand_if_has_higher_precedence() {
489+
let expression = BinaryExpression::new(
490+
BinaryOperator::Concat,
491+
DecimalNumber::new(3.0).into(),
492+
BinaryExpression::new(
493+
BinaryOperator::Plus,
494+
DecimalNumber::new(9.0).into(),
495+
DecimalNumber::new(3.0).into(),
496+
).into(),
497+
);
498+
499+
assert_eq!("3 ..9+3", expression.to_lua_string());
312500
}
313501
}
314502

0 commit comments

Comments
 (0)