【问题标题】:Is everything really a string in TCL?TCL 中的一切真的都是字符串吗?
【发布时间】:2018-11-28 05:04:45
【问题描述】:

如果不是,那是什么?

我读到的关于 TCL 的所有内容都表明所有内容都只是其中的一个字符串。解释器内部可能有一些其他类型和结构(出于性能考虑),但在 TCL 语言级别上,一切都必须像字符串一样表现。还是我错了?

我正在使用一个名为 Vivado 的 IDE 进行 FPGA 编程。 TCL 自动化在那里被积极使用。 (TCL版本还是8.5,如果有帮助的话) Vivado 的 TCL 脚本依赖于某种“面向对象”系统。网络搜索在其他地方没有显示该系统的任何痕迹。 在这个系统中,对象通常是使用“get_*”命令从内部数据库中获取的。我可以使用get_propertyset_propertyreport_property 等命令来操作这些对象的属性。 但这些对象似乎不仅仅是一个字符串。 我将尝试说明:

> set vcu [get_bd_cells /vcu_0]
/vcu_0
> puts "|$vcu|"
|/vcu_0|
> report_property $vcu
Property                            Type    Read-only  Value
CLASS                               string  true       bd_cell
CONFIG.AXI_DEC_BASE0                string  false      0
<...>
> report_property "$vcu"
Property                            Type    Read-only  Value
CLASS                               string  true       bd_cell
CONFIG.AXI_DEC_BASE0                string  false      0
<...>

但是:

> report_property "/vcu_0"
ERROR: [Common 17-58] '/vcu_0' is not a valid first class Tcl object.
> report_property {/vcu_0}
ERROR: [Common 17-58] '/vcu_0' is not a valid first class Tcl object.
> report_property /vcu_0
ERROR: [Common 17-58] '/vcu_0' is not a valid first class Tcl object.
> puts |$vcu|
|/vcu_0|
> report_property [string range $vcu 0 end]
ERROR: [Common 17-58] '/vcu_0' is not a valid first class Tcl object.

那么,我的问题是:这个“有效的第一类 Tcl 对象”到底是什么?

说明: 这个问题可能看起来像是在寻求有关 Vivado 脚本的帮助,但事实并非如此。 (我什至怀疑将 [vivado] 添加到标签中。) 我可以用这些神秘的物体生活和编写脚本。 但更好地了解他们的内部运作会非常有用(对我来说,也许对其他人来说)。 这个“对象系统”是一个肮脏的黑客吗?或者它是一个完全有效的 TCL 用法? 如果它是有效的,我在哪里可以阅读它? 如果它是一个 hack,它是如何(或可以)实现的?字符串结束和对象到底从哪里开始?

相关: this answer 的一部分可以被认为是支持“hack”版本的意见,但在我的问题的意义上它是相当肤浅的。

【问题讨论】:

  • Tcl 中的所有内容都是一个对象,默认情况下包含一个字符串,但该对象可以有一个内部表示,它基本上只是一个指向已知“类型”的特定内存分配的指针。你可以把它想象成一个字符串来保持简单,内部有一个特定的对象表示(一个指针)和一个字符串表示。

标签: tcl xilinx vivado


【解决方案1】:

第一类 Tcl 值是一个字符序列,其中这些字符来自 Unicode 规范的基本多语言平面。 (我们将在未来的版本中放宽 BMP 限制,但这还不是我们推荐使用的版本。)所有其他值在逻辑上都被认为是它的子类型。例如,二进制字符串的字符来自 [U+000000, U+0000FF] 范围,整数是 ASCII 数字序列,可能前面有少量前缀(例如,- 表示负数)。

实施方面,还有更多工作要做。例如,整数通常使用 64 位二进制值以您的系统使用的字节顺序(但可以在需要时扩展为 bignums)在值装箱机制中实现,并且值的字符串版本是按需生成并缓存的,而整数值不会改变。浮点数是 IEEE 双精度浮点数。列表在内部实现为一个值数组(具有处理分配的智能)。字典是散列表,链表挂在每个散列桶上。等等。 这些都是实现细节!作为程序员,您可以并且应该通常完全忽略它们。您需要知道的是,如果两个值相同,则它们将具有相同的字符串,如果它们具有相同的字符串,则在另一种解释中它们是相同的。 (具有不同字符串的值也可能由于其他原因而相等:例如,0xFF 在数值上等于 255 — 十六进制与十进制 — 但它们不是字符串相等。Tcl 真正的自然相等是字符串相等。)

真正的可变实体通常表示为命名对象:只有名称是 Tcl 值。这就是 Tcl 的过程、类、I/O 系统等所有工作的方式。您可以对它们调用操作,但您只能在有限范围内看到内部。

【讨论】:

  • 跟进 Donal 的回答开始:get_bd_cells 将单元格路径作为其参数,并将单元格句柄作为命名对象返回。此句柄对象的名称是一个 Tcl 值,其字符串表示形式与单元路径 (/vcu_0) 匹配。但是这个名称(Tcl 值)不是单元对象,它是内部存储的。因此,无需使用get_bd_cells 请求句柄,Tcl 值/vcu_0 仅表示此文字字符串,没有名称绑定到单元格对象。
  • 旁注:过程的纯值等效项是 lambda 项。请参阅apply 的文档以了解其工作原理;他们目前需要使用 apply 命令。
  • 感谢您严格而详细的回答!验证我是否理解正确:如果string equal $vcu {/vcu_0} 给出1,但*_property 命令在$vcu{/vcu_0} 上的行为不同,则这些命令的实现并不完全正确(无论出于何种原因:错误,性能追逐要不然)?由于这与“如果它们具有相同的字符串,则它们在其他解释中是相同的”相矛盾,因此这是一个抽象泄漏。
  • 至于你的“旁注”——我真的无法理解这个想法。我大致了解 lambdas 以及 apply 的作用,但不知道它在这里有何帮助,以及需要使用它的“他们”是谁。
【解决方案2】:

Vivado TCL 不是 TCL。 Vivado 不会真正记录他们称为 TCL 的语言,而是让您参考真正的 TCL 语言文档。 Vivado TCL 和 TCL 的不同之处在于,您只能靠自己,没有帮助。考虑到非常大的数据库,TCL 对于脚本语言来说是一个糟糕的选择,因此他们不得不对其进行混改以使其功能减半。您最好在 Xilinx 论坛上获得帮助,然后在一般 TCL 论坛上获得帮助。他们为什么选择 TCL 而不是 python,这超出了任何人的理解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 2021-11-04
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多