3

And what is it, if it isn't?

Everything I've read about TCL states that everything is just a string in it. There can be some other types and structures inside of an interpreter (for performance), but at TCL language level everything must behave just like a string. Or am I wrong?

I'm using an IDE for FPGA programming called Vivado. TCL automation is actively used there. (TCL version is still 8.5, if it helps) Vivado's TCL scripts rely on some kind of "object oriented" system. Web search doesn't show any traces of this system elsewhere. In this system objects are usually obtained from internal database with "get_*" commands. I can manipulate properties of these objects with commands like get_property, set_property, report_property, etc. But these objects seem to be something more than just a string. I'll try to illustrate:

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

But:

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

So, my question is: what exactly is this "valid first class Tcl object"?

Clarification: This question might seem like asking for help with Vivado scripting, but it is not. (I was even in doubt about adding [vivado] to tags.) I can just live and script with these mystic objects. But it would be quite useful (for me, and maybe for others) to better understand their inner workings. Is this "object system" a dirty hack? Or is it a perfectly valid TCL usage? If it's valid, where can I read about it? If it is a hack, how is it (or can it be) implemented? Where exactly does string end and object starts?

Related: A part of this answer can be considered as an opinion in favor of the "hack" version, but it is quite shallow in a sense of my question.

Anatol
  • 45
  • 6
  • Everything in Tcl is an object which by default contains a string but the object can have an internal representation which is basically just a pointer to a specific memory allocation for a known "type". You can think of it as a string to keep things simple, internally there is a specific object representation (a pointer) and a string representation. – MoDJ Nov 28 '18 at 21:05

2 Answers2

1

A first class Tcl value is a sequence of characters, where those characters are drawn from the Basic Multilingual Plane of the Unicode specification. (We're going to relax that BMP restriction in a future version, but that's not yet in a version we'd recommend for use.) All other values are logically considered to be subtypes of that. For example, binary strings have the characters come from the range [U+000000, U+0000FF], and integers are ASCII digit sequences possibly preceded by a small number of prefixes (e.g., - for a negative number).

In terms of implementation, there's more going on. For example, integers are usually implemented using 64-bit binary values in the endianness that your system uses (but can be expanded to bignums when required) inside a value boxing mechanism, and the string version of the value is generated on demand and cached while the integer value doesn't change. Floating point numbers are IEEE double-precision floats. Lists are internally implemented as an array of values (with smartness for handling allocation). Dictionaries are hash tables with linked lists hanging off each of the hash buckets. And so on. THESE ARE ALL IMPLEMENTATION DETAILS! As a programmer, you can and should typically ignore them totally. What you need to know is that if two values are the same, they will have the same string, and if they have the same string, they are the same in the other interpretation. (Values with different strings can also be equal for other reasons: for example, 0xFF is numerically equal to 255 — hex vs decimal — but they are not string equal. Tcl's true natural equality is string equality.)

True mutable entities are typically represented as named objects: only the name is a Tcl value. This is how Tcl's procedures, classes, I/O system, etc. all work. You can invoke operations on them, but you can only see inside to a limited extent.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • 1
    To follow up on what Donal's answer started: `get_bd_cells` takes as its argument a cell path and returns a cell handle as a named object. The name of this handle object is a Tcl value with a string representation that matches the cell path (`/vcu_0`). But this name (Tcl value) is not the cell object, this is stored internally. So without requesting the handle using `get_bd_cells`, a Tcl value `/vcu_0` just represents this literal string, there is no name binding to a cell object. – mrcalvin Nov 28 '18 at 16:50
  • Side note: The pure-value equivalent of a procedure is a lambda term. See the docs for [`apply`](http://www.tcl-lang.org/man/tcl8.6/TclCmd/apply.htm) for how that works; they currently need that `apply` command to use. – Donal Fellows Nov 29 '18 at 09:41
  • Thanks for the strict and detailed answer! To verify that I understood correctly: If `string equal $vcu {/vcu_0}` gives `1`, but `*_property` commands behave differently on `$vcu` and `{/vcu_0}`, the implementation of these commands is not completely correct (for whatever reason: bug, performance chase or else)? As this contradicts to "if they have the same string, they are the same in the other interpretation", and hence this is an abstraction leak. – Anatol Nov 30 '18 at 04:41
  • As for your "Side note" - I can't really follow the thought. I understand lambdas in general and what does `apply` do, but can't figure out how it can help here, and who are those "they" who need to use it. – Anatol Nov 30 '18 at 04:47
1

Vivado TCL is not TCL. Vivado will not really document their language they call TCL, but refer you to the real TCL language documentation. Where Vivado TCL and TCL differ, you are left on your own without help. TCL was a poor choice for a scripting language given the very large data bases, so they had to bastardize it to get it half functional. You are better off getting help on the Xilinx forums then in general TCL forums. Why they went with TCL rather than python is beyond anyone's comprehension.