Skip to content

Instantly share code, notes, and snippets.

@progrium
Last active July 14, 2018 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save progrium/c9d56b826b9b5db313758fa16e9c5a5e to your computer and use it in GitHub Desktop.
Save progrium/c9d56b826b9b5db313758fa16e9c5a5e to your computer and use it in GitHub Desktop.
Example throw-away DSL for generating TypeScript
var Generator = require("./tsgen")
ts = new Generator()
ts.decl("import", "electron", "from", ts.str("electron"))
ts.decl("import", "qrpc", "from", ts.str("qrpc"))
ts.commentBlock("Here is a function")
ts.func("register", [ts.var("api", "qrpc.API")], null, (ts) => {
ts.call("api.handle", ts.str("echo"), ts.lambda(ts.var("r", "qrpc.Responder"), ts.var("c", "qrpc.Call"), null, (ts) => {
ts.call("r.return", ts.inline(ts.call("c.decode")))
}))
})
ts.decl("export", "register")
console.log(ts.toString())
import electron from "electron";
import qrpc from "qrpc";
/**
* Here is a function
*/
function register(api: qrpc.API) {
api.handle("echo", (r: qrpc.Responder, c: qrpc.Call) => {
r.return(c.decode());
});
}
export register;
module.exports = class Generator {
constructor() {
this.stack = []
this.stmts = []
}
decl(...args) {
if (typeof args[args.length-1] == "function") {
var blockFn = args.pop()
this.stmts.push(`${args.join(" ")} {\n${this.block(blockFn)}\n}`)
} else {
var semi = ";"
if (args[0].startsWith("/")) semi = ""
this.stmts.push(args.join(" ")+semi)
}
}
inline() {
return this.stmts.pop().slice(0,-1)
}
func(name, args, type, blockFn) {
this.decl("function", `${name}${this.signature(args, type)}`, blockFn)
}
call(name, ...args) {
this.decl(`${name}(${(args||[]).join(", ")})`)
}
comment(str) {
this.decl(`// ${str}`)
}
commentBlock(str) {
this.decl("/**\n * "+(str||"").split("\n").join("\n * ")+"\n */")
}
block(blockFn) {
this.stack.push(this.stmts)
this.stmts = []
blockFn(this)
var blockStmts = this.stmts
this.stmts = this.stack.pop()
return blockStmts.join("\n")
}
signature(args, type) {
return `(${(args||[]).join(", ")})${(type) ? `: ${type} ` : ""}`
}
str(v) {
return `"${v}"`
}
lambda(...args) {
var blockFn = args.pop()
var type = args.pop()
return `${this.signature(args, type)} => {\n${this.block(blockFn)}\n}`
}
var(name, type, value) {
return (value) ? `${name}: ${type} = ${value}` : `${name}: ${type}`
}
toString() {
return this.stmts.join("\n")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment