Why TCL for Enovia?
- We use TCL (Tool Command Language) because it is embedded into MQL (Matrix Query Language), the database access language for Enovia.
- The original server-side tools, "Business" and "Matrix", for Matrix One were written in Tcl/Tk, where Tk is the original GUI interface used with TCL.
- Our emphasis with TCL is on getting and manipulating data from MQL and generating MQL scripts that we can inspect for correctness and run from the MQL command line.
TCL is based on Lines with commands and arguments
The command is on the left and individual arguments are to the right. An argument can be the result of a substitution or be a literal. A comment starts with "#".
# this is a comment because there is a pound sign to the left # a command name starts with a letter or underscore "_" smile "because" "you" "won" 1000000 dollars
"smile" would be the command and each argument would be passed to that command. String literals do not require quotes, so "because" and "dollars" would both be strings.
Basic TCL Commands: set
The simplest command in TCL is "set", which performs assignment.
set my_variable value
set my_variable "value"
set my_variable {value}
All of these "set" commands perform the same action. The contents of "my_variable" become the string "value".To retrieve the contents, you use a dollar sign ($) before the variable name. It is called substitution where the
Basic Syntax: Curly Brackets {} and Square Brackets []
Curly brackets are containers for strings but without the substitution you get from the dollar sign ($).
set my_variable {$value}
Now the contents of "my_variable" is the string "$value".
The square bracket [] enables the result of a command to be substituted into the line:
set some_variable [cmd_with_result arg1 arg2 argN]
Now some_variable has the value of the result of the cmd_with_result.
Understanding TCL Substitution: The Importance of Evaluation
[cite_start]Before a command is executed, TCL performs a crucial step called substitution. [cite: 1] [cite_start]This is where TCL replaces certain constructs with their actual values. [cite: 2] [cite_start]Understanding substitution is key to mastering TCL syntax. [cite: 2] [cite_start]The main types of substitution are: [cite: 3]
Variable Substitution:
[cite_start]When TCL encounters a dollar sign ($) followed by a variable name (e.g., $my_variable), it replaces that entire construct with the value stored in my_variable. [cite: 3]
set greeting "Hello" [cite_start]puts $greeting ;# 'puts' is a command to print output. [cite: 4]
[cite_start]This will print "Hello"[cite: 5].
Command Substitution:
[cite_start]When TCL sees square brackets ([]), it first evaluates the command inside the brackets, and then substitutes the entire bracketed expression with the result of that command. [cite: 5]
set sum [expr 10 + 20] ;# 'expr' is a command that evaluates mathematical expressions [cite: 6] [cite_start]puts $sum ;# This will print "30" [cite: 6]
Backslash Substitution:
[cite_start]Backslashes (\) are used to escape special characters, preventing them from being interpreted by TCL in their usual way. [cite: 6] [cite_start]This allows you to include characters like spaces or dollar signs literally within a string. [cite: 7]
set message "This is a \$dollar sign" [cite_start]puts $message ;# Prints "This is a $dollar sign" [cite: 8]
Controlling Substitution with Quotes and Braces:
[cite_start]This is where your explanation of curly braces and double quotes becomes vital. [cite: 8]
-
[cite_start]
- Double Quotes (""): Allow variable and command substitution within the string. [cite: 9]
set name "Alice" puts "Hello, $name!" [cite_start];# Prints "Hello, Alice!" [cite: 9]
[cite_start] - Curly Brackets ({}): Prevent any form of substitution. [cite: 10] [cite_start]The content inside is treated as a literal string. [cite: 10] [cite_start]This is why they are essential for code blocks and literal arguments. [cite: 11]
set literal_text {This is $a_variable and [some_command]} [cite_start]puts $literal_text ;# Prints "This is $a_variable and [some_command]" literally [cite: 12]
Flow Control
Flow control statements allow your Tcl scripts to make decisions and execute different blocks of code based on certain conditions. The most fundamental flow control command is if.
The `if` Statement
The if command in Tcl evaluates an expression and executes a script block if the expression is true.
if {expression} {
# script block to execute if expression is true
}
The expression is typically a boolean expression that evaluates to true (non-zero) or false (zero). It's common practice to enclose the expression in curly braces {} to prevent variable substitution, letting the if command's internal `expr` evaluation handle it.
`if-else` and `if-elseif-else`
You can extend the if statement with else and elseif clauses for more complex conditional logic.
if {condition1} {
# script if condition1 is true
} elseif {condition2} {
# script if condition1 is false and condition2 is true
} else {
# script if all conditions are false
}
Here's a practical example:
set score 85
if {$score >= 90} {
puts "Grade: A"
} elseif {$score >= 80} {
puts "Grade: B"
} elseif {$score >= 70} {
puts "Grade: C"
} else {
puts "Grade: F"
}
In this example, the `puts` command will output "Grade: B" because 85 is less than 90 but greater than or equal to 80.
The `switch` Statement
The switch command provides a more elegant way to handle multiple conditional branches compared to a long if-elseif-else chain, especially when you are testing a single value against several possible patterns.
Basic `switch` Syntax
The basic form of the switch command takes an expression and a list of patterns and scripts.
switch {string_expression} {
pattern1 {
# script for pattern1 match
}
pattern2 {
# script for pattern2 match
}
default {
# script if no patterns match
}
}
Tcl evaluates the `string_expression` and then compares its result against each `pattern`. When a match is found, the corresponding `script` is executed. If no pattern matches, the `default` script (if provided) is executed.
Example of `switch`
set fruit "apple"
switch $fruit {
"apple" {
puts "It's an apple!"
}
"banana" {
puts "It's a banana!"
}
"orange" {
puts "It's an orange!"
}
default {
puts "Unknown fruit."
}
}
This example will output "It's an apple!".
`switch` Options
The switch command also supports various options to modify its behavior:
- `-exact` (default): Performs an exact string match.
- `-glob`: Allows glob-style pattern matching (e.g., `*`, `?`).
set color "reddish" switch -glob $color { "red*" { puts "It's red-like!" } "blue*" { puts "It's blue-like!" } default { puts "Not a primary color." } }This will print "It's red-like!".
- `-regexp`: Allows regular expression matching.
set email "test@example.com" switch -regexp $email { {^\\S+@\\S+\\.\\S+$} { puts "Valid email format." } default { puts "Invalid email format." } }This will print "Valid email format.".
- `-nocase`: Performs case-insensitive matching.
- `--`: Marks the end of options, useful if your string expression starts with a hyphen.
Looping
Looping constructs allow you to execute a block of Tcl code repeatedly. This is essential for iterating over data, performing actions a fixed number of times, or continuing until a certain condition is met.
The `while` Loop
The while command repeatedly executes a script block as long as a given expression evaluates to true (non-zero).
while {expression} {
# script block to execute repeatedly
}
It's crucial to include code within the loop that eventually makes the `expression` false to prevent an infinite loop.
set i 0
while {$i < 5} {
puts "Current count: $i"
incr i
}
This example will print "Current count: 0" through "Current count: 4". `incr` is a command that increments a variable's value.
The `for` Loop
The for command is similar to `while` but provides a more structured way to handle loops with initialization, condition checking, and an increment/decrement step.
for {initialization} {condition} {increment} {
# script block to execute
}
- `initialization`: A script executed once before the loop starts.
- `condition`: An expression evaluated before each iteration; if true, the loop continues.
- `increment`: A script executed after each iteration.
for {set i 0} {$i < 5} {incr i} {
puts "Loop iteration: $i"
}
This example will also print "Loop iteration: 0" through "Loop iteration: 4".
The `foreach` Loop
The foreach command is designed for iterating over elements in a list.
foreach varName list {
# script block to execute for each element
}
- `varName`: A variable that will take on the value of each element in the list during each iteration.
- `list`: The list of elements to iterate over.
set colors {red green blue}
foreach color $colors {
puts "Color: $color"
}
This example will print:
Color: red Color: green Color: blue
Breaking and Continuing Loops
You can control loop execution using the break and continue commands:
break: Exits the current loop entirely. Execution continues after the loop.continue: Skips the rest of the current iteration and proceeds to the next iteration (if the loop condition is still true).
for {set i 0} {$i < 10} {incr i} {
if {$i == 3} {
continue ;# Skip 3
}
if {$i == 7} {
break ;# Exit loop at 7
}
puts "Loop i: $i"
}
This example will print numbers from 0 to 6, skipping 3.
Code Examples
The simplest way to output a value is the io command "puts"
Here are some more code examples to illustrate TCL concepts:
# Example of retrieving a variable's value puts stdout $my_variable # Another example set another_var "Hello TCL" puts $another_var
If the "puts" command assumes stdout if there is not an IO channel as the first argument