As I was about to write a code generator for F#, I was wondering whether I could avoid stepping into the indentation mess by generating only one-line-values.
As part of this effort, I was considering how I could express Object Expressions in one single line, but couldn't succeed, except in Verbose Mode.
let Expr() = (let ToString = "ToString" in { new System.Object() with member this.ToString() = ToString; member this.GetHashCode() = ToString.GetHashCode()})
The issue is that I don't want to generate all my code in Verbose mode, this is a compatibility feature. Is there any other option?
Thanks a lot in advance for your insights!
François
The reason I ask for this is that I have to generate Object Expressions in arbitrary expressions and I would like to avoid to count the number of characters in the current line to compute how much I've to indent the next line.
(Shameless plug) I maintain F# source code formatter which exposes APIs to pretty-print full F# 3.0 syntax. You have several options:
Implement your code generator using verbose mode and run the source code formatter APIs on the output. Then you don't have to worry about indentation and line break on verbose mode is very easy.
Implement your code generator using functional combinators. There are many combinators in FormatConfig module which you can copy and modify. F# indentation rule is clear; you can read more in this article.
You probably have an AST for pretty printing. If you prefer a lightweight solution, F# Compiler CodeDom has similar combinators for code generation.
This is not strictly speaking an answer, but what is so bad about writing it with proper indentation? You can always make a list of the generated lines and add indentation in a separate step. This is how I usually generate code, even if the language (e.g. HTML) does not need indentation.
Why does generated code have to be illegible for humans? The proper indentation makes a review of the generated code easier and you can even use usual diff tools, if you for instance have the generated sources commited to source control.
At least in my experience proper indentation is actually far less difficult than one might think, especially when generating. Don't forget, that you have all the context at hand during the generation, so adding a level of indentation should be very easy.
let indent = List.map (sprintf " %s")
[
yield "let Expr() ="
yield! [
yield "let ToString = \"ToString\""
yield "{"
yield! [
"new System.Object() with"
"member this.ToString() = ToString"
"member this.GetHashCode() = ToString.GetHashCode()"
] |> indent
yield "}"
] |> indent
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With