Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert mutable type which is unhasable to immutable types #123

Merged
merged 11 commits into from
Jun 1, 2017
46 changes: 35 additions & 11 deletions src/Nirum/Targets/Python.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ module Nirum.Targets.Python ( Code
, unionInstallRequires
) where

import Control.Monad (forM)
import qualified Control.Monad.State as ST
import qualified Data.List as L
import Data.Maybe (fromMaybe)
Expand Down Expand Up @@ -133,7 +134,7 @@ import Nirum.Package.Metadata ( Author (Author, name, email)
import qualified Nirum.Package.ModuleSet as MS

minimumRuntime :: SV.Version
minimumRuntime = SV.version 0 3 9 [] []
minimumRuntime = SV.version 0 4 0 [] []

data Python = Python { packageName :: T.Text
, minimumRuntimeVersion :: SV.Version
Expand Down Expand Up @@ -301,6 +302,32 @@ toIndentedCodes :: (a -> T.Text) -> [a] -> T.Text -> T.Text
toIndentedCodes f traversable concatenator =
T.intercalate concatenator $ map f traversable

compileParameters :: (ParameterName -> ParameterType -> Code)
-> [(T.Text, Code)]
-> Code
compileParameters gen nameTypePairs =
toIndentedCodes (uncurry gen) nameTypePairs ", "

compileFieldInitializers :: DS.DeclarationSet Field -> CodeGen Code
compileFieldInitializers fields = do
initializers <- forM (toList fields) compileFieldInitializer
return $ T.intercalate "\n " initializers
where
compileFieldInitializer :: Field -> CodeGen Code
compileFieldInitializer (Field fieldName' fieldType' _) =
case fieldType' of
SetModifier _ ->
return [qq|self.$attributeName = frozenset($attributeName)|]
ListModifier _ -> do
let imports = [("nirum.datastructures", ["list_type"])]
insertThirdPartyImports imports
return [qq|self.$attributeName = list_type($attributeName)|]
_ -> return [qq|self.$attributeName = $attributeName|]
where
attributeName :: Code
attributeName = toAttributeName' fieldName'


quote :: T.Text -> T.Text
quote s = [qq|'{s}'|]

Expand Down Expand Up @@ -383,6 +410,7 @@ returnCompiler = do
Python2 -> ""
Python3 -> [qq| -> $r|]


compileUnionTag :: Source -> Name -> Tag -> CodeGen Code
compileUnionTag source parentname d@(Tag typename' fields _) = do
typeExprCodes <- mapM (compileTypeExpression source)
Expand All @@ -401,9 +429,6 @@ compileUnionTag source parentname d@(Tag typename' fields _) = do
where
attributes :: T.Text
attributes = toIndentedCodes (\ n -> [qq|self.{n}|]) tagNames ", "
initialArgs gen = toIndentedCodes (uncurry gen) nameNTypes ", "
initialValues =
toIndentedCodes (\ n -> [qq|self.{n} = {n}|]) tagNames "\n "
nameMaps = toIndentedCodes
toNamePair
(map fieldName $ toList fields)
Expand All @@ -415,6 +440,7 @@ compileUnionTag source parentname d@(Tag typename' fields _) = do
typeRepr <- typeReprCompiler
arg <- parameterCompiler
ret <- returnCompiler
initializers <- compileFieldInitializers fields
return [qq|
class $className($parentClass):
{compileDocstringWithFields " " d fields}
Expand All @@ -429,8 +455,8 @@ class $className($parentClass):
$nameMaps
])

def __init__(self, {initialArgs arg}){ ret "None" }:
$initialValues
def __init__(self, {compileParameters arg nameNTypes}){ ret "None" }:
$initializers
validate_union_type(self)

def __repr__(self){ ret "str" }:
Expand Down Expand Up @@ -629,9 +655,6 @@ compileTypeDeclaration src d@TypeDeclaration { typename = typename'
slotTypes = toIndentedCodes
(\ (n, t) -> [qq|'{n}': {t}|]) nameTypePairs ",\n "
slots = toIndentedCodes (\ n -> [qq|'{n}'|]) fieldNames ",\n "
initialArgs gen = toIndentedCodes (uncurry gen) nameTypePairs ", "
initialValues = toIndentedCodes
(\ n -> [qq|self.{n} = {n}|]) fieldNames "\n "
nameMaps = toIndentedCodes
toNamePair
(map fieldName $ toList fields)
Expand All @@ -646,6 +669,7 @@ compileTypeDeclaration src d@TypeDeclaration { typename = typename'
arg <- parameterCompiler
ret <- returnCompiler
typeRepr <- typeReprCompiler
initializers <- compileFieldInitializers fields
let clsType = arg "cls" "type"
return [qq|
class $className(object):
Expand All @@ -663,8 +687,8 @@ class $className(object):
$nameMaps
])

def __init__(self, {initialArgs arg}){ret "None"}:
$initialValues
def __init__(self, {compileParameters arg nameTypePairs}){ret "None"}:
$initializers
validate_record_type(self)

def __repr__(self){ret "bool"}:
Expand Down
20 changes: 19 additions & 1 deletion test/nirum_fixture/fixture/foo.nrm
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type irum = name;
enum gender
# Enum docs.
= female/yeoseong
| male
| male
;
enum eva-char = soryu-asuka-langley
| ayanami-rei
Expand Down Expand Up @@ -67,6 +67,15 @@ union status = run
| stop
;

record song (
text name,
);

record album (
text name,
[song] tracks,
);

service null-service ();

service ping-service (
Expand All @@ -77,3 +86,12 @@ service ping-service (
# Parameter docs.
),
);

record person (
irum first-name,
irum last-name,
);

record people (
{person} people
);
20 changes: 20 additions & 0 deletions test/python/typeconversion_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from nirum.datastructures import List

from fixture.foo import Album, Name, People, Person, Song


def test_sequence_to_tuple():
album = Album(name=u'25', tracks=[
Song(name=u'Hello')
])
assert isinstance(album.tracks, List)
assert hash(album)


def test_set_to_frozenset():
people = People(people={
Person(first_name=Name(u'hyojun'), last_name=Name(u'kang')),
Person(first_name=Name(u'minhee'), last_name=Name(u'hong'))
})
assert isinstance(people.people, frozenset)
assert hash(people)
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ envlist =
deps =
six
flake8
nirum>=0.3.7
nirum>=0.4.1
pytest
commands =
pip install -e ./nirum_fixture
Expand Down