如何使 proc 可用编译时间和 运行 时间

how to make a proc available compile time and run time

我有一个 nim proc,它根据空格缩进多行字符串 第一个缩进行:

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
        """

它很好地输出:

cat:
  - meow
  - purr

dog:
  - bark
  - drool

但是检查中间 C 代码,我看到:

STRING_LITERAL(TM_9amIjLnWbK7OR9aPA8dicbaQ_14, "        cat:2          - meow2          - purr2        2       "
" dog:2          - bark2          - drool2        ", 112);

因此在 运行 时完成了缩进。我可以将 compileTime pragma 添加到 proc:

proc dedent(s: string): string
    {.noSideEffect,compileTime.} =

然后 C 输出变为:

STRING_LITERAL(TM_9amIjLnWbK7OR9aPA8dicbaQ_3, "cat:2  - meow2  - purr22dog:2  - bark2  - drool2", 48);

这正是我想要的,每行周围缩进的多行字符串,但在可执行文件中没有额外的缩进。

但是添加那个 pragma,我无法再在 运行 时访问 dedent,例如添加时:

    import os
    if paramCount() > 0:
        for i in 1..paramCount():
            echo dedent paramStr(i)

isMainModule,你得到错误:

Error: request to generate code for .compileTime proc: dedent

我查看了 strutils.nimsplitLines 的源代码,看看是否有其他一些我可以应用的编译指示,但我没有找到任何有用的东西。

我现在关于 static 语句,但更希望编译器在编译时优化它,而我不必将其添加进去。

如何在不恢复使用 static 的情况下使它在编译时和 运行 时都起作用? 我需要从单独的 .nim 模块编译 proc 吗?或者是否有我缺少的编译器选项、pragma 或其他东西?

您需要将 --implicitStatic:on 标志传递给 Nim 编译器以启用程序的隐式编译时评估。

这些过程不能compileTime pragma。

要在编译时强制计算任何表达式,您可以按以下方式使用 static

when isMainModule:
    echo static(dedent"""
        cat:
          - meow
          - purr

        dog:
          - bark
          - drool
        """)

分配给常量的所有表达式也在编译时求值,因此这是实现相同目的的另一种方法。