From 0a611048f13d1a2d0a4b0ad30c9dbb1ed6fd6120 Mon Sep 17 00:00:00 2001 From: Anton Kesy Date: Fri, 15 Mar 2024 11:49:46 +0100 Subject: [PATCH] add fizz-buzz --- README.md | 4 ++++ examples/fizzbuzz.mmm | 12 ++++++++++++ src/Interpreter/Operation.hs | 11 +++++++++++ src/Parser/Expression.hs | 30 +++++++++++++++++++++++------- src/Parser/Operator.hs | 28 ++++++++++++++-------------- test/Unit/Parser/Atomic.hs | 2 +- test/Unit/Parser/Expression.hs | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 examples/fizzbuzz.mmm diff --git a/README.md b/README.md index d126869..d087305 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ void main() { } ``` +## Limitations + +- left side of operation has to be atomic + ## Usage ```bash diff --git a/examples/fizzbuzz.mmm b/examples/fizzbuzz.mmm new file mode 100644 index 0000000..f25a8c3 --- /dev/null +++ b/examples/fizzbuzz.mmm @@ -0,0 +1,12 @@ +int i = 1; +while i <= 100 { + println(str(i) + ": " + fizzbuzz(i)); + i = i + 1; +} + +str fizzbuzz(int i) { + if 0 == (i % 15) { return "FizzBuzz"; } + if 0 == (i % 3) { return "Fizz"; } + if 0 == (i % 5) { return "Buzz"; } + return str(i); +} diff --git a/src/Interpreter/Operation.hs b/src/Interpreter/Operation.hs index 5617e5c..61eba13 100644 --- a/src/Interpreter/Operation.hs +++ b/src/Interpreter/Operation.hs @@ -4,16 +4,27 @@ import AST import Interpreter.ProgramState interpretOperation :: Operator -> Value -> Value -> Value +-- Bool +interpretOperation Lt (BoolValue left) (BoolValue right) = BoolValue $ left < right +interpretOperation Gt (BoolValue left) (BoolValue right) = BoolValue $ left > right +interpretOperation Le (BoolValue left) (BoolValue right) = BoolValue $ left <= right +interpretOperation Ge (BoolValue left) (BoolValue right) = BoolValue $ left >= right +interpretOperation Eq (BoolValue left) (BoolValue right) = BoolValue $ left == right +interpretOperation And (BoolValue left) (BoolValue right) = BoolValue $ left && right +interpretOperation Or (BoolValue left) (BoolValue right) = BoolValue $ left || right +interpretOperation Neq (BoolValue left) (BoolValue right) = BoolValue $ left /= right -- Int interpretOperation Plus (IntValue left) (IntValue right) = IntValue $ left + right interpretOperation Minus (IntValue left) (IntValue right) = IntValue $ left - right interpretOperation Multiply (IntValue left) (IntValue right) = IntValue $ left * right interpretOperation Divide (IntValue left) (IntValue right) = IntValue $ left `div` right +interpretOperation Modulus (IntValue left) (IntValue right) = IntValue $ left `mod` right interpretOperation Lt (IntValue left) (IntValue right) = BoolValue $ left < right interpretOperation Gt (IntValue left) (IntValue right) = BoolValue $ left > right interpretOperation Le (IntValue left) (IntValue right) = BoolValue $ left <= right interpretOperation Ge (IntValue left) (IntValue right) = BoolValue $ left >= right interpretOperation Eq (IntValue left) (IntValue right) = BoolValue $ left == right +interpretOperation Neq (IntValue left) (IntValue right) = BoolValue $ left /= right -- Float interpretOperation Plus (FloatValue left) (FloatValue right) = FloatValue $ left + right interpretOperation Minus (FloatValue left) (FloatValue right) = FloatValue $ left - right diff --git a/src/Parser/Expression.hs b/src/Parser/Expression.hs index f9ae119..7057158 100644 --- a/src/Parser/Expression.hs +++ b/src/Parser/Expression.hs @@ -1,7 +1,6 @@ module Parser.Expression (module Parser.Expression) where import AST --- import Parser.Atomic import Parser.Literal (parseLiteral) import Parser.Name import Parser.Operator (parseOperator) @@ -11,8 +10,16 @@ import Text.Parsec.String parseExpression :: Parser Expression parseExpression = - try parseOperation - <|> try parseAtomicExpression + try parseExpression' + <|> try + ( char '(' + *> spaces' + *> parseExpression' + <* spaces' + <* char ')' + ) + where + parseExpression' = try parseOperation <|> try parseAtomicExpression parseOperation :: Parser Expression parseOperation = @@ -24,8 +31,17 @@ parseOperation = OperationExpression left op <$> try parseExpression parseAtomicExpression :: Parser Expression -parseAtomicExpression = do - AtomicExpression <$> try parseAtomic +parseAtomicExpression = + try parseAtomic' + <|> try + ( char '(' + *> spaces' + *> parseAtomic' + <* spaces' + <* char ')' + ) + where + parseAtomic' = AtomicExpression <$> try parseAtomic parseFunctionCallAtomic :: Parser Atomic parseFunctionCallAtomic = do @@ -37,6 +53,6 @@ parseFunctionCallAtomic = do parseAtomic :: Parser Atomic parseAtomic = - (LiteralAtomic <$> try parseLiteral) + LiteralAtomic <$> try parseLiteral <|> try parseFunctionCallAtomic - <|> (VariableAtomic <$> try parseName) + <|> VariableAtomic <$> try parseName diff --git a/src/Parser/Operator.hs b/src/Parser/Operator.hs index 7d8392e..eb2ef8f 100644 --- a/src/Parser/Operator.hs +++ b/src/Parser/Operator.hs @@ -6,17 +6,17 @@ import Text.Parsec.String parseOperator :: Parser Operator parseOperator = - (string "+" >> return Plus) - <|> (string "-" >> return Minus) - <|> (string "*" >> return Multiply) - <|> (string "/" >> return Divide) - <|> (string "%" >> return Modulus) - <|> (string "&&" >> return And) - <|> (string "||" >> return Or) - <|> (string "!" >> return Not) - <|> (string "==" >> return Eq) - <|> (string "!=" >> return Neq) - <|> (string "<" >> return Lt) - <|> (string ">" >> return Gt) - <|> (string "<=" >> return Le) - <|> (string ">=" >> return Ge) + try (string "+" >> return Plus) + <|> try (string "<=" >> return Le) + <|> try (string ">=" >> return Ge) + <|> try (string "-" >> return Minus) + <|> try (string "*" >> return Multiply) + <|> try (string "/" >> return Divide) + <|> try (string "%" >> return Modulus) + <|> try (string "&&" >> return And) + <|> try (string "||" >> return Or) + <|> try (string "==" >> return Eq) + <|> try (string "!=" >> return Neq) + <|> try (string "!" >> return Not) + <|> try (string "<" >> return Lt) + <|> try (string ">" >> return Gt) diff --git a/test/Unit/Parser/Atomic.hs b/test/Unit/Parser/Atomic.hs index 0e4eb0b..f5a20e3 100644 --- a/test/Unit/Parser/Atomic.hs +++ b/test/Unit/Parser/Atomic.hs @@ -13,7 +13,7 @@ allTests = ] emptyTestAtomic :: Atomic -emptyTestAtomic = (LiteralAtomic (UnitLiteral)) +emptyTestAtomic = LiteralAtomic UnitLiteral testSimple :: Test testSimple = TestCase $ do diff --git a/test/Unit/Parser/Expression.hs b/test/Unit/Parser/Expression.hs index c3d784c..07b6071 100644 --- a/test/Unit/Parser/Expression.hs +++ b/test/Unit/Parser/Expression.hs @@ -28,3 +28,35 @@ testSimple = TestCase $ do "Function Call" (AtomicExpression (FunctionCallAtomic "print" [])) (fromRight emptyTestExpression (parse parseExpression "" "print()")) + assertEqual + "(print())" + (AtomicExpression (FunctionCallAtomic "print" [])) + (fromRight emptyTestExpression (parse parseExpression "" "(print())")) + assertEqual + "(1) + (3)" + (OperationExpression (AtomicExpression (LiteralAtomic (IntLiteral 1))) Plus (AtomicExpression (LiteralAtomic (IntLiteral 3)))) + (fromRight emptyTestExpression (parse parseExpression "" "(1) + (3)")) + assertEqual + "1 + (3 + 4)" + ( OperationExpression + (AtomicExpression (LiteralAtomic (IntLiteral 1))) + Plus + ( OperationExpression + (AtomicExpression (LiteralAtomic (IntLiteral 3))) + Plus + (AtomicExpression (LiteralAtomic (IntLiteral 4))) + ) + ) + (fromRight emptyTestExpression (parse parseExpression "" "1 + (3 + 4)")) + assertEqual + "0 == (i % 3)" + ( OperationExpression + (AtomicExpression (LiteralAtomic (IntLiteral 0))) + Eq + ( OperationExpression + (AtomicExpression (VariableAtomic "i")) + Modulus + (AtomicExpression (LiteralAtomic (IntLiteral 3))) + ) + ) + (fromRight emptyTestExpression (parse parseExpression "" "0 == (i % 3)"))