mini GNUPlot DSL in NIM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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