# # # The Nim Compiler # (c) Copyright 2015 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # This module handles the parsing of command line arguments. # We do this here before the 'import' statement so 'defined' does not get # confused with 'TGCMode.gcGenerational' etc. template bootSwitch(name, expr, userString) = # Helper to build boot constants, for debugging you can 'echo' the else part. const name = if expr: " " & userString else: "" bootSwitch(usedRelease, defined(release), "-d:release") bootSwitch(usedGnuReadline, defined(useLinenoise), "-d:useLinenoise") bootSwitch(usedBoehm, defined(boehmgc), "--gc:boehm") bootSwitch(usedMarkAndSweep, defined(gcmarkandsweep), "--gc:markAndSweep") bootSwitch(usedGenerational, defined(gcgenerational), "--gc:generational") bootSwitch(usedGoGC, defined(gogc), "--gc:go") bootSwitch(usedNoGC, defined(nogc), "--gc:none") import os, msgs, options, nversion, condsyms, strutils, extccomp, platform, wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos, pathutils # but some have deps to imported modules. Yay. bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc") bootSwitch(usedNativeStacktrace, defined(nativeStackTrace) and nativeStackTraceSupported, "-d:nativeStackTrace") bootSwitch(usedFFI, hasFFI, "-d:useFFI") type TCmdLinePass* = enum passCmd1, # first pass over the command line passCmd2, # second pass over the command line passPP # preprocessor called processCommand() const HelpMessage = "Nim Compiler Version $1 [$2: $3]\n" & "Compiled at $4\n" & "Copyright (c) 2006-" & copyrightYear & " by Andreas Rumpf\n" const Usage = slurp"../doc/basicopt.txt".replace("//", "") FeatureDesc = block: var x = "" for f in low(Feature)..high(Feature): if x.len > 0: x.add "|" x.add $f x AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") % FeatureDesc proc getCommandLineDesc(conf: ConfigRef): string = result = (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name, CPU[conf.target.hostCPU].name, CompileDate]) & Usage proc helpOnError(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(conf, getCommandLineDesc(conf), {msgStdout}) msgQuit(0) proc writeAdvancedUsage(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(conf, (HelpMessage % [VersionAsString, platform.OS[conf.target.hostOS].name, CPU[conf.target.hostCPU].name, CompileDate]) & AdvancedUsage, {msgStdout}) msgQuit(0) proc writeFullhelp(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(conf, `%`(HelpMessage, [VersionAsString, platform.OS[conf.target.hostOS].name, CPU[conf.target.hostCPU].name, CompileDate]) & Usage & AdvancedUsage, {msgStdout}) msgQuit(0) proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: msgWriteln(conf, `%`(HelpMessage, [VersionAsString, platform.OS[conf.target.hostOS].name, CPU[conf.target.hostCPU].name, CompileDate]), {msgStdout}) const gitHash = gorge("git log -n 1 --format=%H").strip when gitHash.len == 40: msgWriteln(conf, "git hash: " & gitHash, {msgStdout}) msgWriteln(conf, "active boot switches:" & usedRelease & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC, {msgStdout}) msgQuit(0) proc writeCommandLineUsage*(conf: ConfigRef; helpWritten: var bool) = if not helpWritten: msgWriteln(conf, getCommandLineDesc(conf), {msgStdout}) helpWritten = true proc addPrefix(switch: string): string = if len(switch) == 1: result = "-" & switch else: result = "--" & switch const errInvalidCmdLineOption = "invalid command line option: '$1'" errOnOrOffExpectedButXFound = "'on' or 'off' expected, but '$1' found" errOnOffOrListExpectedButXFound = "'on', 'off' or 'list' expected, but '$1' found" proc invalidCmdLineOption(conf: ConfigRef; pass: TCmdLinePass, switch: string, info: TLineInfo) = if switch == " ": localError(conf, info, errInvalidCmdLineOption % "-") else: localError(conf, info, errInvalidCmdLineOption % addPrefix(switch)) proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TCmdLinePass, info: TLineInfo) = cmd = "" var i = 0 if i < len(switch) and switch[i] == '-': inc(i) if i < len(switch) and switch[i] == '-': inc(i) while i < len(switch): case switch[i] of 'a'..'z', 'A'..'Z', '0'..'9', '_', '.': add(cmd, switch[i]) else: break inc(i) if i >= len(switch): arg = "" # cmd:arg => (cmd,arg) elif switch[i] in {':', '='}: arg = substr(switch, i + 1) # cmd[sub]:rest => (cmd,[sub]:rest) elif switch[i] == '[': arg = substr(switch, i) else: invalidCmdLineOption(conf, pass, switch, info) proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass, info: TLineInfo) = case arg.normalize of "on": conf.options = conf.optio
discard """
file: "tstringinterp.nim"
output: "Hello Alice, 64 | Hello Bob, 10$"
"""
import macros, parseutils, strutils
proc concat(strings: varargs[string]): string =
result = newString(0)
for s in items(strings): result.add(s)
template processInterpolations(e) =
var s = e[1].strVal
for f in interpolatedFragments(s):
case f.kind
of ikStr: addString(f.value)
of ikDollar: addDollar()
of ikVar, ikExpr: addExpr(newCall("$", parseExpr(f.value)))
macro formatStyleInterpolation(e: untyped): untyped =
let e = callsite()
var
formatString = ""
arrayNode = newNimNode(nnkBracket)
idx = 1
proc addString(s: string) =
formatString.add(s)
proc addExpr(e: NimNode) =
arrayNode.add(e)
formatString.add("$" & $(idx))
inc idx
proc addDollar() =
formatString.add("$$")
processInterpolations(e)
result = parseExpr("\"x\" % [y]")
result[1].strVal = formatString
result[2] = arrayNode
macro concatStyleInterpolation(e: untyped): untyped =
let e = callsite()
var args: seq[NimNode]
newSeq(args, 0)
proc addString(s: string) = args.add(newStrLitNode(s))
proc addExpr(e: NimNode) = args.add(e)
proc addDollar() = args.add(newStrLitNode"$")
processInterpolations(e)
result = newCall("concat", args)
###
proc sum(a, b, c: int): int =
return (a + b + c)
var
alice = "Alice"
bob = "Bob"
a = 10
b = 20
c = 34
var
s1 = concatStyleInterpolation"Hello ${alice}, ${sum(a, b, c)}"
s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}$$"
write(stdout, s1 & " | " & s2)