Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 533 lines (376 sloc) 14.89 kb
35b909c Reini Urban add pddtypes.pod - executive summary for const and types
authored
1 =head1 SUMMARY
2
3 perl design draft - types and const
4
5 =head2 Perl already has a type system
6
7 E.g. C<my Dog $wuff>; stores the "Dog" stashname in comppad_names.
8
9 Only for lexicals (which is good and strict-safe). Almost nobody uses it.
10 There are ~5 typed modules on CPAN, Net::DNS the most prominent.
11 5.10 broke all old type modules. Moose started afresh, but naive and
12 different.
13
14 The biggest performance win would be to be able to mark packages and
15 its @ISA as B<readonly> i.e. B<const> or type objects instances to do
16 method_call compile-time optimizations. Also hash function
17 optimizations (I<perfect>), natively typed arrays and hashes,
18 more constant folding and maybe shared strings.
19
20 const package MyBase 0.01 {
21 our @ISA = ();
22 sub new { bless { @_ }, shift }
23 }
24 const package MyChild 0.01 {
25 our const @ISA = ('MyBase');
26 }
27
28 my $obj = MyChild->new;
29 => MyClass::new()
30
31 See L<perltypes/"Compile-time type optimizations">
32
33 Static compilers such as <B::C> and <B::CC> can optimize storage and
34 run-time performance furthermore. Most of the previously dynamically
35 allocated data can be made static (no parsing time, instant startup
36 time), some data can use COW.
37
38 The management win would be to actually enable strict typing rules
39 and to catch coding mistakes at compile-time.
40 See L<perltypes/"Compile-time type checks">
41
42 =head2 MOP with 5.18
43
44 With the new MOP we can mark classes as C<closed> or immutable
45 (= optimizable), and C<type> function arguments (optimizable method
46 calls + optional type checks).
47
48 package My;
49
50 class MyBase (is_closed => 1) { sub new { bless {@_}, shift } }
51 class MyDog (is_closed => 1, extends => MyBase) {
52 #sub disallowed!
53 method bark (Dog $dog) { print "bark ",ref $dog; }
54 }
55
56 =head2 const
57
d1c07ab Reini Urban pddtypes.pod: more in =head2 const
authored
58 const is added as type-qualifier to lexical declarations and to packages
59 with the feature B<'const'>, which was added with v5.18.
60
35b909c Reini Urban add pddtypes.pod - executive summary for const and types
authored
61 Declaration of C<my const> variables and packages allows compile-time
62 checks, shared strings, lexical scope instead of C<use constant>,
63 familiar syntax, and efficient optimizations, also for extensions,
64 as the L<p5-mop>, L<coretypes> or L<B::C>.
d1c07ab Reini Urban pddtypes.pod: more in =head2 const
authored
65 const packages allow compile-time optimizations of method calls.
66
67 use v5.18;
68 my const $a = 0;
69 my const @a = (0..9);
70 my const %h = ('ok' => '1',
71 'bad' => '2');
72 const package foo {
73 ...
74 }
35b909c Reini Urban add pddtypes.pod - executive summary for const and types
authored
75
76 Why not as attribute C<my $var :const>?
77
78 1. This was my first proposal. I<blogs.perl Feb 2011>
79
80 2. This attribute must also be special cased in core as my const.
81 The hard part is optree support for const pads, not the keyword.
82
83 3. Third party modules cannot use this attribute, as there is no
84 CHECK time hook for attributes yet, only at run-time. But at
85 run-time it is too late.
86
87 4. The internal implementation look both bad, I'll try both.
88 It will be easier to use for C<class>, as class declarations
89 are already overloaded with new syntax: extends, with, is,
90 is_closed, metaclass, DEMOLISH, BUILD, FINALIZE.
91 class NAME (is_closed => 1) {} currently defines an
92 immutable, constant class.
93
94 5. my const looks better and familiar
95
96 my const($a, int $b) = (0,1);
97 my (const $a, int $b) = (0,1);
98 vs:
99 my ($a:const, int $b:const) = (0,1);
100
101 =head2 p5 does NOT declare a type system
102
103 p5 only allows storing types in C<comppad_names> and does some
104 compile-time optimizations with const and methods. It only declares
105 const.
106
107 p5 does not declare a type system by itself. One must use an extension
108 which declares and handles its types. p5-mop is such a meta type system.
109
110 L<coretypes> declares the native core types int, double and string for
111 IV, NV and PV, for scalars, arrays and hashes. Not for functions yet,
112 as function parameters are handled by extensions. coretypes is
113 backwards compat.
114
115 There is no p5 super object, such as C<class> or C<object>. Maybe the
116 mop needs one, but the three coretypes do not inherit. There is no
117 C<< $var->>print >>, C<< @a->reverse >> and such planned.
118 This can be done by mixins. coretypes will be slim, p5-mop will be fat.
119 But hopefully optimizable (i.e. compile-time) in the general case.
120
121 PS: Several people at YAPC expressed their wish to make class immutable
122 to be the new default. Then there must be a syntax to allow run-time changes
123 (i.e. non-constant classes).
124 class NAME (is_closed => 0) {}
125 class NAME :mutable {}
126 or such.
127
128
129 =head2 Acceptable type upgrades with const and coretypes
130
131 const variables are not purely constant, they are different from strictly
132 typed variables.
133 const variables may be upgraded to its string or numeric representation.
134 They may be numified and/or stringified, strictly typed variables not.
135
136 my const $a = 1;
137 my const $s = "1";
138 my int $ti = 0;
139 my string $ts = "1";
140
141 print "my $a"; # valid, upgraded from IV to PVIV
142 print "my $ti"; # invalid, compile-time type violation error,
143 # the int IV cannot be stringified
144 You have to use:
145 sprintf "my %d",$ti; # or
146 print "my ",$ti;
147
148 $g = $s + 1; # valid, upgraded from PV to PVIV
149 $g = $ts + 1; # invalid numify, compile-time type violation error
150 $g = 0+$ts; # invalid numify, compile-time type violation error
151
152 =head2 const and magic @_
153
154 How about function arguments and return value constness?
155
156 Return values are always copied without keeping constness from within a function.
157
158 # valid
159 perl -MReadonly -e'sub ret { Readonly my $i => 1; $i} my $x=ret();$x+=1'
160
161 Arguments handled by reference keep constness:
162
163 # invalid
164 perl -MReadonly -e'sub get { Readonly $_[0]; } my $x=1; get($x); $x+=1;'
165 => Modification of a read-only value attempted
166
167 Arguments copied by value from @_ loose constness:
168
169 # valid
170 perl -MReadonly -e'sub get { my $x=shift; Readonly $x; } my $x=1; get($x); $x+=1;'
171 perl -MReadonly -e'sub get { my $x=shift; $x+=1; } Readonly my $x=>1; get($x);'
172
173 =head2 Declare function signatures and types (target 5.20)
174
175 perlsub has this say:
176 "Some folks would prefer full alphanumeric prototypes. Alphanumerics have been
177 intentionally left out of prototypes for the express purpose of someday in the
178 future adding named, formal parameters. The current mechanism's main goal is to let
179 module writers provide better diagnostics for module users. Larry feels the
180 notation quite understandable to Perl programmers, and that it will not intrude
181 greatly upon the meat of the module, nor make it harder to read. The line noise is
182 visually encapsulated into a small pill that's easy to swallow."
183
184 We want to optionally declare function parameter names and types and
185 the return type. There is no need to come up with new keywords like
186 fun just seperate sub prototypes from sub parameters. The simple rule
187 is: If there is a whitespace or alphanumeric sequence in the protoype,
188 it's no prototype. The general rule, esp. for single parameters: If
189 there is any non-prototype character, it's an parameter declaration
190 then.
191
192 Prototype changes the parser bindings, named function signatures
193 avoids manual @_ extraction, function types and const declarations
194 will catch type errors earlier and helps in compiler-time
195 optimizations.
196
197 sub fun ($arg1) {}
198
199 Function parameters have optional names and if so use them inside the function as such.
200 @_ is not used then externaly, ony internaly.
201
202 sub adder ($arg1, $arg2) { $arg1 + arg2 }
203
204 You are able to declare types of function parameters and return values.
205
206 int sub adder (const int $arg1, const int $arg2) { $arg1 + arg2 }
207
208 You can als use types only without names. Note that the C<;> semicolon here
209 denotes the 2nd argument as optional.
210
211 int sub adder (const int; const int) { shift + shift }
212
213 With names it is better to use the C<=> syntax for optional parameter declarations
214 and a default value.
215 You are able to declare optional parameter default values with using a name and C<=>
216 and a literal default value. Default values can be constants or variables, but no
217 function calls.
218
219 int sub adder (const int $arg1, const int $arg2=0) { $arg1 + arg2 }
220 adder(1);
221 adder(1,1);
222
223 Arguments are copied by default. To use pass by reference style as with $_[0]
224 which changes the passed value, use the ref syntax \$name
225
226 int sub adder (int \$arg1, const int $arg2=0) { $arg1 += arg2 }
227 my $i=0;
228 adder($i,1);
229 adder($i,1);
230 print $i;
231 => 2
232
d1c07ab Reini Urban pddtypes.pod: more in =head2 const
authored
233 See also L<Method::Signatures>.
35b909c Reini Urban add pddtypes.pod - executive summary for const and types
authored
234
235 =head3 Return type declarations
236
237 The parameters were straightforward, but this is now hairy, as there
238 are many competing syntax variants currently used.
239
240 At first: return types loose constness.
241
242 const int
243 sub ret_const { # => returns const int
244 ReadOnly my $foo => 1;
245 my const $myarg = shift;
246
247 $_[0] = 2; # run-time error byref
248 $foo # return a copy of a const
249 }
250
251 my const $arg = 1;
252 my $foo = ret_const($arg);
253 $foo += 1;
254
255 Pointy Variant
256 sub function (int $i -> int) {}
257 Hashy Variant
258 sub function (int $i => int) {}
259 Old Variant (use typesafety)
260 sub function (int; int $i) {}
261 Modern C-like variant
262 int sub function (int $i) {}
263
42b0094 Reini Urban pddtypes.pod: add section "Changes & existing bugs"
authored
264 =head2 Changes & existing bugs
265
c25811c Reini Urban pddtypes.pod: add [#21979][#109744] referenced constant loses readonlyne...
authored
266 =head3 [#21979] [#todo] Can't declare subroutine entry in "my"
42b0094 Reini Urban pddtypes.pod: add section "Changes & existing bugs"
authored
267
268 Multiple B<my> declarations with types are not parsed correctly.
269
270 perl -e'$i::x; my (j $a, i $b)=(1,2);'
271 => Can't declare subroutine entry in "my" at -e line 1, near ")="
272
c25811c Reini Urban pddtypes.pod: add [#21979][#109744] referenced constant loses readonlyne...
authored
273 perl -e'my (i $a)=(1);'
42b0094 Reini Urban pddtypes.pod: add section "Changes & existing bugs"
authored
274 => Can't declare subroutine entry in "my" at -e line 1, near ")="
275
276 This is a parser problem.
277 A C<my (TYPE EXPR, ...)> declaration should not be mixed with a function call,
278 i.e. subroutine entry. C<my> is a reserved keyword and cannot be the name of
279 a subroutine.
280
281 The error should be the same as with
282 perl -e'my j $a;'
283 => No such class j at -e line 1, near "my j"
284 and
285 perl -e'$i::x; my i $a;'
286 parses correctly.
287
c25811c Reini Urban pddtypes.pod: add [#21979][#109744] referenced constant loses readonlyne...
authored
288 =head3 [#21979][#109744] referenced constant loses readonlyness
42b0094 Reini Urban pddtypes.pod: add section "Changes & existing bugs"
authored
289
c25811c Reini Urban pddtypes.pod: add [#21979][#109744] referenced constant loses readonlyne...
authored
290 On a threading Perl, a list-mode refgen applied to a constant will copy the constant
291 rather than reference it, but the SVf_READONLY flag is not copied.
292 An srefgen, however, will reference it. On a non-threading Perl constness
293 is preserved.
294
295 L<http://github.com/rurban/perl/branch/typed/ro> starts with support for const
296 pads (preserve and use const-ness at compile-time).
297
298 See also L<Scalar::Construct> to create a const. This module was
299 created in response to the ticket [#109744], similar but with less features
300 than L<Readonly> or L<Const::Fast>.
42b0094 Reini Urban pddtypes.pod: add section "Changes & existing bugs"
authored
301
302
35b909c Reini Urban add pddtypes.pod - executive summary for const and types
authored
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 =head1 Private implementation notes
328
329 Please ignore
330
331 =head2 optree traversal
332
333 Generally, optree traversal to do optimizations in perl5 is forward only.
334 You do not know the previous op, even kids do not know its parents.
335 Some ops have special pointers backwards though, such as some UNOPs and BINOPs.
336 So to do a simple tree-optimization, such as
337
338 my const $i = 0;
339
340 const (IV 0)
341 padsv [$a]/CONST
342 sassign *
343
344 which is represented in the optree as
345
346 5 <2> sassign vKS*/2 ->6
347 3 <$> const(IV 0) s ->4
348 4 <0> padsv[$a:1,2] sRM*/LVINTRO,CONSTINIT ->5
349
350 you need to step forward to sassign to see that the 2nd argument
351 padsv is constant, so either in the case of
352 $i = 1; # $i being a const pad
353
354 9 <2> sassign vKS/2 ->a
355 7 <$> const(IV 1) s ->8
356 8 <0> padsv[$a:1,2] sRM* ->9
357
358 which is illegal and throws a compiler error.
359
360 Or in the case above as
361 my const $i = 0;
362 which is a valid initialization, and allows overwriting the constant $i pad.
363
364 1.
365
366 One would like to do constant folding directly at sassign, to check if the rhs of
367 the expression evaluates to a constant.
368
369 my $i = 1 + ($a << 2);
370
371 constant if $a is const, otherwise not.
372
373 If so, the rhs can be shortened to CONST. No need for various compiler passes
374 through the whole optree. I<"localize optimizations">
375
376 my $i;
377 my const $a = 2;
378 $i = 1 + ($a << 2);
379 =>
380 const(IV 2)
381 padsv [$a] /CONST
382 sassign /CONSTINIT
383 const(IV 9) <=== optimized 1 + (2 << 2)
384 padsv [$i]
385 sassign
386
387 2.
388
389 Or get rid of a const padsv initialization by sassign at all
390 if the rhs is parsed already to a constant scalar.
391
392 perl -DT -e'my const $a=0;'
393
394 0:LEX_NORMAL/XSTATE "\n;"
395 <== MY(ival=1)
396
397 1:LEX_NORMAL/XTERM "$a=0;\n"
398 <== '$'
399
400 1:LEX_NORMAL/XOPERATOR "=0;\n"
401 Pending identifier '$a'
402 <== PRIVATEREF(opval=op_padany)
403
404 1:LEX_NORMAL/XOPERATOR "=0;\n"
405 <== ASSIGNOP(ival=op_null)
406
407 1:LEX_NORMAL/XTERM "0;\n"
408 Saw number in ";\n"
409 <== THING(opval=op_const) IV(0)
410
411 1:LEX_NORMAL/XOPERATOR ";\n"
412 <== ';'
413
414 1:LEX_NORMAL/XSTATE "\n"
415 <== ';'
416
417 1:LEX_NORMAL/XSTATE ""
418 Tokener got EOF
419 <== EOF
420
421 parsed as:
422 MY $a(padany) ASSIGNOP THING const(IV 0);
423 compiled to:
424 const(IV 0)
425 padsv[$a]/CONST
426 sassign /CONSTINIT
427
428 Since padsv already knows that it will be assigned to a CONST, and that is const
429 it should store the value and the READONLY flag and omit the CONST and SASSIGN ops at all.
430
431 =head2 CONST
432
433 It would be nice to use compile my const $i=1 to
434 CONST(IV=1) instead of PADSV($i) with $i SVf_READONLY
435 to have faster access for the optimizer.
436
437 But the compiler needs to find lexical pads in the scope
438 upwards, and I'm not sure if a CONST->op_sv assumption
439 pointing to a pad is a good idea. A lexical is still a
440 lexical.
441 Every PAD*V($i) with $i SVf_READONLY should be marked as
442 op_private = OPpPAD_CONST when the PAD is created (looked up)
443 to be easier and more reliable detectable by the compiler,
444 and visible via B::Concise/Deparse.
445
446 store my const $padsv as OP_CONST with ->op_sv pointing to the pad?
447 at all, convert early or later?
448 how about pad_findlex and lexical scoping rules then?
449
450 { my const $i;
451 sub x {$i+20}
452 }
453 seems to be safe to convert early, and not waste a padsv.
454 not for padav and padhv.
455
456 How to pad_findlex a const $i if optimized to OP_CONST?
457 How about dynamic scope at run-time?
458 How about late binding CvLATE: ANON and PVFM. (delayed creation of the pad)
459 intro_my?
460
461 if so:
462 ck: save to strip off padsv and sassign
463 CONST IV=1
464
465 Nope. Better add const PADSV to the optimizers.
466 CONST wants its sv as sv.
467
468 --
469
470 my const $i=1; # simple scalar case
471
472 Lexer:
473 MY(ival=2)
474 PRIVATEREF padany
475 ASSIGNOP
476 Initialize my const $i
477 const IV 1
478 op:
479 CONST IV=1
480 PADSV OPpPAD_CONST+OPpPAD_CONSTINIT, targ -> READONLY
481 SASSIGN OPf_SPECIAL (for const init temp. overwrite)
482
483 --
484
485 my const ($i)=(1); # list case
486
487 Lexer:
488 MY(ival=2)
489 PRIVATEREF padany
490 ASSIGNOP
491 Initialize my const $i
492 const IV 1
493 op:
494 CONST IV=1
495 PADSV OPpPAD_CONST+OPpPAD_CONSTINIT, targ -> READONLY
496 SASSIGN OPf_SPECIAL (for const init temp. overwrite)
497
498 --
499
500 my const @a=(1); # PADAV
501
502 Lexer:
503 MY(ival=2)
504 PRIVATEREF padany
505 ASSIGNOP
506 Initialize my const @a
507 const IV 1
508 op:
509 pushmark
510 CONST IV=1
511 pushmark
512 PADAV OPpPAD_CONST+OPpPAD_CONSTINIT, targ -> READONLY
513 AASSIGN OPf_SPECIAL
514
515 --
516
517 my const $i;
518 ...
519 should warn: Uninitialized const $i at -e, line 1
520
521 constant folding:
522 my const $i=1; $x=$i+20;
523
524 const 1
525 padsv $i
526 sassign
527 =>
528 padsv $i const 21
529 const 20
530 add
531 gvsv gvsv
532 sassign sassign
Something went wrong with that request. Please try again.