I have a nim proc that dedents a multiline string based on the whitespace of the first indented line:
import strutils
proc dedent(s: string): string
{.noSideEffect.} =
var prefix = ""
for line in s.splitLines(keepEol=true):
if prefix == "" and line.len > 0:
for j in 0..<line.len:
if line[j] != ' ':
prefix = line[0..j-1]
break
if line.startsWith(prefix):
result.add(line[prefix.len .. high(line)])
else:
result.add(line)
when isMainModule:
echo dedent """
cat:
- meow
- purr
dog:
- bark
- drool
"""
it nicely outputs:
cat:
- meow
- purr
dog:
- bark
- drool
but inspecting the intermediate C code, I see:
STRING_LITERAL(TM_9amIjLnWbK7OR9aPA8dicbaQ_14, " cat:\012 - meow\012 - purr\012 \012 "
" dog:\012 - bark\012 - drool\012 ", 112);
so the dedenting is done at run-time. I can add the compileTime
pragma to the proc:
proc dedent(s: string): string
{.noSideEffect,compileTime.} =
and then the C output changes to:
STRING_LITERAL(TM_9amIjLnWbK7OR9aPA8dicbaQ_3, "cat:\012 - meow\012 - purr\012\012dog:\012 - bark\012 - drool\012", 48);
Which is exactly what I want, multi-line strings that are indented to their surrounding on every line, but don't have that extra indentation in the executable.
But adding that pragma, I can no longer access dedent
at run-time, e.g. when adding:
import os
if paramCount() > 0:
for i in 1..paramCount():
echo dedent paramStr(i)
to isMainModule
, you get the error:
Error: request to generate code for .compileTime proc: dedent
I looked at the source for splitLines
in strutils.nim
to see if there was some other pragma that I could apply, but I did not find anything that would work.
I now about the static
statement, but would prefer that the compiler optimises this at compile time without me having to sprinkle this in.
How can I get this to work both compile-time as well as run-time without reverting to the use of static
?
Do I need to compile the proc from a seperate .nim
module? Or is there a compiler option, pragma, something else, that I am missing?