Skip to content

How to add a language

Santiago Munín edited this page Aug 15, 2015 · 2 revisions

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).

Location

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 other

The 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
...

Adding the new language to the end to end tests

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:

  • bad examples: compile them and make sure they fail.
  • good examples:
    • 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).

The final step is to run this script to make sure that the new implementation is correct.

Clone this wiki locally