=head1 use types;
YAPC::EU 2011
B<rurban> - Reini Urban <br>
C<vienna.pm> => C<houston.pm>
=head1 Goal
<br><br>
Provide type semantics to enable more compile-time
optimizations, to make Perl and compiled Perl smaller and faster.
=head1 Outline
=over
=item Status Quo: CORE types
C<< my TYPE $i; my My::Class $o; >> # Declaration only <br>
package TYPE must exist
=item Optimizations planned for 5.16 - 5.18
smaller and faster, ensured at compile-time:<br>
faster method calls, fix types, declarations via class and attributes,
typed arrays + hashes, perfect hashes.
=item Artur Bergman's B<types> module
Declare and check type safety. int, double, number, string.
params and return values.
=back
=head1 About me
<img src=pix/austria-shitty-little-country.jpg>
=head1 About me
Architect. Mainly LISP for several years. Perl as better build system.
B<rurban> maintains B<cygwin perl> since 5.8.8
and some modules: illguts, B<B::*> => 5.10,
mainly the "compiler".
No perl dayjob, just for fun. Until now.
In the future a B<lot> more time for the compiler and CORE.
Left B<AVL> (I<automotive industry>), went to B<cPanel> to
improve the compiler.
=head1 Perl's Type System
=begin perl
my int $var; # or our
# my :attribs are not known at compile-time, only our.
$ perl -cw -e 'package int; package main; our int $i:const;'
Invalid SCALAR attribute: const at -e line 1
$ perl -cw -e 'package int; package main; my int $i:const;'
-e syntax OK
=end perl
FETCH_SCALAR_ATTRIBUTES => New B<CHECK_SCALAR_ATTRIBUTES> callback for C<my>.
=head1 Perl's Type System
Yes, the language already has one. CORE:
=begin perl
my TYPE $var;
sub name (proto) {} => proto: &name->pv
=end perl
Only a few out-of-CORE implementations: <br>
Moose, fields, <strike>types, typesafety</strike>, Lexical::Types,
Attribute::Types I<(run-time)>
B<Params>: C<Devel::Declare>, C<Params::Validate>, C<Params::Classify> <br>
B<Objects>: C<Class::Meta>, C<Moose>
=head1 Prototypes
No standard prototype language, no CPAN prototype parser!
=begin perl
# types 0.x
sub foo (int $foo) { my ($foo) = @_ } # return type implicit.
#No optree injection as in Devel::Declare
# typesafety
sub foo (int; int, undef) # returns int
# types 1.0
sub foo (int $i => int) { return 2 * $i } # return type explicit
=end perl
=head1 Prototypes
No standard prototype language, no CPAN prototype parser!
=begin perl
# Devel::Declare, Method::Signatures
method hello (Str :$who, Int :$age where { $_ > 0 }) {
$self->say("Hello ${who}, I am ${age} years old!");
}
# Moose
has 'accessor' => (isa => Int, is => 'rw', default => 1);
=end perl
=head1 Perl's Type System
At first a look at CORE types, not the language:
B<SCALAR> (non-strict, VB-like): IV, NV, UV, PV, ...
B<ARRAY> (non-strict): AV
B<HASH> (non-strict): HV
B<Objects> ("stashes", @ISA, declaration)
=head1 Perl's Type System - SCALAR
B<SCALAR> (non-strict, VB-like)
multiple types (IV,NV,PV) per variable, context dependent.
internally upgraded: IV => PVIV => PVNV
=head1 Perl's Type System - SCALAR
B<SCALAR> (non-strict, VB-like)
multiple types (IV,NV,PV) per variable, context dependent.
IV: integer
<img src=pix/sviv-14.png height=204px width=278px>
=head1 Perl's Type System - SCALAR
B<SCALAR> (non-strict, VB-like)
multiple types (IV,NV,PV) per variable, context dependent.
Typed IV: integer unblessed, untied. C<my int $i;> I<~SV_SMAGIC =C<< > >> SVf_FAKE: no head>
<img src=pix/sviv-14.png height=204px width=278px> => <img src=pix/sviv-new.png height=204px width=278px>
=head1 Perl's Type System - SCALAR
B<SCALAR> (non-strict, VB-like)
multiple types (IV,NV,PV) per variable, context dependent.
internally upgraded: IV => NV
<img src=pix/svnv-14.png height=252px width=288px>
=head1 Perl's Type System - SCALAR
B<SCALAR> (non-strict, VB-like)
multiple types (IV,NV,PV) per variable, context dependent.
internally upgraded: IV => NV => PVNV
<img src=pix/svpvnv-14.png height=264px width=552px>
=head1 Perl's Type System - SCALAR
B<SCALAR> (non-strict, VB-like)
internally upgraded: IV => PVIV => PVNV => "Objects" => Tie
<img src=pix/svpvmg-14.png>
=head1 Perl's Type System - SCALAR
B<"STASH"> - Hierarchical symbol table,<br>
used as package name for Objects. i.e. I<"Class pointer">
<img src=pix/stash.png>
=head1 Perl's Type System - ARRAY
B<ARRAY> (non-strict)
Keys are integers, Values any SCALAR
=head1 Perl's Type System - ARRAY
B<ARRAY> (non-strict)
Keys are integers, Values any SCALAR
=begin perl
@a = ("any", 1, 2.5006, \&code, ['arrayref'], {hashref=>1});
=end perl
=head1 Perl's Type System - ARRAY
B<ARRAY> (non-strict)
Keys are integers, Values any SCALAR - flexible, untyped, big
=begin perl
@a = ("any", 1, 2.5006, \&code, ['arrayref'], {hashref=>1});
=end perl
<img src=pix/av-sv.png>
=head1 Typed ARRAY
B<Typed ARRAY>s (optional, faster, less space)
Keys are integers, Values of one type only (native)
=begin perl
my int @a; $#a=256; # pre-allocate: 256 * sizeof(IV)
my int @a = (1); # non-fixed size: 3 * sizeof(IV)
my int @a :const = (1); # fixed size: 1 * sizeof(IV)
=end perl
Untyped:
=begin perl
my @a; $#a=256; # pre-allocate: 256 * sizeof(SV)
=end perl
=head1 Typed ARRAY
=begin perl
my int @a;
=end perl
<img src=pix/av-typed.png>
AvTYPED && (IOK | NOK | POK)
=head1 Typed ARRAY
<p>
=begin perl
my int @a;
=end perl
Declaration already possible now!
=begin bash
perl -we'package int; package main; my int @a;'
-e syntax ok
=end bash
B<int> must be a package definition.
<small>Note: C<@a> is currently declared as C<int>, but not blessed.</small>
=head1 Perl's Type System - HASH
B<HASH> untyped: flexible, but big
Keys any SCALAR, Values any SCALAR
=begin perl
%h = ('any' => ["any", 1, 2.5006];
1 => 1,
1.005 => 2.5);
=end perl
Internally: Keys are stringified.
=head1 Perl's Type System - HASH
B<HASH> untyped: flexible<br>
Keys any SCALAR, Values any SCALAR
<img src=pix/hv-sv.png>
=head1 Typed HASH
B<HASH> typed: fast, small
Keys STRING only, Values typed
=begin perl
my string %h; $h{'x'} = 'string';
my int %h; $h{'x'} = 1;
my double %h; $h{'x'} = 1.0;
=end perl
=head1 Typed HASH
B<HASH> typed: directer access, small <br>
Keys STRING only, Values typed
<img src=pix/hv-typed.png>
=head1 Typed HASH
B<HASH> typed: fast, small
Keys STRING only, Values are typed.
=begin perl
my int %h; $h{'any'} = 1;
$h{2} = 1;
=> Wrong type: hash key no string
$h{'2'} = '1';
=> Wrong type: hash value no int
=end perl
=head1 Perfect HASH
Perfect hashes - I<guaranteed O(1) lookup, dynamic hash function generation, no collisions><br>
Library B<cmph> BDZ algorithm (I<"RAM hashing">)
=over
=item C<my %h :const;> => untyped perfect hash of unknown size<br>
=item C<my %h :perfect;> => writable perfect hash
=item C<study %h>; => optimize lookup function to perfect hash.
=back
study untyped hash => copies the old perl hash (HV)
to new perfect hash (PH).
=head1 Perfect HASH
Perfect hash. Should be typed to optimize implementation.
=begin perl
my int %h :const = ('my' => 1, 'your' => 2);
=end perl
C<:const> hashes are always C<:perfect><br>
No need to study with :const and init on declaration.
=begin perl
my %h :const = ('my' => 1, 'your' => 2);
# untyped: value = SV
=end perl
=head1 Perfect HASH Idioms
- Avoid copy from perl hash to perfect hash.
=begin perl
my int %h :perfect;
$h{$_}=1 for @h;
study %h;
=end perl
=head1 Perfect HASH Idioms
- Declare size in advance.
=begin perl
my int %h :perfect;
length %h = length @h; # not legal yet, but should be
$h{$_}=1 for @h;
study %h;
=end perl
=head1 Perfect HASH Idioms
- :const hash with computed key => values, without study
Idea 1
=begin perl
my int %h :const;
length %h = length @keys; # not legal yet, but should be
$h{$_} = $i++ for @keys;
=end perl
Init until length is filled
=head1 Perfect HASH Idioms
- :const hash with computed key => values, without study
Idea 2
=begin perl
my int %h :const = map { $h{$_} => $i++} @keys;
=>
my int %h :const;
{ $h{$_} = $i++ for @keys; }
=end perl
Initialization on next expression, usually a block.
=head1 Perl's Type System - OBJECTS
B<OBJECTS>: typed, but dynamic
run-time changable, mostly no compile-time optimizations possible.
Features: STASH ("class hash"), @ISA (mro), DESTROY
=head1 Perl's Type System - OBJECTS
B<OBJECTS>: typed, but dynamic.
Class by STASH, Inheritance by @ISA (mro), magic DESTROY and CLONE methods.
Four method calls possible:
=over
=item Class->method()
=item $object->method()
=item Class->$method()
=item $object->$method()
=back
=head1 Compilation of a function
=begin perl
Class::sub(ARGS...)
=end perl
pushmark <br>
ARGS... <br>
gv => GV *Class::sub <br>
entersub
Class->method() <br>
$object->method() <br>
Class->$method() <br>
$object->$method()
=head1 Compilation of a static method call
Class::sub() <br>
=begin perl
Class->method(ARGS...)
=end perl
pushmark <br>
const => PV "Class" <br>
ARGS... <br>
method_named => PV "method" <br>
entersub
$object->method() <br>
Class->$method() <br>
$object->$method()
=head1 Compilation of a method call
=begin perl
$object->method(ARGS...)
=end perl
pushmark <br>
padsv => GV *object <br>
ARGS... <br>
method_named => PV "method" <br>
entersub
=head1 Compilation of a method call
=begin perl
Class->$method(ARGS...)
=end perl
pushmark <br>
const => PV "Class" <br>
ARGS... <br>
method => GV *method <br>
entersub
=head1 Compilation of a method call
=begin perl
$object->$method(ARGS...)
=end perl
pushmark <br>
padsv => GV *object <br>
ARGS... <br>
method => GV *method <br>
entersub
=head1 Optimization of a static method call
=begin perl
Class->method()
=end perl
pushmark <br>
const => PV "Class" <br>
ARGS... <br>
method_named => PV "method" <br>
entersub <br>
=> <br>
pushmark <br>
const => PV "Class" <br>
ARGS... <br>
gv => GV *Class::method <br>
entersub
=head1 Optimization of a static method call
=begin perl
Class->method(...) => &Class::method('Class', ...)
if defined &Class::method
=end perl
or C<package Class> B<:locked> or in Moose immutable.<br>
i.e. not changed at run-time.
=E<gt> 4% faster method calls.
Note: C<@Class::ISA> B<:const> = C<qw(bla);> does not help.
=head1 Optimization of other method calls
B<Dynamic> method calls are possible to optimize in a similar way,
if the object is B<declared> - known class at compile-time.
=begin perl
my My::Class $object = My::Class->new;
$object->call();
my My::Class $object = My::ParentClass->new;
bless $object, 'My::Class';
$object->call();
=end perl
Inherited methods are optimizable if all classes in path to the
final class are B<:locked>, resp. B<immutable>.
=head1 Summary so far
All this is possible now, without changing the language.
Just optimized implementations are missing.
I heard that in July 2011 Moose methods of immutable classes are
going to be inlined, but what I saw so far it's not using
optree changes like these to speed it up.
=head1 More optimizations
More compile-time optimizations.
B<:const> for variables
B<:locked> for packages: const C<@ISA>, no run-time created methods.
=head1 use types;
B<types> is Artur Bergman's compile-time checking attempt from 2002,
after the B<compiler>, B<B::Generate> and B<optimize>.
And before B<optimizer>, which uses B<types> to improve the optree.
=head1 use types;
B<types> does compile-time type-checking only.
compile-time type-optimizations in B<optimizer>.
Problem: B<slower>, not faster.
=head1 use types;
The idea is to make programs with C<use types;>
B<faster>, not slower.
And define basic scalar types from CORE
C<< int >>, C<< double >> and C<< string >>
=head1 B::CC
The same types and declarations are used in B::CC also
to optimize types even further.
=head1 B::CC - optimizing perl compiler
B::CC also needs a syntax to optionally declare simple types:
B<int> and B<double> (strict)
So far it was done by magic variable name suffices: C<$a_i>, C<$n_d>;
faster, B<much> faster
=head1 B::CC - User Type declarations
Strict types as class, and optional type hints as attributes.
=begin perl
my int $foo :const;
=end perl
With C<use types> you get B<type-declarations>, <br>
partial B<type-safety>, and <br>
B<type optimizations> at compile-time.
=head1 SUMMARY
=begin perl
my double $foo = "string"; #compile-time error
sub foo (int $foo) { my ($foo) = @_ };
foo("hi"); #compile-time Type mismatch error
my int $int;
sub foo { my double $foo; return $foo }
$int = $foo; # compile-time Type mismatch error
my int @array = (0..10); # optimized internal representation
$array[2] = 2; # no SV, just the raw int at slot 2.
=end perl
=head1 SUMMARY
=begin perl
my int @array :const = (0..10);
# even more optimized internal representation
$array[2] = 2; # int @array is readonly
$array[2] = '2'; # compile-time const error
my string %stash :perfect =
(foo => 'str1', bar => 'str2'); # perfect hash (stashes)
; # more init...
study %stash; # initialization finished
print $stash{foo}; # faster lookup O(1)
$stash{new} = 1; # compile-time Type mismatch error
=end perl
=head1 SUMMARY
=begin perl
my int $i :double; # declares a IV with SVf_NOK.
my $i:int:double; # same but without type-check
my int $i; # declares an IV.
my $i:int; # same but without type-check
my int $i :string; # declares a PVIV.
my int @array :unsigned = (0..4);
# Will be used as c var in faster arithmetic and cmp.
# Will use no SV value slot, just the direct value.
my string %hash :const = (foo => 'any', bar => 'any');
# declare string keys only
# generate as read-only perfect hash.
=end perl
=head1 Questions?
=head1 Questions?
L<http://blogs.perl.org/users/rurban/2011/02/use-types.html>
=cut
rurban - Vienna, Houston, 2011-06-17
__END__
Local Variables:
fill-column:65
End: