=head1 use types; YAPC::EU 2011 B - Reini Urban
C => C =head1 Goal

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
package TYPE must exist =item Optimizations planned for 5.16 - 5.18 smaller and faster, ensured at compile-time:
faster method calls, fix types, declarations via class and attributes, typed arrays + hashes, perfect hashes. =item Artur Bergman's B module Declare and check type safety. int, double, number, string. params and return values. =back =head1 About me =head1 About me Architect. Mainly LISP for several years. Perl as better build system. B maintains B since 5.8.8 and some modules: illguts, B => 5.10, mainly the "compiler". No perl dayjob, just for fun. Until now. In the future a B more time for the compiler and CORE. Left B (I), went to B 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 callback for C. =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:
Moose, fields, types, typesafety, Lexical::Types, Attribute::Types I<(run-time)> B: C, C, C
B: C, C =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 (non-strict, VB-like): IV, NV, UV, PV, ... B (non-strict): AV B (non-strict): HV B ("stashes", @ISA, declaration) =head1 Perl's Type System - SCALAR B (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 (non-strict, VB-like) multiple types (IV,NV,PV) per variable, context dependent. IV: integer =head1 Perl's Type System - SCALAR B (non-strict, VB-like) multiple types (IV,NV,PV) per variable, context dependent. Typed IV: integer unblessed, untied. C I<~SV_SMAGIC =C<< > >> SVf_FAKE: no head> => =head1 Perl's Type System - SCALAR B (non-strict, VB-like) multiple types (IV,NV,PV) per variable, context dependent. internally upgraded: IV => NV =head1 Perl's Type System - SCALAR B (non-strict, VB-like) multiple types (IV,NV,PV) per variable, context dependent. internally upgraded: IV => NV => PVNV =head1 Perl's Type System - SCALAR B (non-strict, VB-like) internally upgraded: IV => PVIV => PVNV => "Objects" => Tie =head1 Perl's Type System - SCALAR B<"STASH"> - Hierarchical symbol table,
used as package name for Objects. i.e. I<"Class pointer"> =head1 Perl's Type System - ARRAY B (non-strict) Keys are integers, Values any SCALAR =head1 Perl's Type System - ARRAY B (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 (non-strict) Keys are integers, Values any SCALAR - flexible, untyped, big =begin perl @a = ("any", 1, 2.5006, \&code, ['arrayref'], {hashref=>1}); =end perl =head1 Typed ARRAY Bs (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 AvTYPED && (IOK | NOK | POK) =head1 Typed ARRAY

=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 must be a package definition. Note: C<@a> is currently declared as C, but not blessed. =head1 Perl's Type System - HASH B 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 untyped: flexible
Keys any SCALAR, Values any SCALAR =head1 Typed HASH B 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 typed: directer access, small
Keys STRING only, Values typed =head1 Typed HASH B 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
Library B BDZ algorithm (I<"RAM hashing">) =over =item C => untyped perfect hash of unknown size
=item C => writable perfect hash =item C; => 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>
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: 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: 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
ARGS...
gv => GV *Class::sub
entersub Class->method()
$object->method()
Class->$method()
$object->$method() =head1 Compilation of a static method call Class::sub()
=begin perl Class->method(ARGS...) =end perl pushmark
const => PV "Class"
ARGS...
method_named => PV "method"
entersub $object->method()
Class->$method()
$object->$method() =head1 Compilation of a method call =begin perl $object->method(ARGS...) =end perl pushmark
padsv => GV *object
ARGS...
method_named => PV "method"
entersub =head1 Compilation of a method call =begin perl Class->$method(ARGS...) =end perl pushmark
const => PV "Class"
ARGS...
method => GV *method
entersub =head1 Compilation of a method call =begin perl $object->$method(ARGS...) =end perl pushmark
padsv => GV *object
ARGS...
method => GV *method
entersub =head1 Optimization of a static method call =begin perl Class->method() =end perl pushmark
const => PV "Class"
ARGS...
method_named => PV "method"
entersub
=>
pushmark
const => PV "Class"
ARGS...
gv => GV *Class::method
entersub =head1 Optimization of a static method call =begin perl Class->method(...) => &Class::method('Class', ...) if defined &Class::method =end perl or C B<:locked> or in Moose immutable.
i.e. not changed at run-time. =E 4% faster method calls. Note: C<@Class::ISA> B<:const> = C does not help. =head1 Optimization of other method calls B method calls are possible to optimize in a similar way, if the object is B - 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. =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 is Artur Bergman's compile-time checking attempt from 2002, after the B, B and B. And before B, which uses B to improve the optree. =head1 use types; B does compile-time type-checking only. compile-time type-optimizations in B. Problem: B, not faster. =head1 use types; The idea is to make programs with C B, 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 and B (strict) So far it was done by magic variable name suffices: C<$a_i>, C<$n_d>; faster, B 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 you get B,
partial B, and
B 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 =cut rurban - Vienna, Houston, 2011-06-17 __END__ Local Variables: fill-column:65 End: