Proposal of syntax, expressiveness and semantic improvements with annotations

Introduction

The creation of {*} expansion prefix brought clarity to Tcl.

There is still space in the parser for this kind of annotations. But how can it be usefull for programmers ?

Let's suppose that we add a new rule to Tcl :

  • a word enclosed by braces in a prefix position to another word is called an annotation of this word.
  • These annotations can be recognized at two levels :
    • in a generic way, at the top-level parser, as a 'generic annotation'
    • in a specific way, inside a command parser, as a 'specific annotation'

Generic anotations :

These generic annotations should be recognized by the parser and result in immediate actions from it.

  • {*}$list : actual expansion prefix
  • {=}$expr : new expression prefix : next word is to be computed as an expression
  • {&}$ref : new reference prefix : next word is to be captured as a reference to the value
  • {#}comment : new comment prefix : next word is to be skiped by the parser
  • {:}Label : new label prefix : next word is to be recorded as a location in the script

Specific annotation

These annotations should be recognized by the parser, and result in an annotation token, whose prefixed word is a subsequent component. The future substitution of this kind of Token will result in the object of suffix word linked to the annotation object.

As their effect will be specific to the command that recieved them, we can't gives generic rules on their effect. But we can distinguish some appetitive features for the main Tcl entity :

  • constraint the type of a variable : why ? The Type theory has nowedays a number of applications, for instance in mathematics (see Coq ). Programmers needs to model a reality and that commonly comes with some typologies or taxonomies. So There is a need for it.

Usage of annotations on variable

  • constraint the type :
 set {Person}P ... {#}{P is a person}

the SetObjCmd proc will recieved an annoted object as 1st argument. But what will it do with it ?

There should be somewhere a previous definition of what is a person :

define Person {
   {string}LastName
   {string}FirstName
   {index}id
}

The SetObjCmd will look at the definition of Person and see that this specific type defines some fields :

  • Lastname as a string
  • firstname as a string
  • id as an index

Let's say the index type denotes an auto-incremented integer

Now the SetObjCmd knows, that, along the definition of this this type, the variable contains two fields, so he knows what to do with this variable. We can write :

set {Personne}P {LastName}OUSTERHOUT {FirstName}John

The annotation of the objects arguments give the name of the field, with the help of a function : Tcl_GetAnnotationFromObj()

For generic types, we would write directly :

set {list}L 1 2 3 4 5 6 {#}{it's a list !}
set {dict}D k1 v1 k2 v2 {#}{it's a dict !}

I would like also to be allowed to "compose" type annotations. For instance, i'd like to specify list of lists or list of dicts or dict of lists or dict of dicts. Maybe it could be done in annotating the annotation.

set {{list}list}LL [list A B C] [list E F G]
set {{dict}list}DL key1 [list A B C] key2 [list E F G]
set {{list}dict}LD {dict}{k00 v00 k01 v01} {dict}{k10 v10 k11 v11}
set {{dict}dict}DD k1 {dict}{k00 v00 k01 v01} k2 {dict}{k10 v10 k11 v11}

I would like also to constraint the length of the list, or to specify the keys of a dict.

define vect {
     {{list[3]}number}Vi
} 
set {vect}V 1 2 3
define Personne {
     {dict[{string}Last,{string}First]}Name
     {dict[{dict[work,home]}mail, {dict[work,home]}tel]}Contact
}
set {Personne}P \
   {Name}{
       {Last}OUSTERHOUT 
       {First}John
   } {Contact}{
       {mail}{
            {work}{[email protected]} 
            {home}{[email protected]}
       } {tel}{
            {work}{1232343}
            {home}{3676333}
       }
   }
  • Unifying dict and lists access

let's define data of a Person P

set P {dict}{
        Phone {dict}{Home 45644 Work 435841 Mobile 48344}
        Mail {dict}{Personal {list}{[email protected] [email protected]} work [email protected]}
}

As there is no ambiguities on the type of the values, we can write :

set P(Phone(Home)) {#}{returns Home Phone number : 45644}
set P(Mail(Personal(end))) {#}{returns the last element of Personal's Mail : [email protected]}

Usage of annotation in proc

an arg prefix with an {&} annotation could be sean as a reference, aka :

proc SET {{&}var args} {
    set var $args
}

# Should be equivalent to :

proc SET {varname args} {
    upvar #0 $varname var
    set var $args
}

Illustrations

generic annotation

References

Let'say we have a team of n peoples

# Coming from a database
set P1 {Person}{{Nom}{{Last}... {First}...} {Phone}{{Work}... {Home}...}}
...
set Pi {Person}{{Nom}{{Last}... {First}...} {Phone}{{Work}... {Home}...}}
...
set Pn {Person}{{Nom}{{Last}... {First}...} {Phone}{{Work}... {Home}...}}

# We set a team of 3 members
set M1 {&}$P1
set M2 {&}$P2
set M3 {&}$P3

set {list}Team {&}$M1 {&}$M2 {&}$M3

# If we want to change a member
set M1 {&}$P4
# -> The list would be automatically updated (M1 now refer to P4)

# We want to change the phone number of someone
# Apply to someone a specified type of data
set P4 {Person{Phone{Work}}}0543876787

set {Person{Phone{Work}}}[lindex $Team 0] {#}{return the new work phone number}

Linked list

define node {
     {string}Name
     {node}next
     {node}previous
}
set {node}n0 {Name}{First Node}  
set {node}n1 {Name}{Second Node} 
set {node}n2 {Name}{Third Node} 

set {node}n0(next) {&}$n1
set {node}n1(next) {&}$n2
set {node}n2(next) {&}$n0
set {node}n1(previous) {&}$n0
set {node}n2(previous) {&}$n1
set {node}n0(previous) {&}$n2

specific annotation

...writing in progress...

Discussion

Comments Welcome