-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds basic generation of record wrappers (#40)
* Adds basic generation of record wrappers * Fix missing `extends` generation
- Loading branch information
1 parent
55598ea
commit 58ec90e
Showing
7 changed files
with
225 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,22 @@ | ||
module Morphir.Snowpark.Constants exposing (..) | ||
import Morphir.Scala.AST as Scala | ||
|
||
snowflakeNamespace : List String | ||
snowflakeNamespace = ["com", "snowflake", "snowpark"] | ||
|
||
functionsNamespace : List String | ||
functionsNamespace = ["com", "snowpark", "functions"] | ||
functionsNamespace = snowflakeNamespace ++ ["functions"] | ||
|
||
|
||
|
||
applySnowparkFunc : String -> List Scala.Value -> Scala.Value | ||
applySnowparkFunc name args = | ||
Scala.Apply | ||
(Scala.Ref functionsNamespace name) | ||
(args |> List.map (\v -> Scala.ArgValue Nothing v)) | ||
(args |> List.map (\v -> Scala.ArgValue Nothing v)) | ||
|
||
|
||
|
||
typeRefForSnowparkType : String -> Scala.Type | ||
typeRefForSnowparkType typeName = | ||
(Scala.TypeRef snowflakeNamespace typeName) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
module Morphir.Snowpark.RecordWrapperGenerator exposing (generateRecordWrappers) | ||
|
||
import Dict exposing (Dict) | ||
import Morphir.Scala.AST as Scala | ||
import Morphir.IR.Documented exposing (Documented) | ||
import Morphir.IR.AccessControlled exposing (Access(..), AccessControlled) | ||
import Morphir.IR.Name exposing (Name, toTitleCase) | ||
import Morphir.IR.Type as Type | ||
import Morphir.IR.Package as Package | ||
import Morphir.IR.Module exposing (ModuleName) | ||
import Morphir.IR.FQName as FQName | ||
import Morphir.Snowpark.MappingContext exposing (MappingContextInfo, isRecordWithSimpleTypes) | ||
import Morphir.IR.Type exposing (Field) | ||
import Morphir.IR.Name as Name | ||
import Morphir.Snowpark.Constants exposing (applySnowparkFunc) | ||
import Morphir.Snowpark.Constants exposing (typeRefForSnowparkType) | ||
|
||
|
||
{-| This module contains to create wrappers for record declarations that represent tables. | ||
For each record a Trait and an Object is generated with `Column` fields for each member. | ||
|-} | ||
|
||
generateRecordWrappers : Package.PackageName -> ModuleName -> MappingContextInfo a -> Dict Name (AccessControlled (Documented (Type.Definition ta))) -> List (Scala.Documented (Scala.Annotated Scala.TypeDecl)) | ||
generateRecordWrappers packageName moduleName ctx typesInModule = | ||
typesInModule | ||
|> Dict.toList | ||
|> List.concatMap (processTypeDeclaration packageName moduleName ctx) | ||
|
||
|
||
processTypeDeclaration : Package.PackageName -> ModuleName -> MappingContextInfo a -> (Name, (AccessControlled (Documented (Type.Definition ta)))) -> List (Scala.Documented (Scala.Annotated Scala.TypeDecl)) | ||
processTypeDeclaration packageName moduleName ctx (name, typeDeclAc) = | ||
-- For the moment we are going generating wrappers for record types | ||
case typeDeclAc.value.value of | ||
Type.TypeAliasDefinition _ (Type.Record _ members) -> | ||
processRecordDeclaration | ||
name | ||
typeDeclAc.value.doc | ||
members | ||
(isRecordWithSimpleTypes (FQName.fQName packageName moduleName name) ctx) | ||
_ -> [] | ||
|
||
processRecordDeclaration : Name -> String -> (List (Field a)) -> Bool -> List (Scala.Documented (Scala.Annotated Scala.TypeDecl)) | ||
processRecordDeclaration name doc fields recordWithSimpleTypes = | ||
if recordWithSimpleTypes then | ||
[ | ||
traitForRecordWrapper name doc fields, | ||
objectForRecordWrapper name fields | ||
] | ||
else | ||
[] | ||
|
||
traitForRecordWrapper : Name -> String -> (List (Field a)) -> (Scala.Documented (Scala.Annotated Scala.TypeDecl)) | ||
traitForRecordWrapper name doc fields = | ||
let | ||
members = fields |> List.map generateTraitMember | ||
in | ||
( Scala.Documented (Just doc) | ||
(Scala.Annotated [] | ||
(Scala.Trait | ||
{ modifiers = | ||
[] | ||
, name = | ||
name |> toTitleCase | ||
, typeArgs = | ||
[] | ||
, members = | ||
members | ||
, extends = | ||
[] | ||
} | ||
) | ||
)) | ||
|
||
generateTraitMember : (Field a) -> (Scala.Annotated Scala.MemberDecl) | ||
generateTraitMember field = | ||
(Scala.Annotated | ||
[] | ||
(Scala.FunctionDecl | ||
{ | ||
modifiers = [] | ||
, name = (field.name |> Name.toCamelCase) | ||
, typeArgs = [] | ||
, args = [] | ||
, returnType = Just (typeRefForSnowparkType "Column") | ||
, body = Nothing | ||
})) | ||
|
||
|
||
objectForRecordWrapper : Name -> (List (Field a)) -> (Scala.Documented (Scala.Annotated Scala.TypeDecl)) | ||
objectForRecordWrapper name fields = | ||
let | ||
nameToUse = name |> toTitleCase | ||
members = fields |> List.map generateObjectMember | ||
in | ||
( Scala.Documented Nothing | ||
(Scala.Annotated [] | ||
(Scala.Object | ||
{ modifiers = | ||
[] | ||
, name = | ||
nameToUse | ||
, members = | ||
members | ||
, extends = | ||
[ Scala.TypeRef [] nameToUse ] | ||
, body = | ||
Nothing | ||
} | ||
) | ||
)) | ||
|
||
generateObjectMember : (Field a) -> (Scala.Annotated Scala.MemberDecl) | ||
generateObjectMember field = | ||
(Scala.Annotated | ||
[] | ||
(Scala.FunctionDecl | ||
{ | ||
modifiers = [] | ||
, name = (field.name |> Name.toCamelCase) | ||
, typeArgs = [] | ||
, args = [] | ||
, returnType = Just (typeRefForSnowparkType "Column") | ||
, body = Just (applySnowparkFunc "col" [(Scala.Literal (Scala.StringLit (field.name |> Name.toCamelCase)))]) | ||
})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
module Morphir.Snowpark.RecordWrapperGenerationTests exposing (..) | ||
|
||
|
||
import Dict | ||
import Test exposing (Test, describe, test) | ||
import Expect | ||
import Morphir.IR.Path as Path | ||
import Morphir.IR.Module exposing (emptyDefinition) | ||
import Morphir.IR.AccessControlled exposing (public) | ||
import Morphir.IR.Name as Name | ||
import Morphir.IR.Type as Type | ||
import Morphir.IR.Type exposing (Type(..)) | ||
import Morphir.Snowpark.MappingContext as MappingContext | ||
import Morphir.IR.Type exposing (Type(..)) | ||
import Morphir.Snowpark.RecordWrapperGenerator as RecordWrapperGenerator | ||
import Morphir.IR.Path as Path | ||
import Morphir.Scala.AST as Scala | ||
|
||
stringTypeInstance : Type () | ||
stringTypeInstance = Reference () ( [ [ "morphir" ], [ "s", "d", "k" ] ], [ [ "string" ] ], [ "string" ] ) [] | ||
|
||
testDistributionName = (Path.fromString "UTest") | ||
|
||
typesDict = | ||
Dict.fromList [ | ||
-- A record with simple types | ||
(Name.fromString "Emp1", | ||
public { doc = "", value = Type.TypeAliasDefinition [] (Type.Record () [ | ||
{ name = Name.fromString "firstname", tpe = stringTypeInstance }, | ||
{ name = Name.fromString "lastname", tpe = stringTypeInstance } | ||
]) }) | ||
] | ||
|
||
testDistributionPackage = | ||
({ modules = Dict.fromList [ | ||
( Path.fromString "MyMod", | ||
public { emptyDefinition | types = typesDict } ) | ||
]}) | ||
|
||
typeClassificationTests : Test | ||
typeClassificationTests = | ||
let | ||
calculatedContext = MappingContext.processDistributionModules testDistributionName testDistributionPackage | ||
firstModule = Dict.get [(Name.fromString "MyMod")] testDistributionPackage.modules |> Maybe.map (\access -> access.value) | ||
assertItCreatedWrapper = | ||
test ("Wrapper creation") <| | ||
\_ -> | ||
let | ||
generationResult = | ||
firstModule | ||
|> Maybe.map (\mod -> RecordWrapperGenerator.generateRecordWrappers testDistributionName (Path.fromString "MyMod") calculatedContext mod.types) | ||
|> Maybe.map (\scalaElementList -> scalaElementList |> List.map stringFromScalaTypeDefinition) | ||
|> Maybe.withDefault [] | ||
|
||
in | ||
Expect.equal ["Trait:Emp1:2", "Object:Emp1:2"] generationResult | ||
|
||
in | ||
describe "resolveTNam" | ||
[ assertItCreatedWrapper | ||
] | ||
|
||
|
||
stringFromScalaTypeDefinition : (Scala.Documented (Scala.Annotated Scala.TypeDecl)) -> String | ||
stringFromScalaTypeDefinition scalaElement = | ||
case scalaElement.value.value of | ||
Scala.Object { name, members } -> "Object:" ++ name ++ ":" ++ (members |> List.length |> String.fromInt) | ||
Scala.Trait { name, members } -> "Trait:" ++ name ++ ":" ++ (members |> List.length |> String.fromInt) | ||
_ -> "" |