diff --git a/spec/PythonSpec.hs b/spec/PythonSpec.hs index a944f2a8..d9ef7ace 100644 --- a/spec/PythonSpec.hs +++ b/spec/PythonSpec.hs @@ -87,9 +87,21 @@ spec = do (SimpleMethod "foo" [VariablePattern "self", VariablePattern "x"] (Return (Reference "x"))) ])) - it "doesn't parse methods without self" $ do + it "parses classes with static methods" $ do + py "class Something:\n @staticmethod\n def foo(x): return x" `shouldBe` ( + Class "Something" Nothing (Decorator [Static] + (SimpleMethod "foo" [VariablePattern "x"] (Return (Reference "x"))) + )) + + it "parses classes with class methods" $ do + py "class Something:\n @classmethod\n def foo(cls, x): return x" `shouldBe` ( + Class "Something" Nothing (Decorator [Classy] + (SimpleMethod "foo" [VariablePattern "cls", VariablePattern "x"] (Return (Reference "x"))) + )) + + it "does parse methods without self" $ do py "class Something:\n def bar(): return None\n" `shouldBe` ( - Class "Something" Nothing (SimpleFunction "bar" [] (Return MuNil))) + Class "Something" Nothing (SimpleMethod "bar" [] (Return MuNil))) it "doesn't parse methods pseudo-methods outside a class" $ do py "def bar(self): return None\n" `shouldBe` (SimpleFunction "bar" [VariablePattern "self"] (Return MuNil)) diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs index 4eac7ae3..7d2339f6 100644 --- a/src/Language/Mulang/Ast.hs +++ b/src/Language/Mulang/Ast.hs @@ -89,6 +89,7 @@ data Type data Modifier = Abstract | Static + | Classy | Private | Protected | Annotation Expression diff --git a/src/Language/Mulang/Parsers/Python.hs b/src/Language/Mulang/Parsers/Python.hs index 49b7458e..b5680d90 100644 --- a/src/Language/Mulang/Parsers/Python.hs +++ b/src/Language/Mulang/Parsers/Python.hs @@ -43,10 +43,15 @@ muModule :: ModuleSpan -> M.Expression muModule (Module statements) = compactMap muStatement statements muClassStatement :: StatementSpan -> M.Expression -muClassStatement (Fun name args@((Param (Ident "self" _) _ _ _):_) _ body _) = - M.SimpleMethod (muIdent name) (map muParameter args) (muSuite body) +muClassStatement (Fun name args _ body _) = M.SimpleMethod (muIdent name) (map muParameter args) (muSuite body) +muClassStatement (Decorated ds statement _) = M.Decorator (map muDecorator ds) (muClassStatement statement) muClassStatement other = muStatement other +muDecorator (Decorator [Ident "staticmethod" _] [] _) = M.Static +muDecorator (Decorator [Ident "classmethod" _] [] _) = M.Classy +muDecorator (Decorator [Ident name _] [] _) = M.Annotation (M.Reference name) +muDecorator other = M.debugModifier other + muStatement :: StatementSpan -> M.Expression muStatement (While cond body _ _) = M.While (muExpr cond) (muSuite body) muStatement (For targets generator body _ _) = M.For [M.Generator (M.TuplePattern (map (M.VariablePattern . muVariable) targets)) (muExpr generator)] (muSuite body) @@ -98,10 +103,10 @@ muClass parent name body = M.Class name parent body normalizeTests (M.Sequence exprs) = M.Sequence $ map normalizeTest exprs normalizeTests expr = normalizeTest expr -normalizeTest func@(M.SimpleProcedure name _ body) = if isPrefixOf "test_" name - then M.Test (M.MuString name) body - else func -normalizeTest e = e +normalizeTest func@(M.SimpleMethod name _ body) = if isPrefixOf "test_" name + then M.Test (M.MuString name) body + else func +normalizeTest e = e muIf (condition, body) otherwise = M.If (muExpr condition) (muSuite body) otherwise