diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 49d8086a9..3c1cb6771 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -113,6 +113,7 @@ pub enum BinaryOp { Div, Pow, Mod, + FloatMod, Eq, NotEq, Less, @@ -142,6 +143,7 @@ impl fmt::Display for BinaryOp { Div => "/", Pow => "**", Mod => "%", + FloatMod => "%%", Eq => "==", NotEq => "!=", Less => "<", @@ -172,6 +174,7 @@ pub enum AssignOp { MulAssign, DivAssign, ModAssign, + FloatModAssign, AssignInto, BitAndAssign, AndAssign, @@ -192,6 +195,7 @@ impl fmt::Display for AssignOp { MulAssign => "*=", DivAssign => "/=", ModAssign => "%=", + FloatModAssign => "%%=", AssignInto => ":=", BitAndAssign => "&=", AndAssign => "&&=", @@ -233,6 +237,7 @@ augmented! { Mul = MulAssign; Div = DivAssign; Mod = ModAssign; + FloatMod = FloatModAssign; BitAnd = BitAndAssign; BitOr = BitOrAssign; BitXor = BitXorAssign; diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 40adc04de..c75a240cf 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -684,6 +684,14 @@ impl<'a> ConstantFolder<'a> { numeric!(LessEq <=); numeric!(Greater >); numeric!(GreaterEq >=); + match (op, lhs, rhs) { + (BinaryOp::FloatMod, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs - ((lhs / rhs).floor() * rhs))), + (_, lhs_, rhs_) => { + lhs = lhs_; + rhs = rhs_; + } + } + match (op, lhs, rhs) { (BinaryOp::Pow, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs.powf(rhs))), (_, lhs_, rhs_) => { diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index ed4c46d22..6a5abde35 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -71,9 +71,12 @@ table! { "!", Not; "!=", NotEq; "\"", DoubleQuote; + "\"\"", EmptyQuote; "#", Hash; "##", TokenPaste; "%", Mod; + "%%", FloatMod; + "%%=", FloatModAssign; "%=", ModAssign; "&", BitAnd; "&&", And; @@ -146,22 +149,26 @@ impl fmt::Display for Punctuation { /// character in the input, blazing fast. The code to generate it is contained /// in the following test. static SPEEDY_TABLE: [(usize, usize); 127] = [ - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 10), (10, 14), (14, 15), - (15, 16), (16, 17), (17, 20), (20, 23), (23, 24), (24, 27), (27, 30), (30, 34), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (34, 37), (37, 38), (38, 43), (43, 45), (45, 49), (49, 53), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (53, 54), (0, 0), (54, 55), (55, 57), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (57, 59), (59, 63), (63, 64), (64, 67)]; + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (2, 3), (3, 5), (5, 7), + (7, 9), (0, 0), (9, 13), (13, 17), (17, 18), (18, 19), (19, 20), + (20, 23), (23, 26), (26, 27), (27, 30), (30, 33), (33, 37), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (37, 40), (40, 41), (41, 46), (46, 48), (48, 52), + (52, 56), (0, 0), (0,0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (56, 57), (0, 0), (57, 58), (58, 60), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (60, 62), (62, 66), (66, 67), + (67, 70) + ]; #[test] fn make_speedy_table() { @@ -278,6 +285,7 @@ impl Token { Eq | NotEq | Mod | + FloatMod | And | BitAndAssign | AndAssign | diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index cde624246..922ba0cc3 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -150,11 +150,12 @@ oper_table! { BINARY_OPS; Pow { (BinaryOp, Pow), } - // * / % + // * / % %% Mul { (BinaryOp, Mul), // (BinaryOp, Div = Slash), // (BinaryOp, Mod), + (BinaryOp, FloatMod), } // + - Add { @@ -205,7 +206,7 @@ oper_table! { BINARY_OPS; Conditional { (TernaryOp, Conditional = QuestionMark), } - // = += -= -= *= /= %= &= |= ^= <<= >>= + // = += -= -= *= /= %= %%= &= |= ^= <<= >>= Assign { (AssignOp, Assign), (AssignOp, AddAssign), @@ -213,6 +214,7 @@ oper_table! { BINARY_OPS; (AssignOp, MulAssign), (AssignOp, DivAssign), (AssignOp, ModAssign), + (AssignOp, FloatModAssign), (AssignOp, BitAndAssign), (AssignOp, BitOrAssign), (AssignOp, BitXorAssign), @@ -887,6 +889,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { last_part.push('%'); } else if self.exact(Punct(ModAssign))?.is_some() { last_part.push_str("%="); + } else if self.exact(Punct(FloatMod))?.is_some() { + last_part.push_str("%%"); + } else if self.exact(Punct(FloatModAssign))?.is_some() { + last_part.push_str("%%="); } else if self.exact(Punct(BitAnd))?.is_some() { last_part.push('&'); } else if self.exact(Punct(BitAndAssign))?.is_some() { @@ -944,6 +950,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else { last_part.push_str("[]"); } + } else if self.exact(Punct(EmptyQuote))?.is_some() { + last_part.push_str("\"\"") } SUCCESS }