From 133b4091b4a3932eef1df040c71b6f2eb1c04bd4 Mon Sep 17 00:00:00 2001 From: Franco Bulgarelli Date: Mon, 30 Apr 2018 11:22:50 -0300 Subject: [PATCH 1/8] Type alias now accepts the aliased type --- spec/HaskellSpec.hs | 4 ++++ src/Language/Mulang/Ast.hs | 2 +- src/Language/Mulang/Generator.hs | 2 +- src/Language/Mulang/Inspector/Generic.hs | 4 ++-- src/Language/Mulang/Parsers/Haskell.hs | 4 ++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/spec/HaskellSpec.hs b/spec/HaskellSpec.hs index 3c383fb35..7f0d77116 100644 --- a/spec/HaskellSpec.hs +++ b/spec/HaskellSpec.hs @@ -12,3 +12,7 @@ spec = do it "parses right infix partial application" $ do hs "f = (+1)" `shouldBe` Variable "f" (Application (Reference "+") [MuNumber 1.0]) + + it "parses type alias" $ do + hs "type String = [Char]" `shouldBe` TypeAlias "String" "[Char]" + diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs index 1d177b5fd..8d7da6efc 100644 --- a/src/Language/Mulang/Ast.hs +++ b/src/Language/Mulang/Ast.hs @@ -61,7 +61,7 @@ type SubroutineBody = [Equation] -- | However, although all those elements can be used as subexpressions and have an dohave an associated value, -- | Mulang does not state WHICH is that value. data Expression - = TypeAlias Identifier + = TypeAlias Identifier Identifier -- ^ Functional programming type alias. -- Only the type alias identifier is parsed | Record Identifier diff --git a/src/Language/Mulang/Generator.hs b/src/Language/Mulang/Generator.hs index ba9084bf9..195e496f1 100644 --- a/src/Language/Mulang/Generator.hs +++ b/src/Language/Mulang/Generator.hs @@ -36,7 +36,7 @@ declarations e@(Subroutine n b) = (n, e) : concatMap declarations (equationE declarations e@(Object n b) = (n, e) : declarations b declarations e@(Clause n _ _) = [(n, e)] declarations e@(Record n) = [(n, e)] -declarations e@(TypeAlias n) = [(n, e)] +declarations e@(TypeAlias n _) = [(n, e)] declarations e@(TypeSignature n _ _)= [(n, e)] declarations e@(Variable n _) = [(n, e)] declarations _ = [] diff --git a/src/Language/Mulang/Inspector/Generic.hs b/src/Language/Mulang/Inspector/Generic.hs index b90847636..da5500382 100644 --- a/src/Language/Mulang/Inspector/Generic.hs +++ b/src/Language/Mulang/Inspector/Generic.hs @@ -154,8 +154,8 @@ declaresComputationWithArity' arityPredicate = containsBoundDeclaration f declaresTypeAlias :: IdentifierInspection declaresTypeAlias = containsBoundDeclaration f - where f (TypeAlias _) = True - f _ = False + where f (TypeAlias _ _) = True + f _ = False declaresTypeSignature :: IdentifierInspection declaresTypeSignature = containsBoundDeclaration f diff --git a/src/Language/Mulang/Parsers/Haskell.hs b/src/Language/Mulang/Parsers/Haskell.hs index 22448999e..1d7e0a843 100644 --- a/src/Language/Mulang/Parsers/Haskell.hs +++ b/src/Language/Mulang/Parsers/Haskell.hs @@ -29,7 +29,7 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) where mergeDecls decls exp = compact (decls ++ [exp]) - muDecls (HsTypeDecl _ name _ _) = [TypeAlias (muName name)] + muDecls (HsTypeDecl _ name _ t) = [TypeAlias (muName name) (muType t)] muDecls (HsDataDecl _ _ name _ _ _ ) = [Record (muName name)] muDecls (HsTypeSig _ names (HsQualType _ t)) = map (muTypeSignature t) names muDecls (HsFunBind equations) | (HsMatch _ name _ _ _) <- head equations = @@ -128,7 +128,7 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) where topTypes = muTopTypes t listToMaybe [] = Nothing - listToMaybe xs = Just xs + listToMaybe xs = Just xs muTopTypes (HsTyFun i o) = muType i : muTopTypes o muTopTypes t = [muType t] From 4bbb5a6e2c251529b528838e80f7a881ad425c51 Mon Sep 17 00:00:00 2001 From: Franco Bulgarelli Date: Tue, 1 May 2018 11:57:45 -0300 Subject: [PATCH 2/8] Types refactor --- README.md | 271 +++++++++++++----- spec/HaskellSpec.hs | 14 + spec/JavaSpec.hs | 120 +++++--- src/Language/Mulang/Analyzer/Analysis/Json.hs | 2 + src/Language/Mulang/Ast.hs | 42 ++- src/Language/Mulang/Generator.hs | 5 +- src/Language/Mulang/Inspector/Generic.hs | 24 +- src/Language/Mulang/Parsers/Haskell.hs | 46 +-- src/Language/Mulang/Parsers/Java.hs | 8 +- src/Language/Mulang/Signature.hs | 8 +- 10 files changed, 384 insertions(+), 156 deletions(-) diff --git a/README.md b/README.md index 87a6f9608..752840b71 100644 --- a/README.md +++ b/README.md @@ -896,14 +896,15 @@ $ mulang ' # Mulang AST spec -In this section, we will get into the technical details of the Mulang AST. It is built around 4 core elements: +In this section, we will get into the technical details of the Mulang AST. It is built around 5 core elements: * [Expressions](#expressions) * [Patterns](#patterns) +* [Types](#types) * Equations * Generators -All the AST elements fall within any of this 4 categories. +All the AST elements fall within any of this 5 categories. ## Expressions @@ -944,67 +945,11 @@ struct Point { Currently, the `Record` expression does not hold information about the record contents. -### `TypeAlias` - -> A `TypeAlias` represents a synonym for a type, like the `type` declaration in Haskell and Scala or C's `typedef`. -> It is a typical statically typed functional programming feature. - -#### Syntax - -```haskell -(TypeAlias Identifier) -``` - -#### Haskell Example - -```haskell -type Point = (Point, Int) -``` - -```haskell -(TypeAlias "Point") -``` - -#### Caveats - -Currently, the `TypeAlias` expression does not hold information about the aliased type. - -### TypeSignature - -> A `TypeSignature` represents an explicit type annotation for a computation, -> variable or constant, as you can find in Java or Haskell. - -#### Syntax - -```haskell -(TypeSignature Identifier [Identifier] Identifier) -``` - -#### Haskell Example - -```haskell -name :: String -``` +### `TypeAlias`, `TypeSignature` and `TypeCast` -```haskell -(TypeSignature "name" [] "String") -``` - -#### Java Example - -In Java, as in most typed C-like languages, type signature and variable declartions are bound. This means that, for example, a local variable declaration will produce both a `TypeSignature` and a `Variable` expression. +Mulang AST support for type analysis is quite limited, and it is mostly focused on expressions and declarations analysis. However, for sake of completness and in order to provide some limited type-information in Mulang AST, `TypeAlias`, `TypeSignature` and `TypeCast` expressions are provided. -```java -String name; -``` - -```haskell -(TypeSignature "name" [] "String") -``` - -#### Caveats - -`TypeSignature`s of zero-args computation and variables are identical. +See [types section](#types) for more details. ### `EntryPoint` @@ -1613,10 +1558,10 @@ for (var i = 0; i < 10; i++) { ``` ```haskell -(ForLoop - (Variable "i" (MuNumber 0.0)) - (Application (Reference "<") [Reference "i",MuNumber 10.0]) - (Assignment "i" (Application (Reference "+") [Reference "i",MuNumber 1.0])) +(ForLoop + (Variable "i" (MuNumber 0.0)) + (Application (Reference "<") [Reference "i",MuNumber 10.0]) + (Assignment "i" (Application (Reference "+") [Reference "i",MuNumber 1.0])) (Send (Reference "console") (Reference "log") [Reference "i"])) ``` @@ -1918,6 +1863,202 @@ function foo(x, y) { } (OtherPattern) ``` +## Types + +When processing statically-typed languages, all type-information - regardless we are typing a function, a variable or a class - is represented with the `Type` ADT, can be one of: + + * `SimpleType`: composed by a type identifier and zero or type more constraints + * `ParameterizedType`: composed by input type parmaters, an output type, and type constratins + * `ConstrainedType`: composed by just type constraints. + * `OtherType`: an unrecognized type + +`Type`s can be introduced in the Mulang AST using the following elements: + +### `TypeAlias` + +> A `TypeAlias` represents a synonym for a type, like the `type` declaration in Haskell and Scala or C's `typedef`. +> It is a typical statically typed functional programming feature. + +#### Syntax + +```haskell +(TypeAlias Identifier Identifier) +``` + +#### Haskell Example + +```haskell +type Point = (Point, Int) +``` + +```haskell +(TypeAlias "Point" "(Point, Int") +``` + +### TypeSignature + +> A `TypeSignature` represents an explicit type annotation for a computation, +> variable or module, as you can find in Java or Haskell. + +#### Syntax + +```haskell +(TypeSignature Identifier Type) +``` + +#### Haskell Examples + +Simple types: + +```haskell +name :: String +``` + +```haskell +(TypeSignature "name" (SimpleType "String" [])) +``` + +Simple types and constraints: + +```haskell +f :: Num a => a +```` + +```haskell +(TypeSignature "f" (SimpleType "a" ["Num a"])) +``` + +Parameterized types: + + +```haskell +elem :: (Eq a, Foldable t) => a -> t a -> Bool +```` + +```haskell +(TypeSignature "elem" (ParameterizedType ["a", "t a"] "Bool" ["Eq a", "Foldable t"])) +``` + +#### Java Examples + +In Java, as in most typed C-like languages, type signature and variable declartions are bound. This means that, for example, a local variable declaration will produce both a `TypeSignature` and a `Variable` expression. + +Variable and attribute types: + +```java +String name; +``` + +```haskell +(TypeSignature "name" (SimpleType "String" [])) +``` + +Method types: + +```java +void String f() { return null; } +``` + +```haskell +(TypeSignature "f" (ParameterizedType [] "String" [])) +``` + +Method types with type parameters: + +```java +void A f() { return null; } +``` + +```haskell +(TypeSignature "f" (ParameterizedType [] "A" ["A"])) +``` + +Method types with type parameters and constraints: + +```java +void void f(A a) {} +``` + +```haskell +(TypeSignature "f" (ParameterizedType ["A"] "void" ["A super B"])) +``` + +Class or interfaces types: + +```java +class A { } +``` + +```haskell +(TypeSignature "A" (ConstrainedType ["B extends C", "D extends C"])) +``` + + +### `TypeCast` + +> A `TypeCast` represent explictly giving a type to an expression +> which may have static or dynamic impact on the program. It is aimed to represent +> type-casts in c-like languages and inline type signatures in funcional languages. + +#### Syntax + +```haskell +(TypeCast Expression Type) +``` + +#### Haskell Examples + +Simple types: + +```haskell +... = 4 :: Num a => a +``` + +```haskell +(TypeCast (MuNumber 4) (SimpleType "a" ["Num a"])) +``` + +#### Java Examples + +Variable and attribute types: + +```java +(Integer) 4; +``` + +```haskell +(TypeCast (MuNumber 4) (SimpleType "Integer" [])) +``` + +```java +(Option) something; +``` + +```haskell +(TypeCast (Reference "something") (SimpleType "Option" [])) +``` + +##### Caveats + +The type constraints refer to type-constrained parametrizations that the cast introduces, and +not any other kind of constraints the cast uses. That is whay the following Java code: + +```java +(Num) something; +``` + +produces: + +```haskell +(TypeCast (Reference "something") (SimpleType "Num" [])) +``` + +instead of: + +```haskell +(TypeCast (Reference "something") (SimpleType "Num" ["A"])) +``` + # Building mulang from source ## Setup diff --git a/spec/HaskellSpec.hs b/spec/HaskellSpec.hs index 7f0d77116..42da27832 100644 --- a/spec/HaskellSpec.hs +++ b/spec/HaskellSpec.hs @@ -13,6 +13,20 @@ spec = do it "parses right infix partial application" $ do hs "f = (+1)" `shouldBe` Variable "f" (Application (Reference "+") [MuNumber 1.0]) + it "parses type restrictions" $ do + hs "f :: Num a => [a] -> [a]" `shouldBe` SubroutineSignature "f" ["[a]"] "[a]" ["Num a"] + + it "parses multiple type restrictions" $ do + hs "f :: (Num a, Eq b) => [a] -> [b]" `shouldBe` SubroutineSignature "f" ["[a]"] "[b]" ["Num a", "Eq b"] + + it "parses signatures without type restrictions" $ do + hs "f :: [a] -> [a]" `shouldBe` SubroutineSignature "f" ["[a]"] "[a]" [] + it "parses type alias" $ do hs "type String = [Char]" `shouldBe` TypeAlias "String" "[Char]" + it "parses type alias with arguments" $ do + hs "type List a = [a]" `shouldBe` TypeAlias "List a" "[a]" + + it "parses inline type annotations" $ do + hs "x = 1 :: Int" `shouldBe` Variable "x" (TypeCast (MuNumber 1) (SimpleType "Int" [])) diff --git a/spec/JavaSpec.hs b/spec/JavaSpec.hs index 8dfd07963..db3bf31bc 100644 --- a/spec/JavaSpec.hs +++ b/spec/JavaSpec.hs @@ -25,14 +25,24 @@ spec = do it "parses Simple Interface" $ do run "public interface Foo {}" `shouldBe` Interface "Foo" [] MuNull + it "parses Simple Interface with type args" $ do + run "public interface Foo {}" `shouldBe` Sequence [ + ModuleSignature "Foo" ["A"], + Interface "Foo" [] MuNull] + + it "parses Simple Interface with type args and constraints" $ do + run "public interface Foo {}" `shouldBe` Sequence [ + ModuleSignature "Foo" ["A extends B"], + Interface "Foo" [] MuNull] + it "parses Simple Interface With Messages" $ do - run "public interface Foo { void foo(); }" `shouldBe` Interface "Foo" [] (SubroutineTypeSignature "foo" [] "void") + run "public interface Foo { void foo(); }" `shouldBe` Interface "Foo" [] (SubroutineSignature "foo" [] "void" []) it "parses Simple Interface With Non-Void Messages" $ do - run "public interface Foo { int foo(); }" `shouldBe` Interface "Foo" [] (SubroutineTypeSignature "foo" [] "int") + run "public interface Foo { int foo(); }" `shouldBe` Interface "Foo" [] (SubroutineSignature "foo" [] "int" []) it "parses Simple Interface With Messages With Params" $ do - run "public interface Foo { void foo(String x, int y); }" `shouldBe` Interface "Foo" [] (SubroutineTypeSignature "foo" ["String", "int"] "void") + run "public interface Foo { void foo(String x, int y); }" `shouldBe` Interface "Foo" [] (SubroutineSignature "foo" ["String", "int"] "void" []) it "parses Interface with superinterfaces" $ do run "public interface Foo extends Bar, Baz {}" `shouldBe` Interface "Foo" ["Bar", "Baz"] MuNull @@ -42,28 +52,44 @@ spec = do class Foo { public void hello() {} }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] MuNull)]) + it "parses Methods with type arguments" $ do + run [text| + class Foo { + public A hello(A a) {} + }|] `shouldBe` Class "Foo" Nothing (Sequence [ + SubroutineSignature "hello" ["A"] "A" [], + (SimpleMethod "hello" [VariablePattern "a"] MuNull)]) + + it "parses Methods with type arguments and type constraints" $ do + run [text| + class Foo { + public A hello(A a) {} + }|] `shouldBe` Class "Foo" Nothing (Sequence [ + SubroutineSignature "hello" ["A"] "A" [], + (SimpleMethod "hello" [VariablePattern "a"] MuNull)]) + it "parses Empty Returns" $ do run [text|class Foo { public void hello() { return; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (Return MuNull))]) it "parses Strings In Returns" $ do run [text|class Foo { public String hello() { return "hello"; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "String", + SubroutineSignature "hello" [] "String" [], (SimpleMethod "hello" [] (Return (MuString "hello")))]) it "parses Int In Returns" $ do run [text|class Foo { public int hello() { return 1; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "int", + SubroutineSignature "hello" [] "int" [], (SimpleMethod "hello" [] (Return (MuNumber 1)))]) @@ -71,7 +97,7 @@ spec = do run [text|class Foo { public double hello() { return 453.2; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "double", + SubroutineSignature "hello" [] "double" [], (SimpleMethod "hello" [] (Return (MuNumber 453.2)))]) @@ -79,26 +105,26 @@ spec = do run [text|class Foo { public boolean hello() { return true; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "boolean", + SubroutineSignature "hello" [] "boolean" [], (SimpleMethod "hello" [] (Return MuTrue))]) it "parses Negation In Returns" $ do run [text|class Foo { public boolean hello() { return !true; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "boolean", + SubroutineSignature "hello" [] "boolean" [], (SimpleMethod "hello" [] (Return (SimpleSend MuTrue "!" [])))]) it "parses Chars In Returns" $ do run [text|class Foo { public char hello() { return 'f'; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "char", + SubroutineSignature "hello" [] "char" [], (SimpleMethod "hello" [] (Return (MuString "f")))]) it "parses Parameters" $ do run "public class Foo extends Bar { int succ(int y) {} }" `shouldBe` Class "Foo" (Just "Bar") (Sequence [ - TypeSignature "succ" (Just ["int"]) "int", + SubroutineSignature "succ" ["int"] "int" [], (SimpleMethod "succ" [VariablePattern "y"] MuNull)]) it "parses Enums" $ do @@ -115,9 +141,9 @@ spec = do class Foo { public void hello() { int x = 1; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (Sequence [ - TypeSignature "x" Nothing "int", + VariableSignature "x" "int" [], Variable "x" (MuNumber 1)]))]) it "parses Variables And Ints" $ do @@ -125,9 +151,9 @@ spec = do class Foo { public void hello() { Foo x = this; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (Sequence [ - TypeSignature "x" Nothing "Foo", + VariableSignature "x" "Foo" [], Variable "x" Self]))]) it "parses Variables And ternaries" $ do @@ -135,9 +161,9 @@ spec = do class Foo { public void hello() { Foo x = true ? this : this; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (Sequence [ - TypeSignature "x" Nothing "Foo", + VariableSignature "x" "Foo" [], Variable "x" (If MuTrue Self Self)]))]) it "parses Variables without initialization" $ do @@ -145,9 +171,9 @@ spec = do class Foo { public void hello() { int x; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (Sequence [ - TypeSignature "x" Nothing "int", + VariableSignature "x" "int" [], Variable "x" MuNull]))]) it "parses self-send" $ do @@ -155,7 +181,7 @@ spec = do class Foo { public void hello() { f(); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (SimpleSend Self "f" []))]) it "parses self-send" $ do @@ -163,7 +189,7 @@ spec = do class Foo { public void hello() { f(2); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (SimpleSend Self "f" [MuNumber 2]))]) it "parses explict self-send" $ do @@ -171,7 +197,7 @@ spec = do class Foo { public void hello() { this.f(); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (SimpleSend Self "f" []))]) it "parses nested send" $ do @@ -181,7 +207,7 @@ spec = do System.err.println("hello"); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "foo" [] "void", + SubroutineSignature "foo" [] "void" [], (SimpleMethod "foo" [] (SimpleSend (Reference "System.err") "println" [MuString "hello"]))]) it "parses argument-send" $ do @@ -189,7 +215,7 @@ spec = do class Foo { public void hello(String g) { g.toString(); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" ["String"] "void", + SubroutineSignature "hello" ["String"] "void" [], (SimpleMethod "hello" [VariablePattern "g"] (SimpleSend (Reference "g") "toString" []))]) @@ -198,7 +224,7 @@ spec = do class Foo { public void hello(String g) { g.size().toString(); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" ["String"] "void", + SubroutineSignature "hello" ["String"] "void" [], (SimpleMethod "hello" [VariablePattern "g"] (SimpleSend (SimpleSend (Reference "g") "size" []) "toString" []))]) @@ -207,7 +233,7 @@ spec = do class Foo { public void hello() { if (true) { } } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (If MuTrue MuNull MuNull))]) it "parses Ifs with return in braces" $ do @@ -215,7 +241,7 @@ spec = do class Foo { public void hello() { if (true) { return true; } else { return false; } } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] (If MuTrue (Return MuTrue) (Return MuFalse)))]) it "parses Ifs with equal comparisons on conditions" $ do @@ -223,7 +249,7 @@ spec = do class Foo { public void hello(String x) { if (x == "foo") { } } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" ["String"] "void", + SubroutineSignature "hello" ["String"] "void" [], SimpleMethod "hello" [VariablePattern "x"] ( If (Send (Reference "x") Equal [MuString "foo"]) MuNull @@ -234,7 +260,7 @@ spec = do class Foo { public void hello(String x) { if (x != "foo") { } } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" ["String"] "void", + SubroutineSignature "hello" ["String"] "void" [], (SimpleMethod "hello" [VariablePattern "x"] ( If (Send (Reference "x") NotEqual [MuString "foo"]) MuNull @@ -244,10 +270,10 @@ spec = do run [text|class Foo { public void hello() { double m = 1.0; m = 3.4; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "void", + SubroutineSignature "hello" [] "void" [], (SimpleMethod "hello" [] ( Sequence [ - TypeSignature "m" Nothing "double", + VariableSignature "m" "double" [], Variable "m" (MuNumber 1.0), Assignment "m" (MuNumber 3.4)]))]) @@ -255,7 +281,7 @@ spec = do run [text|class Foo { public Object hello() { return (int x) -> x + 1; } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "Object", + SubroutineSignature "hello" [] "Object" [], (SimpleMethod "hello" [] ( Return (Lambda [VariablePattern "x"] (SimpleSend (Reference "x") "+" [MuNumber 1]))))]) @@ -263,55 +289,55 @@ spec = do run [text|class Foo { public Foo hello() { return new Bar(3); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - SubroutineTypeSignature "hello" [] "Foo", + SubroutineSignature "hello" [] "Foo" [], SimpleMethod "hello" [] ( Return (New "Bar" [MuNumber 3]))]) it "parses switch with default" $ do run [text|class Foo { - public Foo hello() { + public Foo hello() { switch(a){ case 1: return 1; default: return 3; } } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - TypeSignature "hello" (Just []) "Foo", + SubroutineSignature "hello" [] "Foo" [], SimpleMethod "hello" [] ( Switch (Reference "a") [(MuNumber 1, Return (MuNumber 1))] (Return (MuNumber 3.0)))]) it "parses switch with no default" $ do run [text|class Foo { - public Foo hello() { + public Foo hello() { switch(a){ case 1: return 1; case 2: return 2; } } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - TypeSignature "hello" (Just []) "Foo", + SubroutineSignature "hello" [] "Foo" [], SimpleMethod "hello" [] ( Switch (Reference "a") [(MuNumber 1,Return (MuNumber 1)), (MuNumber 2, Return (MuNumber 2))] MuNull)]) it "parses for" $ do run [text|class Foo { - public Foo hello() { + public Foo hello() { for(int i : ints) a(); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - TypeSignature "hello" (Just []) "Foo", - SimpleMethod "hello" [] + SubroutineSignature "hello" [] "Foo" [], + SimpleMethod "hello" [] (For [Generator (VariablePattern "i") (Reference "ints")] (Send Self (Reference "a") []))]) it "parses c-style for" $ do run [text|class Foo { - public Foo hello() { + public Foo hello() { for(int i = 0; true; a()) b(); } }|] `shouldBe` Class "Foo" Nothing (Sequence [ - TypeSignature "hello" (Just []) "Foo", - SimpleMethod "hello" [] - (ForLoop - (Sequence [TypeSignature "i" Nothing "int", Variable "i" (MuNumber 0)]) - MuTrue + SubroutineSignature "hello" [] "Foo" [], + SimpleMethod "hello" [] + (ForLoop + (Sequence [VariableSignature "i" "int" [], Variable "i" (MuNumber 0)]) + MuTrue (Send Self (Reference "a") []) (Send Self (Reference "b") []))]) diff --git a/src/Language/Mulang/Analyzer/Analysis/Json.hs b/src/Language/Mulang/Analyzer/Analysis/Json.hs index ffbb83d85..89397cd30 100644 --- a/src/Language/Mulang/Analyzer/Analysis/Json.hs +++ b/src/Language/Mulang/Analyzer/Analysis/Json.hs @@ -24,6 +24,7 @@ instance FromJSON EquationBody instance FromJSON Expression instance FromJSON Pattern instance FromJSON Statement +instance FromJSON Type instance ToJSON AnalysisResult instance ToJSON ExpectationResult @@ -35,4 +36,5 @@ instance ToJSON EquationBody instance ToJSON Expression instance ToJSON Pattern instance ToJSON Statement +instance ToJSON Type diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs index 8d7da6efc..085f817e4 100644 --- a/src/Language/Mulang/Ast.hs +++ b/src/Language/Mulang/Ast.hs @@ -17,6 +17,7 @@ module Language.Mulang.Ast ( Code, Equation(..), EquationBody(..), + Type(..), Expression(..), Statement(..), Pattern(..), @@ -30,9 +31,11 @@ module Language.Mulang.Ast ( pattern SimpleProcedure, pattern SimpleMethod, pattern SimpleSend, + pattern SubroutineSignature, + pattern VariableSignature, + pattern ModuleSignature, pattern MuTrue, pattern MuFalse, - pattern SubroutineTypeSignature, pattern Subroutine, pattern Clause, pattern Call, @@ -48,12 +51,29 @@ type Code = String data Equation = Equation [Pattern] EquationBody deriving (Eq, Show, Read, Generic) data EquationBody - = UnguardedBody Expression - | GuardedBody [(Expression, Expression)] - deriving (Eq, Show, Read, Generic) + = UnguardedBody Expression + | GuardedBody [(Expression, Expression)] + deriving (Eq, Show, Read, Generic) type SubroutineBody = [Equation] +-- A Generic Type, that can be used for typing expressions, +-- classes, functions, variables and so on, using a @TypeSignature@ +-- or a @TypeCast@ +data Type + = SimpleType Identifier [Identifier] + -- ^ simple types, with a type identifier and type constraints + -- Useful for modelling variable types + | ParameterizedType [Identifier] Identifier [Identifier] + -- ^ parameterized types, with type inputs, type identifier and type constraints + -- Useful for modelling functions, methods and procedures types + | ConstrainedType [Identifier] + -- ^ constrained type, with just type constraints. + -- Usefull for modelling classes and interfaces types + | OtherType (Maybe String) (Maybe Type) + -- ^ unrecognized type, with optional code and nested type + deriving (Eq, Show, Read, Generic) + -- | Expression is the root element of a Mulang program. -- | With the exception of Patterns, nearly everything is an Expression: variable declarations, literals, -- | control structures, even object oriented classes declarations. @@ -67,9 +87,13 @@ data Expression | Record Identifier -- ^ Imperative / Functional programming struct declaration. -- Only the record name is parsed - | TypeSignature Identifier (Maybe [Identifier]) Identifier + | TypeSignature Identifier Type -- ^ Generic type signature for a computation, - -- composed by a name, parameter types and return type + -- composed by a name and its type + | TypeCast Expression Type + -- ^ Generic type annotation for an expression. For example, + -- a Java cast: (String) anObject => TypeAnnotation (Variable "anObject") "String" + -- a Haskell inline type declaration: ... = x :: Int => TypeAnnotation (Variable "x") "Int" | EntryPoint Identifier Expression -- ^ Entry point with its body | Function Identifier SubroutineBody @@ -198,6 +222,10 @@ data Statement debug :: Show a => a -> Expression debug a = Unknown (Just (show a)) Nothing +pattern VariableSignature name t cs = TypeSignature name (SimpleType t cs) +pattern SubroutineSignature name args t cs = TypeSignature name (ParameterizedType args t cs) +pattern ModuleSignature name cs = TypeSignature name (ConstrainedType cs) + pattern Other = Unknown Nothing Nothing pattern OtherBody body <- Unknown _ (Just body) @@ -212,8 +240,6 @@ pattern SimpleMethod name params body = Method name [SimpleEquation params pattern MuTrue = MuBool True pattern MuFalse = MuBool False -pattern SubroutineTypeSignature name params return = TypeSignature name (Just params) return - pattern Subroutine name body <- (extractSubroutine -> Just (name, body)) pattern Clause name patterns expressions <- (extractClause -> Just (name, patterns, expressions)) diff --git a/src/Language/Mulang/Generator.hs b/src/Language/Mulang/Generator.hs index 195e496f1..a56b6dfa4 100644 --- a/src/Language/Mulang/Generator.hs +++ b/src/Language/Mulang/Generator.hs @@ -37,7 +37,7 @@ declarations e@(Object n b) = (n, e) : declarations b declarations e@(Clause n _ _) = [(n, e)] declarations e@(Record n) = [(n, e)] declarations e@(TypeAlias n _) = [(n, e)] -declarations e@(TypeSignature n _ _)= [(n, e)] +declarations e@(TypeSignature n _) = [(n, e)] declarations e@(Variable n _) = [(n, e)] declarations _ = [] @@ -59,8 +59,8 @@ expressions expr = expr : concatMap expressions (subExpressions expr) subExpressions (Clause _ _ es) = es subExpressions (EntryPoint _ e) = [e] subExpressions (For stmts a) = statementExpressions stmts ++ [a] - subExpressions (ForLoop i c p s) = [i, c, p, s] subExpressions (Forall e1 e2) = [e1, e2] + subExpressions (ForLoop i c p s) = [i, c, p, s] subExpressions (If a b c) = [a, b, c] subExpressions (Interface _ _ v) = [v] subExpressions (Lambda _ a) = [a] @@ -78,6 +78,7 @@ expressions expr = expr : concatMap expressions (subExpressions expr) subExpressions (Subroutine _ es) = equationExpressions es subExpressions (Switch e1 list _) = e1 : concatMap (\(x,y) -> [x,y]) list subExpressions (Try t cs f) = t : map snd cs ++ [f] + subExpressions (TypeCast e _) = [e] subExpressions (Variable _ v) = [v] subExpressions (While e1 e2) = [e1, e2] subExpressions (Yield v) = [v] diff --git a/src/Language/Mulang/Inspector/Generic.hs b/src/Language/Mulang/Inspector/Generic.hs index da5500382..7133da3f2 100644 --- a/src/Language/Mulang/Inspector/Generic.hs +++ b/src/Language/Mulang/Inspector/Generic.hs @@ -44,23 +44,23 @@ type IdentifierInspection = IdentifierPredicate -> Inspection typesReturnAs :: IdentifierInspection typesReturnAs predicate = containsDeclaration f - where f (SubroutineTypeSignature _ _ name) = predicate name - f _ = False + where f (SubroutineSignature _ _ name _) = predicate name + f _ = False typesParameterAs :: IdentifierInspection typesParameterAs predicate = containsDeclaration f - where f (SubroutineTypeSignature _ names _) = any predicate names - f _ = False + where f (SubroutineSignature _ names _ _) = any predicate names + f _ = False typesAs :: IdentifierInspection typesAs predicate = containsDeclaration f - where f (TypeSignature _ Nothing name) = predicate name - f _ = False + where f (VariableSignature _ name _) = predicate name + f _ = False usesType :: IdentifierInspection usesType predicate = containsDeclaration f - where f (TypeSignature _ _ name) | predicate name = True - f (SubroutineTypeSignature _ names _) = any predicate names + where f (VariableSignature _ name _) = predicate name + f (SubroutineSignature _ args ret _) = any predicate (ret:args) f _ = False -- | Inspection that tells whether an expression is equal to a given piece of code after being parsed @@ -107,8 +107,8 @@ usesFor = containsExpression f -- | Inspection that tells whether a top level declaration exists declares :: IdentifierInspection declares = containsBoundDeclaration f - where f (TypeSignature _ _ _) = False - f _ = True + where f (TypeSignature _ _) = False + f _ = True -- | Inspection that tells whether an expression is direct recursive declaresRecursively :: IdentifierInspection @@ -159,8 +159,8 @@ declaresTypeAlias = containsBoundDeclaration f declaresTypeSignature :: IdentifierInspection declaresTypeSignature = containsBoundDeclaration f - where f (TypeSignature _ _ _) = True - f _ = False + where f (TypeSignature _ _) = True + f _ = False raises :: IdentifierInspection raises predicate = containsExpression f diff --git a/src/Language/Mulang/Parsers/Haskell.hs b/src/Language/Mulang/Parsers/Haskell.hs index 1d7e0a843..1ae08e65f 100644 --- a/src/Language/Mulang/Parsers/Haskell.hs +++ b/src/Language/Mulang/Parsers/Haskell.hs @@ -29,9 +29,10 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) where mergeDecls decls exp = compact (decls ++ [exp]) - muDecls (HsTypeDecl _ name _ t) = [TypeAlias (muName name) (muType t)] + muDecls (HsTypeDecl _ name _ t) = [TypeAlias (muName name) (muTypeId t)] muDecls (HsDataDecl _ _ name _ _ _ ) = [Record (muName name)] - muDecls (HsTypeSig _ names (HsQualType _ t)) = map (muTypeSignature t) names + muDecls (HsTypeSig _ names (HsQualType constraints t)) + = map (muTypeSignature constraints t) names muDecls (HsFunBind equations) | (HsMatch _ name _ _ _) <- head equations = [Function (muName name) (map muEquation equations)] muDecls (HsPatBind _ (HsPVar name) (HsUnGuardedRhs exp) _) = [Variable (muName name) (muExp exp)] @@ -124,19 +125,30 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) muStmt (HsGenerator _ pat exp) = Generator (muPat pat) (muExp exp) muStmt (HsQualifier exp) = Guard (muExp exp) - muTypeSignature t name = TypeSignature (muName name) (listToMaybe $ init topTypes) (last topTypes) - where topTypes = muTopTypes t - - listToMaybe [] = Nothing - listToMaybe xs = Just xs - - muTopTypes (HsTyFun i o) = muType i : muTopTypes o - muTopTypes t = [muType t] - - muType (HsTyFun i o) = muType i ++ " -> " ++ muType o - muType (HsTyCon name) = muQName name - muType (HsTyVar name) = muName name - muType (HsTyTuple ts) = "(" ++ (intercalate ", " . map muType $ ts) ++ ")" - muType (HsTyApp (HsTyCon (Special HsListCon)) t2) = "[" ++ muType t2 ++ "]" - muType (HsTyApp t1 t2) = muType t1 ++ " " ++ muType t2 + muTypeSignature :: [HsAsst] -> HsType -> HsName -> Expression + muTypeSignature cs t name = TypeSignature (muName name) (muType t cs) + + muType :: HsType -> [HsAsst] -> Type + muType t cs | null initTypes = SimpleType lastType constraints + | otherwise = ParameterizedType initTypes lastType constraints + where + initTypes = init topTypes + lastType = last topTypes + topTypes = muTopTypes t + constraints = map muConstraint cs + + muConstraint :: HsAsst -> Identifier + muConstraint (constraint, targets) = + intercalate " " (muQName constraint : map muTypeId targets) + + muTopTypes (HsTyFun i o) = muTypeId i : muTopTypes o + muTopTypes t = [muTypeId t] + + muTypeId :: HsType -> Identifier + muTypeId (HsTyFun i o) = muTypeId i ++ " -> " ++ muTypeId o + muTypeId (HsTyCon name) = muQName name + muTypeId (HsTyVar name) = muName name + muTypeId (HsTyTuple ts) = "(" ++ (intercalate ", " . map muTypeId $ ts) ++ ")" + muTypeId (HsTyApp (HsTyCon (Special HsListCon)) t2) = "[" ++ muTypeId t2 ++ "]" + muTypeId (HsTyApp t1 t2) = muTypeId t1 ++ " " ++ muTypeId t2 diff --git a/src/Language/Mulang/Parsers/Java.hs b/src/Language/Mulang/Parsers/Java.hs index e6c5ad9be..c07124767 100644 --- a/src/Language/Mulang/Parsers/Java.hs +++ b/src/Language/Mulang/Parsers/Java.hs @@ -58,7 +58,7 @@ muMemberDecl e@(ConstructorDecl _ _ _ _params _ _constructorBody) = return . muMemberDecl (MemberClassDecl decl) = return $ muClassTypeDecl decl muMemberDecl (MemberInterfaceDecl decl) = return $ muInterfaceTypeDecl decl -muMethodSignature name params returnType = TypeSignature (i name) (Just $ map muFormalParamType params) (muReturnType returnType) +muMethodSignature name params returnType = SubroutineSignature (i name) (map muFormalParamType params) (muReturnType returnType) [] muEnumConstant (EnumConstant name _ _) = i name muFormalParam (FormalParam _ _ _ id) = VariablePattern (v id) @@ -143,7 +143,9 @@ muOp Equal = M.Equal muOp NotEq = NotEqual muOp e = debug e -muVarDecl typ (VarDecl id init) = [TypeSignature (v id) Nothing (muType typ), Variable (v id) (fmapOrNull muVarInit init)] +muVarDecl typ (VarDecl id init) = [ + TypeSignature (v id) (SimpleType (muType typ) []), + Variable (v id) (fmapOrNull muVarInit init)] muMethodBody (MethodBody (Just block)) = muBlock block @@ -171,7 +173,7 @@ muCase (SwitchBlock (SwitchCase exp) block) = (muExp exp, compactConcatMap muBlo muDefault (SwitchBlock Default block) = compactConcatMap muBlockStmt block muForInit:: ForInit -> Expression -muForInit (ForLocalVars _ typ varDecls) = compactConcatMap (muVarDecl typ) varDecls +muForInit (ForLocalVars _ typ varDecls) = compactConcatMap (muVarDecl typ) varDecls muForInit (ForInitExps exps) = compactMap muExp exps isDefault (SwitchBlock Default _) = True diff --git a/src/Language/Mulang/Signature.hs b/src/Language/Mulang/Signature.hs index 6917d375f..2000d3f67 100644 --- a/src/Language/Mulang/Signature.hs +++ b/src/Language/Mulang/Signature.hs @@ -54,11 +54,15 @@ signaturesOf = nub . mapMaybe (signatureOf.snd) . declarations signatureOf :: Expression -> Maybe Signature signatureOf (Subroutine name es) = Just $ NamedSignature name (parameterNamesOf es) signatureOf (Clause name args _) = Just $ AritySignature name (length args) -signatureOf (TypeSignature name (Just args) ret) = Just $ TypedSignature name args ret -signatureOf (TypeSignature name Nothing ret) = Just $ TypedSignature name [] ret +signatureOf (TypeSignature name t) = typedSignatureOf name t signatureOf (Variable name _) = Just $ AritySignature name 0 signatureOf _ = Nothing +typedSignatureOf :: Identifier -> Type -> Maybe Signature +typedSignatureOf name (ParameterizedType args ret []) = Just $ TypedSignature name args ret +typedSignatureOf name (SimpleType ret []) = Just $ TypedSignature name [] ret +typedSignatureOf _ _ = Nothing + parameterNamesOf :: [Equation] -> [Maybe Identifier] parameterNamesOf = map msum . transpose . map (map parameterNameOf . equationPatterns) From 1c341760aedf29258340fbaaa0884504283afd3f Mon Sep 17 00:00:00 2001 From: Franco Bulgarelli Date: Tue, 1 May 2018 11:58:47 -0300 Subject: [PATCH 3/8] Updating TOC --- README.md | 147 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 752840b71..581355fd3 100644 --- a/README.md +++ b/README.md @@ -39,176 +39,181 @@ Mulang is three different - but thighly related - things: - [Syntax](#syntax) - [C Example](#c-example) - [Caveats](#caveats) - + [`TypeAlias`](#typealias) + + [`TypeAlias`, `TypeSignature` and `TypeCast`](#typealias-typesignature-and-typecast) + + [`EntryPoint`](#entrypoint) - [Syntax](#syntax-1) - - [Haskell Example](#haskell-example) - - [Caveats](#caveats-1) - + [TypeSignature](#typesignature) - - [Syntax](#syntax-2) - - [Haskell Example](#haskell-example-1) - [Java Example](#java-example) - - [Caveats](#caveats-2) - + [`EntryPoint`](#entrypoint) - - [Syntax](#syntax-3) - - [Java Example](#java-example-1) + [`Function`](#function) - - [Syntax](#syntax-4) + - [Syntax](#syntax-2) - [Example](#example) + [`Procedure`](#procedure) - - [Syntax](#syntax-5) + - [Syntax](#syntax-3) + [`Method`](#method) - - [Syntax](#syntax-6) + - [Syntax](#syntax-4) - [Ruby Example](#ruby-example) - - [Java Example](#java-example-2) + - [Java Example](#java-example-1) + [`EqualMethod` and `HashMethod`](#equalmethod-and-hashmethod) - - [Syntax](#syntax-7) + - [Syntax](#syntax-5) - [Ruby Example](#ruby-example-1) + [`Variable`](#variable) - - [Syntax](#syntax-8) + - [Syntax](#syntax-6) - [Example](#example-1) + [`Assignment`](#assignment) - - [Syntax](#syntax-9) + - [Syntax](#syntax-7) - [Example](#example-2) + [`Attribute`](#attribute) - - [Syntax](#syntax-10) + - [Syntax](#syntax-8) - [Example](#example-3) + [`Object`](#object) - - [Syntax](#syntax-11) + - [Syntax](#syntax-9) - [Example](#example-4) + [`Class`](#class) - - [Syntax](#syntax-12) + - [Syntax](#syntax-10) - [Ruby Example](#ruby-example-2) - [Java Examples](#java-examples) + [`Enumeration`](#enumeration) - - [Syntax](#syntax-13) - - [Java Example](#java-example-3) + - [Syntax](#syntax-11) + - [Java Example](#java-example-2) + [`Interface`](#interface) - - [Syntax](#syntax-14) - - [Java Example](#java-example-4) + - [Syntax](#syntax-12) + - [Java Example](#java-example-3) + [`Rule`](#rule) - - [Syntax](#syntax-15) + - [Syntax](#syntax-13) - [Example](#example-5) + [`Fact`](#fact) - - [Syntax](#syntax-16) + - [Syntax](#syntax-14) - [Example](#example-6) + [`Exist`](#exist) - - [Syntax](#syntax-17) + - [Syntax](#syntax-15) - [Example](#example-7) + [`Not`](#not) - - [Syntax](#syntax-18) + - [Syntax](#syntax-16) - [Example](#example-8) + [`Findall`](#findall) - - [Syntax](#syntax-19) + - [Syntax](#syntax-17) - [Example](#example-9) + [`Forall`](#forall) - - [Syntax](#syntax-20) + - [Syntax](#syntax-18) - [Example](#example-10) + [`Reference`](#reference) - - [Syntax](#syntax-21) + - [Syntax](#syntax-19) - [Example](#example-11) + [`Application`](#application) - - [Syntax](#syntax-22) + - [Syntax](#syntax-20) - [Example](#example-12) + [`Send`](#send) - - [Syntax](#syntax-23) + - [Syntax](#syntax-21) - [Ruby Example](#ruby-example-3) + [`New`](#new) - - [Syntax](#syntax-24) + - [Syntax](#syntax-22) - [Example](#example-13) + [`Implement`](#implement) - - [Syntax](#syntax-25) + - [Syntax](#syntax-23) - [Example](#example-14) + [`Include`](#include) - - [Syntax](#syntax-26) + - [Syntax](#syntax-24) - [Example](#example-15) + [`If`](#if) - - [Syntax](#syntax-27) + - [Syntax](#syntax-25) + [`Lambda`](#lambda) - - [Syntax](#syntax-28) + - [Syntax](#syntax-26) + [`Return`](#return) - - [Syntax](#syntax-29) + - [Syntax](#syntax-27) + [`While`](#while) - - [Syntax](#syntax-30) + - [Syntax](#syntax-28) - [Example](#example-16) + [`Repeat`](#repeat) - - [Syntax](#syntax-31) + - [Syntax](#syntax-29) - [Example](#example-17) + [`Match`](#match) - - [Syntax](#syntax-32) + - [Syntax](#syntax-30) + [`Switch`](#switch) - - [Syntax](#syntax-33) + - [Syntax](#syntax-31) + [`Try`](#try) - - [Syntax](#syntax-34) + - [Syntax](#syntax-32) - [Example](#example-18) + [`Raise`](#raise) - - [Syntax](#syntax-35) + - [Syntax](#syntax-33) - [Example](#example-19) + [`Print`](#print) - - [Syntax](#syntax-36) + - [Syntax](#syntax-34) - [Ruby Example](#ruby-example-4) + [`For`](#for) - - [Syntax](#syntax-37) - - [Haskell Example](#haskell-example-2) - - [Java Example](#java-example-5) + - [Syntax](#syntax-35) + - [Haskell Example](#haskell-example) + - [Java Example](#java-example-4) + [`ForLoop`](#forloop) - - [Syntax](#syntax-38) + - [Syntax](#syntax-36) - [Example](#example-20) + [`Sequence`](#sequence) - - [Syntax](#syntax-39) + - [Syntax](#syntax-37) - [Example](#example-21) + [`Other`](#other) - - [Syntax](#syntax-40) + - [Syntax](#syntax-38) + [`Equal` and `NotEqual`](#equal-and-notequal) - - [Syntax](#syntax-41) + - [Syntax](#syntax-39) + [`Self`](#self) - - [Syntax](#syntax-42) + - [Syntax](#syntax-40) + [`MuNull`](#munull) - - [Syntax](#syntax-43) + - [Syntax](#syntax-41) + [`MuNil`](#munil) - - [Syntax](#syntax-44) + - [Syntax](#syntax-42) - [Example](#example-22) + [`MuObject`](#muobject) - - [Syntax](#syntax-45) + - [Syntax](#syntax-43) - [JavaScript Example](#javascript-example) + [`MuNumber`, `MuBool`, `MuString` and `MuSymbol`](#munumber-mubool-mustring-and-musymbol) - - [Syntax](#syntax-46) + - [Syntax](#syntax-44) - [Ruby Example](#ruby-example-5) + [`MuTuple` and `MuList`](#mutuple-and-mulist) - - [Syntax](#syntax-47) + - [Syntax](#syntax-45) * [Patterns](#patterns) + [`VariablePattern`](#variablepattern) - - [Syntax](#syntax-48) + - [Syntax](#syntax-46) - [JavaScript Example](#javascript-example-1) + [`LiteralPattern`](#literalpattern) - - [Syntax](#syntax-49) + - [Syntax](#syntax-47) - [Example](#example-23) + [`InfixApplicationPattern`](#infixapplicationpattern) - - [Syntax](#syntax-50) - * [Caveats](#caveats-3) + - [Syntax](#syntax-48) + * [Caveats](#caveats-1) + [`ApplicationPattern`](#applicationpattern) - - [Syntax](#syntax-51) + - [Syntax](#syntax-49) - [Example](#example-24) + [`TuplePattern`](#tuplepattern) - - [Syntax](#syntax-52) + - [Syntax](#syntax-50) - [Example](#example-25) + [`ListPattern`](#listpattern) - - [Syntax](#syntax-53) + - [Syntax](#syntax-51) - [Example](#example-26) + [`FunctorPattern`](#functorpattern) - - [Syntax](#syntax-54) + - [Syntax](#syntax-52) - [Example](#example-27) + [`AsPattern`](#aspattern) - - [Syntax](#syntax-55) + - [Syntax](#syntax-53) - [Example](#example-28) + [`TypePattern`](#typepattern) - - [Syntax](#syntax-56) + - [Syntax](#syntax-54) - [Example](#example-29) + [`WildcardPattern`](#wildcardpattern) - - [Syntax](#syntax-57) + - [Syntax](#syntax-55) + [`UnionPattern`](#unionpattern) - - [Syntax](#syntax-58) + - [Syntax](#syntax-56) + [`OtherPattern`](#otherpattern) + - [Syntax](#syntax-57) + * [Types](#types) + + [`TypeAlias`](#typealias) + - [Syntax](#syntax-58) + - [Haskell Example](#haskell-example-1) + + [TypeSignature](#typesignature) - [Syntax](#syntax-59) + - [Haskell Examples](#haskell-examples) + - [Java Examples](#java-examples-1) + + [`TypeCast`](#typecast) + - [Syntax](#syntax-60) + - [Haskell Examples](#haskell-examples-1) + - [Java Examples](#java-examples-2) + * [Caveats](#caveats-2) - [Building mulang from source](#building-mulang-from-source) * [Setup](#setup) * [Installing and creating an executable](#installing-and-creating-an-executable) From 0cd333d90e341de6fedb26cec8f89962df019a5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Berbel=20Alt?= Date: Wed, 2 May 2018 15:14:42 -0300 Subject: [PATCH 4/8] fix typos in README --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 581355fd3..cdeffb969 100644 --- a/README.md +++ b/README.md @@ -909,7 +909,7 @@ In this section, we will get into the technical details of the Mulang AST. It is * Equations * Generators -All the AST elements fall within any of this 5 categories. +All the AST elements fall within any of these 5 categories. ## Expressions @@ -952,7 +952,7 @@ Currently, the `Record` expression does not hold information about the record co ### `TypeAlias`, `TypeSignature` and `TypeCast` -Mulang AST support for type analysis is quite limited, and it is mostly focused on expressions and declarations analysis. However, for sake of completness and in order to provide some limited type-information in Mulang AST, `TypeAlias`, `TypeSignature` and `TypeCast` expressions are provided. +Mulang AST support for type analysis is quite limited, and it is mostly focused on expressions and declarations analysis. However, for sake of completeness and in order to provide some limited type-information in Mulang AST, `TypeAlias`, `TypeSignature` and `TypeCast` expressions are provided. See [types section](#types) for more details. @@ -1893,11 +1893,11 @@ When processing statically-typed languages, all type-information - regardless we #### Haskell Example ```haskell -type Point = (Point, Int) +type Point = (Int, Int) ``` ```haskell -(TypeAlias "Point" "(Point, Int") +(TypeAlias "Point" "(Int, Int)") ``` ### TypeSignature @@ -1946,7 +1946,7 @@ elem :: (Eq a, Foldable t) => a -> t a -> Bool #### Java Examples -In Java, as in most typed C-like languages, type signature and variable declartions are bound. This means that, for example, a local variable declaration will produce both a `TypeSignature` and a `Variable` expression. +In Java, as in most typed C-like languages, type signature and variable declarations are bound. This means that, for example, a local variable declaration will produce both a `TypeSignature` and a `Variable` expression. Variable and attribute types: @@ -1961,7 +1961,7 @@ String name; Method types: ```java -void String f() { return null; } +String f() { return null; } ``` ```haskell @@ -1971,7 +1971,7 @@ void String f() { return null; } Method types with type parameters: ```java -void A f() { return null; } + A f() { return null; } ``` ```haskell @@ -1981,7 +1981,7 @@ void A f() { return null; } Method types with type parameters and constraints: ```java -void void f(A a) {} + void f(A a) {} ``` ```haskell @@ -2003,7 +2003,7 @@ class A { } > A `TypeCast` represent explictly giving a type to an expression > which may have static or dynamic impact on the program. It is aimed to represent -> type-casts in c-like languages and inline type signatures in funcional languages. +> type-casts in c-like languages and inline type signatures in functional languages. #### Syntax From a3c95c658c03bb2cbc79a09ae1f4e75a485cd886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Berbel=20Alt?= Date: Wed, 2 May 2018 15:20:30 -0300 Subject: [PATCH 5/8] add code and nested pattern fields to otherpattern and add debugType and debugPattern functions --- src/Language/Mulang/Ast.hs | 12 ++++++++++-- src/Language/Mulang/Parsers/Haskell.hs | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs index 085f817e4..a68608ae5 100644 --- a/src/Language/Mulang/Ast.hs +++ b/src/Language/Mulang/Ast.hs @@ -24,6 +24,8 @@ module Language.Mulang.Ast ( Identifier, SubroutineBody, debug, + debugType, + debugPattern, pattern Other, pattern OtherBody, pattern SimpleEquation, @@ -210,8 +212,8 @@ data Pattern | WildcardPattern -- ^ wildcard pattern @_@ | UnionPattern [Pattern] - | OtherPattern - -- ^ Other unrecognized pattern + | OtherPattern (Maybe String) (Maybe Pattern) + -- ^ Other unrecognized pattern with optional code and nested pattern deriving (Eq, Show, Read, Generic) data Statement @@ -222,6 +224,12 @@ data Statement debug :: Show a => a -> Expression debug a = Unknown (Just (show a)) Nothing +debugType :: Show a => a -> Type +debugType a = OtherType (Just (show a)) Nothing + +debugPattern :: Show a => a -> Pattern +debugPattern a = OtherPattern (Just (show a)) Nothing + pattern VariableSignature name t cs = TypeSignature name (SimpleType t cs) pattern SubroutineSignature name args t cs = TypeSignature name (ParameterizedType args t cs) pattern ModuleSignature name cs = TypeSignature name (ConstrainedType cs) diff --git a/src/Language/Mulang/Parsers/Haskell.hs b/src/Language/Mulang/Parsers/Haskell.hs index 1ae08e65f..4e71b3bd8 100644 --- a/src/Language/Mulang/Parsers/Haskell.hs +++ b/src/Language/Mulang/Parsers/Haskell.hs @@ -58,7 +58,7 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) muPat (HsPParen pattern) = muPat pattern muPat (HsPAsPat name pattern) = AsPattern (muName name) (muPat pattern) muPat HsPWildCard = WildcardPattern - muPat _ = OtherPattern + muPat p = debugPattern p muExp (HsVar (UnQual (HsIdent "undefined"))) = Raise (MuString "undefined") From 53d9dc9593fd6757ddf0042e1602e5da34868c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Berbel=20Alt?= Date: Wed, 2 May 2018 18:10:46 -0300 Subject: [PATCH 6/8] fix type alias and add typecast support to haskell --- spec/HaskellSpec.hs | 3 +++ src/Language/Mulang/Parsers/Haskell.hs | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/HaskellSpec.hs b/spec/HaskellSpec.hs index 42da27832..113de8bb4 100644 --- a/spec/HaskellSpec.hs +++ b/spec/HaskellSpec.hs @@ -30,3 +30,6 @@ spec = do it "parses inline type annotations" $ do hs "x = 1 :: Int" `shouldBe` Variable "x" (TypeCast (MuNumber 1) (SimpleType "Int" [])) + + it "parses inline type annotations with restrictions" $ do + hs "x = 1 :: (Num a, Foldable t) => t a" `shouldBe` Variable "x" (TypeCast (MuNumber 1) (SimpleType "t a" ["Num a", "Foldable t"])) diff --git a/src/Language/Mulang/Parsers/Haskell.hs b/src/Language/Mulang/Parsers/Haskell.hs index 4e71b3bd8..bc1c8d3a1 100644 --- a/src/Language/Mulang/Parsers/Haskell.hs +++ b/src/Language/Mulang/Parsers/Haskell.hs @@ -29,7 +29,7 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) where mergeDecls decls exp = compact (decls ++ [exp]) - muDecls (HsTypeDecl _ name _ t) = [TypeAlias (muName name) (muTypeId t)] + muDecls (HsTypeDecl _ name args t) = [TypeAlias (unwords . map muName $ name : args) (muTypeId t)] muDecls (HsDataDecl _ _ name _ _ _ ) = [Record (muName name)] muDecls (HsTypeSig _ names (HsQualType constraints t)) = map (muTypeSignature constraints t) names @@ -90,6 +90,7 @@ mu (HsModule _ _ _ _ decls) = compact (concatMap muDecls decls) muExp (HsEnumFromThenTo from thn to) = Application (Reference "enumFromThenTo") [(muExp from), (muExp thn), (muExp to)] muExp (HsListComp exp stmts) = For (map muStmt stmts) (Yield (muExp exp)) muExp (HsDo stmts) | (HsQualifier exp) <- last stmts = For (map muStmt stmts) (Yield (muExp exp)) + muExp (HsExpTypeSig _ exp (HsQualType cs t)) = TypeCast (muExp exp) (muType t cs) muExp e = debug e muLit (HsCharPrim v) = MuString [v] From b26c8b8316604f1194301d9fa84c081276030a8b Mon Sep 17 00:00:00 2001 From: Franco Bulgarelli Date: Wed, 2 May 2018 23:55:36 -0300 Subject: [PATCH 7/8] Merging unknown and other semantics Fixes #167 --- spec/InspectorSpec.hs | 2 +- src/Language/Mulang/Ast.hs | 9 ++------- src/Language/Mulang/Generator.hs | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/spec/InspectorSpec.hs b/spec/InspectorSpec.hs index 5f2c369b5..d1e804f76 100644 --- a/spec/InspectorSpec.hs +++ b/spec/InspectorSpec.hs @@ -94,7 +94,7 @@ spec = do it "is False otherwise" $ do assigns (named "x") (Assignment "y" (MuTrue)) `shouldBe` False - assigns (named "x") (Other) `shouldBe` False + assigns (named "x") (Other Nothing Nothing) `shouldBe` False assigns (named "x") (MuFalse) `shouldBe` False describe "declaresFunction" $ do diff --git a/src/Language/Mulang/Ast.hs b/src/Language/Mulang/Ast.hs index a68608ae5..a39d5ca8e 100644 --- a/src/Language/Mulang/Ast.hs +++ b/src/Language/Mulang/Ast.hs @@ -26,8 +26,6 @@ module Language.Mulang.Ast ( debug, debugType, debugPattern, - pattern Other, - pattern OtherBody, pattern SimpleEquation, pattern SimpleFunction, pattern SimpleProcedure, @@ -166,7 +164,7 @@ data Expression -- ^ Imperative / OOP programming c-style for loop | Sequence [Expression] -- ^ Generic sequence of statements - | Unknown (Maybe String) (Maybe Expression) + | Other (Maybe String) (Maybe Expression) -- ^ Unrecognized expression, with optional description and body | Equal | NotEqual @@ -222,7 +220,7 @@ data Statement deriving (Eq, Show, Read, Generic) debug :: Show a => a -> Expression -debug a = Unknown (Just (show a)) Nothing +debug a = Other (Just (show a)) Nothing debugType :: Show a => a -> Type debugType a = OtherType (Just (show a)) Nothing @@ -234,9 +232,6 @@ pattern VariableSignature name t cs = TypeSignature name (SimpleType t cs pattern SubroutineSignature name args t cs = TypeSignature name (ParameterizedType args t cs) pattern ModuleSignature name cs = TypeSignature name (ConstrainedType cs) -pattern Other = Unknown Nothing Nothing -pattern OtherBody body <- Unknown _ (Just body) - pattern SimpleEquation params body = Equation params (UnguardedBody body) pattern SimpleSend receptor selector args = Send receptor (Reference selector) args diff --git a/src/Language/Mulang/Generator.hs b/src/Language/Mulang/Generator.hs index a56b6dfa4..88ad5ae00 100644 --- a/src/Language/Mulang/Generator.hs +++ b/src/Language/Mulang/Generator.hs @@ -71,7 +71,7 @@ expressions expr = expr : concatMap expressions (subExpressions expr) subExpressions (New _ es) = es subExpressions (Not e) = [e] subExpressions (Object _ v) = [v] - subExpressions (OtherBody e) = [e] + subExpressions (Other _ (Just e)) = [e] subExpressions (Repeat e1 e2) = [e1, e2] subExpressions (Return v) = [v] subExpressions (Sequence es) = es From ce305350f4edd61df3eac290721d24d1257dee50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juli=C3=A1n=20Berbel=20Alt?= Date: Thu, 3 May 2018 11:47:21 -0300 Subject: [PATCH 8/8] add type parametrization support to java --- spec/JavaSpec.hs | 11 ++++++++--- src/Language/Mulang/Parsers/Java.hs | 22 +++++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/spec/JavaSpec.hs b/spec/JavaSpec.hs index db3bf31bc..67680543a 100644 --- a/spec/JavaSpec.hs +++ b/spec/JavaSpec.hs @@ -30,11 +30,16 @@ spec = do ModuleSignature "Foo" ["A"], Interface "Foo" [] MuNull] - it "parses Simple Interface with type args and constraints" $ do - run "public interface Foo {}" `shouldBe` Sequence [ - ModuleSignature "Foo" ["A extends B"], + it "parses Simple Interface with complex type parametrization" $ do + run "public interface Foo> {}" `shouldBe` Sequence [ + ModuleSignature "Foo" ["A extends Comparable"], Interface "Foo" [] MuNull] + it "parses Simple Class with type args" $ do + run "public class Foo {}" `shouldBe` Sequence [ + ModuleSignature "Foo" ["A"], + Class "Foo" Nothing MuNull] + it "parses Simple Interface With Messages" $ do run "public interface Foo { void foo(); }" `shouldBe` Interface "Foo" [] (SubroutineSignature "foo" [] "void" []) diff --git a/src/Language/Mulang/Parsers/Java.hs b/src/Language/Mulang/Parsers/Java.hs index c07124767..89f12d634 100644 --- a/src/Language/Mulang/Parsers/Java.hs +++ b/src/Language/Mulang/Parsers/Java.hs @@ -10,6 +10,7 @@ import Language.Mulang.Builder (compact, compactMap, compactConcatMap) import Language.Java.Parser import Language.Java.Syntax +import Language.Java.Pretty (prettyPrint) import Control.Fallible @@ -28,18 +29,29 @@ parseJava' = fmap m . j m (CompilationUnit _ _ typeDecls) = compactMap muTypeDecl $ typeDecls -muTypeDecl (ClassTypeDecl decl) = muClassTypeDecl decl +muTypeDecl (ClassTypeDecl decl) = muClassTypeDecl decl muTypeDecl (InterfaceTypeDecl decl) = muInterfaceTypeDecl decl -muClassTypeDecl (ClassDecl _ name _ superclass interfaces (ClassBody body)) = +muClass (ClassDecl _ name _ superclass interfaces (ClassBody body)) = Class (i name) (fmap muRefType superclass) (compact (map muImplements interfaces ++ concatMap muDecl body)) -muClassTypeDecl (EnumDecl _ name _ (EnumBody constants _)) = + +muEnum (EnumDecl _ name _ (EnumBody constants _)) = Enumeration (i name) (map muEnumConstant constants) +muInterface (InterfaceDecl _ name _ interfaces (InterfaceBody body)) = + Interface (i name) (map muRefType interfaces) (compactConcatMap muMemberDecl body) + +muClassTypeDecl clazz@(ClassDecl _ name args _ _ _) = muDeclaration name args $ muClass clazz + +muClassTypeDecl enum@(EnumDecl _ name _ (EnumBody constants _)) = + Enumeration (i name) (map muEnumConstant constants) + muImplements interface = Implement $ muRefType interface -muInterfaceTypeDecl (InterfaceDecl _ name _ interfaces (InterfaceBody body)) = - Interface (i name) (map muRefType interfaces) (compactConcatMap muMemberDecl body ) +muInterfaceTypeDecl interface@(InterfaceDecl _ name args _ _) = muDeclaration name args $ muInterface interface + +muDeclaration _ [] decl = decl +muDeclaration name args decl = Sequence [ModuleSignature (i name) (map prettyPrint args), decl] muDecl :: Decl -> [Expression] muDecl (MemberDecl memberDecl) = muMemberDecl memberDecl