xref: /illumos-gate/usr/src/contrib/ast/src/cmd/ksh93/TYPES (revision b30d1939)
1
2The ability for users to define types has been added to ksh93t.
3Here is a quick summary of how types are defined and used in ksh93t.
4This is still a work in progress so some changes and additions
5are likely.
6
7A type can be defined either by a shared library or by using the new
8typeset -T option to the shell.  The method for defining types via
9a shared library is not described here.  However, the source file
10bltins/enum.c is an example of a builtin that creates enumeration types.
11
12By convention, typenames begin with a capitol letter and end in _t.
13To define a type, use
14	typeset -T Type_t=(
15		definition
16	)
17where definition contains assignment commands, declaration commands,
18and function definitions.  A declaration command (for example typeset,
19readonly, and export), is a built-in that differs from other builtins in
20that tilde substitution is performed on arguments after an =, assignments
21do not have to precede the command name, and field splitting and pathname
22expansion is not performed on the arguments.
23For example,
24	typeset -T Pt_t=(
25		float -h 'length in inches' x=1
26		float -h 'width in inches' y=0
27		integer -S count=0
28		len()
29		{
30			print -r $((sqrt(_.x*_.x + _.y*_.y)))
31		}
32		set()
33		{
34			(( _.count++))
35		}
36	)
37
38defines a type Pt_t that has three variables x, y, and count defined as well
39as the discipline functions len and set.  The variable x has an initial value
40of 1 and the variable y has an initial value of 0.  The new -h option argument,
41is used for documentations purposes as described later and is ignored outside
42of a type definition.
43
44
45The variable count has the new -S attribute which means that it is shared
46between all instances of the type.  The -S option to typeset is ignored
47outside of a type definition.  Note the variable named _ that is used inside
48the function definition for len and set.  It will be a reference to the
49instance of Pt_t that invoked the function.  The functions len and set
50could also have been defined with function len and function set, but
51since there are no local variables, the len() and set() form are more
52efficient since they don't need to set up a context for local variables
53and for saving and restoring traps.
54
55If the discipline function named create is defined it will be
56invoked when creating each instance for that type. A function named
57create cannot be defined by any instance.
58
59When a type is defined, a declaration built-in command by this name
60is added to ksh.  As with other shell builtins, you can get the man page
61for this newly added command by invoking Pt_t --man.  The information from
62the -h options will be embedded in this man page.  Any functions that
63use getopts to process arguments will be cross referenced on the generated
64man page.
65
66Since Pt_t is now a declaration command it can be used in the definition
67of other types, for example
68	typeset -T Rect_t=( Pt_t ur ll)
69
70Because a type definition is a command, it can be loaded on first reference
71by putting the definition into a file that is found on FPATH.
72Thus, if this definition is in a file named Pt_t on FPATH, then
73a program can create instances of Pt_t without first including
74the definition.
75
76A type definition is readonly and cannot be unset.  Unsetting non-shared
77elements of a type restores them to their default value.  Unsetting a
78shared element has no effect.
79
80The Pt_t command is used to create an instance of Pt_t.
81	Pt_t p1
82creates an instance named p1 with the initial value for p1.x set to 1
83and the initial value of p1.y set to 0.
84	Pt_t p2=(x=3 y=4)
85creates an instance with the specified initial values.  The len function
86gives the distance of the point to the origin.  Thus, p1.len will output
871 and p2.len will output 5.
88
89ksh93t also introduces a more efficient command substitution mechanism.
90Instead of $(command), the new command substitution ${ command;}
91can be used.  Unlike (and ) which are always special, the { and } are
92reserved words and require the space after { and a newline or ; before }.
93Unlike $(), the ${ ;} command substitution executes the command in
94the current shell context saving the need to save and restore
95changes, therefore also allowing side effects.
96
97When trying to expand an element of a type, if the element does not exist,
98ksh will look for a discipline function with that name and treat this as if
99it were the ${ ;} command substitution.  Thus, ${p1.len} is equivalent to
100${ p1.len;} and within an arithmetic expression, p1.len will be expanded
101via the new command substitution method.
102
103The type of any variable can be obtained from the new prefix
104operator @.  Thus, ${@p1} will output Pt_t.
105
106By default, each instance inherits all the discipline functions defined
107by the type definition other than create.  However, each instance can define
108a function by the same name that will override this definition.
109However, only discipline functions with the same name as those defined
110by the type or the standard get, set, append, and unset disciplines
111can be defined by each instance.
112
113Each instance of the type Pt_t behaves like a compound variable except
114that only the variables defined by the type can be referenced or set.
115Thus, p2.x=9 is valid, but p2.z=9 is not.  Unless a set discipline function
116does otherwise, the value of $p1 will be expanded to the form of a compound
117variable that can be used for reinput into ksh.
118
119If the variables var1 and var2 are of the same type, then the assignment
120	var2=var1
121will create a copy of the variable var1 into var2.  This is equivalent to
122	eval var2="$var1"
123but is faster since the variable does not need to get expanded or reparsed.
124
125The type Pt_t can be referenced as if it were a variable using the name
126.sh.type.Pt_t.  To change the default point location for subsequent
127instances of Pt_t, you can do
128	.sh.type.Pt_t=(x=5 y=12)
129so that
130	Pt_t p3
131	p3.len
132would be 13.
133
134Types can be defined for simple variables as well as for compound
135objects such as Pt_t.  In this case, the variable named . inside
136the definition refers to the real value for the variable.  For example,
137the type definition
138	typeset -T Time_t=(
139		integer .=0
140		_='%H:%M:%S'
141		get()
142		{
143			.sh.value=$(printf "%(${_._})T" "#$((_))" )
144		}
145		set()
146		{
147			.sh.value=$(printf "%(%#)T" "${.sh.value}")
148
149		}
150	)
151
152The sub-variable name _ is reserved for data used by discipline functions
153and will not be included with data written with the %B option to printf.
154In this case it is used to specify a date format.
155
156In this case
157	Time_t t1 t2=now
158will define t1 as the time at the beginning of the epoch and t2
159as the current time.  Unlike the previous case, $t2 will output
160the current time in the date format specified by the value t2._.
161However, the value of ${t2.} will expand the instance to a form
162that can be used as input to the shell.
163
164Finally, types can be derived from an existing type.  If the first
165element in a type definition is named _, then the new type
166consists of all the elements and discipline functions from the
167type of _ extended by elements and discipline functions defined
168by new type definition.  For example,
169
170	typeset -T Pq_t=(
171		Pt_t _
172		float z=0.
173		len()
174		{
175			print -r $((sqrt(_.x*_.x + _.y*_.y + _.z*_.z)))
176		}
177	)
178
179defines a new type Pq_t which is based on Pq_t and contains an additional
180field z and a different len discipline function.  It is also possible
181to create a new type Pt_t based on the original Pt_t.  In this case
182the original Pt_t is no longer accessible.
183