diff --git a/README.md b/README.md index 87a6f9608..cdeffb969 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) @@ -896,14 +901,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 these 5 categories. ## Expressions @@ -944,67 +950,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 -``` - -```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. - -```java -String name; -``` - -```haskell -(TypeSignature "name" [] "String") -``` +### `TypeAlias`, `TypeSignature` and `TypeCast` -#### Caveats +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. -`TypeSignature`s of zero-args computation and variables are identical. +See [types section](#types) for more details. ### `EntryPoint` @@ -1613,10 +1563,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 +1868,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 = (Int, Int) +``` + +```haskell +(TypeAlias "Point" "(Int, 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 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: + +```java +String name; +``` + +```haskell +(TypeSignature "name" (SimpleType "String" [])) +``` + +Method types: + +```java +String f() { return null; } +``` + +```haskell +(TypeSignature "f" (ParameterizedType [] "String" [])) +``` + +Method types with type parameters: + +```java + A f() { return null; } +``` + +```haskell +(TypeSignature "f" (ParameterizedType [] "A" ["A"])) +``` + +Method types with type parameters and constraints: + +```java + 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 functional 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 3c383fb35..113de8bb4 100644 --- a/spec/HaskellSpec.hs +++ b/spec/HaskellSpec.hs @@ -12,3 +12,24 @@ 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" [])) + + 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/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/spec/JavaSpec.hs b/spec/JavaSpec.hs index 8dfd07963..67680543a 100644 --- a/spec/JavaSpec.hs +++ b/spec/JavaSpec.hs @@ -25,14 +25,29 @@ 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 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" [] (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 +57,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 +102,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 +110,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 +146,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 +156,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 +166,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 +176,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 +186,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 +194,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 +202,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 +212,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 +220,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 +229,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 +238,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 +246,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 +254,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 +265,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 +275,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 +286,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 +294,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 1d177b5fd..a39d5ca8e 100644 --- a/src/Language/Mulang/Ast.hs +++ b/src/Language/Mulang/Ast.hs @@ -17,22 +17,25 @@ module Language.Mulang.Ast ( Code, Equation(..), EquationBody(..), + Type(..), Expression(..), Statement(..), Pattern(..), Identifier, SubroutineBody, debug, - pattern Other, - pattern OtherBody, + debugType, + debugPattern, pattern SimpleEquation, pattern SimpleFunction, 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. @@ -61,15 +81,19 @@ 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 -- ^ 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 @@ -140,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 @@ -186,8 +210,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 @@ -196,10 +220,17 @@ 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 -pattern Other = Unknown Nothing Nothing -pattern OtherBody body <- Unknown _ (Just body) +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) pattern SimpleEquation params body = Equation params (UnguardedBody body) @@ -212,8 +243,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 ba9084bf9..88ad5ae00 100644 --- a/src/Language/Mulang/Generator.hs +++ b/src/Language/Mulang/Generator.hs @@ -36,8 +36,8 @@ 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@(TypeSignature n _ _)= [(n, e)] +declarations e@(TypeAlias 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] @@ -71,13 +71,14 @@ 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 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 b90847636..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 @@ -154,13 +154,13 @@ 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 - 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 22448999e..bc1c8d3a1 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 _ _) = [TypeAlias (muName name)] + muDecls (HsTypeDecl _ name args t) = [TypeAlias (unwords . map muName $ name : args) (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)] @@ -57,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") @@ -89,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] @@ -124,19 +126,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..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 @@ -58,7 +70,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 +155,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 +185,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)