-
Notifications
You must be signed in to change notification settings - Fork 1
How to add a language
Adding a new language to Harmony is not an easy task: it involves a lot of template code. The good news is that the generation framework needs little modification (which in our opinion is a symptom of a good design).
Language implementations are inside the templates folder, and the structure of that folder is the one followed by Harmony while generating the output.
If one wants to implement a server in Go, she should create the templates/server/go folder and implement the templates there. The TemplateCompiler.hs file contains the Service record (the one sent to the template compiler), one should refer to this record in order to figure out which commands can be used in the templates. For more information, refer to the Mustache/Hastache documentation (the existing templates are also a good source of information).
## Enabling the language in Harmony
Implementing the templates is not enough if the tool cannot provide a way of selecting the new output. For this reason, it is necessary to first add a function to OutputGenerator.hs that contains generation related information for the new target:
generateGoServer :: GenerationFunction
generateGoServer =
generateOutput (files, templates, fieldMapping) postOpFunc
where
-- Static files
files = [ "templates/server/go/runtime_lib.go"]
-- Templates (to be compiled to .go files)
templates = [ ("templates/server/go/server.tpl", "go")
, ("templates/server/go/util.tpl", "go")
]
-- How types are represented in the target language
fieldMapping AS.TString = "string"
fieldMapping AS.TLong = "int64"
fieldMapping AS.TInt = "int32"
fieldMapping AS.TDouble = "float64"
fieldMapping (AS.TList t) = "[]" ++ fieldMapping t
...
fieldMapping other =
error \$ "Go server generation: Type not recognized -> "
++ show otherThe postOpFunc can optionally be modified in order to apply any beautifier or postprocessing necessary:
postOpFunc :: String -> FilePath -> IO ()
postOpFunc "go" = applyGoPostProcessing
...
postOpFunc _ = \_ -> return ()With this, the developer only needs to map a flag value to the generation function in harmony-commandline/Main.hs:
parseClient, parseServer :: Maybe String -> OG.GenerationFunction
...
parseServer (Just "js") = OG.generateJSServer
parseServer (Just "go") = OG.generateGoServer
...The end to end tests are specified in the tests.sh script. This script needs to be modified in order to add the new target to the end to end testing. The developer should proceed as follows:
-
badexamples: compile them and make sure they fail. -
goodexamples:- Servers
- Compile.
- Deploy.
- Execute at least one of the client + test bundles.
- Clients: if tests are also generated, then add them to all the servers steps (otherwise, open an issue to track the eventual implementation of the tests).
- Servers
The final step is to run this script to make sure that the new implementation is correct.