Skip to content

Instantly share code, notes, and snippets.

@ugovaretto
Last active October 5, 2020 09:42
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 ugovaretto/965a73bccd5f2b18333dfc38e5569fd3 to your computer and use it in GitHub Desktop.
Save ugovaretto/965a73bccd5f2b18333dfc38e5569fd3 to your computer and use it in GitHub Desktop.
mini GNUPlot DSL in NIM
# Generate gnuplot string from NIM DSL with variable substitution
# Author: Ugo Varetto
import macros, sets, sequtils, strutils, strformat, sugar
proc genCommands(node: NimNode,
stmts: var seq[seq[string]],
cur: var seq[string],
commands: HashSet[string],
subst: bool = false): bool =
#last list not added
var substitute = false
var inbracket = 0
var separator = ","
if node.kind == nnkIdent:
if len(cur) > 0 and cur[^1] == "save" and node.strVal == "set":
cur.add node.strVal
elif node.strVal in commands:
if len(cur) > 0 :
stmts.add(cur)
cur = newSeq[string]()
cur.add node.strVal
else:
if node.strVal == "!":
return true
else:
if subst:
cur.add "{" & node.strVal & "}"
else:
cur.add node.strVal
elif node.kind == nnkStrLit:
cur.add fmt"'{node.strVal}'"
elif node.kind == nnkIntLit:
cur.add $node.intVal
elif node.kind == nnkFloatLit:
cur.add $node.floatVal
elif node.kind == nnkBracket:
cur.add "["
inbracket = len(node)
separator = ","
elif node.kind == nnkExprColonExpr:
separator = ":"
inbracket = len(node)
else:
echo $node.kind
for n in node.children:
if inbracket > 0 and cur[^1] != "[":
cur.add separator
substitute = genCommands(n, stmts, cur, commands, substitute)
if inbracket == 1:
cur.add "]"
if inbracket > 0:
inbracket -= 1
substitute
const commands = toHashSet(["set", "plot", "splot", "load", "save", "bind", "unset", "fit", "array", "stats", "FILE"])
macro gnuplot*(varname: untyped, body: untyped)=
#parse line by line to keep same format
echo body.toStrLit.strVal.split("\n")
let t = parseStmt(body.toStrLit.strVal.split("\n")[1])
var stm: seq[seq[string]]
var cur: seq[string]
discard genCommands(body, stm, cur, commands)
if len(cur) > 0:
stm.add(cur)
let cmds = stm.map((x: seq[string]) -> string => x.join(" ")).join("\n")
result = newStmtList(
newConstStmt(varname, newStrLitNode(cmds))
)
let color = "#0060ad"
gnuplot gpcommands:
set style line 1 linecolor rgb color! linetype 1 linewidth 2
set style line 4 linecolor rgb "#0660ad" linetype 1 linewidth 5
plot [0:0.5] sin(x) "file.dat"
set x [1,[2,4],3]
echo fmt $gpcommands
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment