use types;

YAPC::US 2011

rurban - Reini Urban
vienna.pm, houston.pm

Outline

Who am I

rurban active in p5p since 1995.

maintains cygwin perl since 5.8.8 and 3-4 modules: illguts, B::* => 5.10, mainly the "compiler".

In the future a lot more time for the compiler and CORE.

I'm known as the BAD guy on p5p who started fighting with Nick. Sorry about that. Sometimes I'm just arrogant and stupid, but unfortunately not as funny as Matt.

Perl's Type System

Yes, the language already has one.

  my int $var# or our

  # my :attribs are not known at compile-time, only our.
  $ perl -c-e'package int; package main; our int $i:const;'
    Invalid SCALAR attribute: const at -e line 1
  $ perl -c-e'package int; package main; my int $i:const;'
    -e syntax OK

  sub name (proto) {} => proto: &name->pv

Perl's Type System

Yes, the language already has one. CORE:

  my TYPE $var;
  sub name (proto) {} => proto: &name->pv

Only a few out-of-CORE implementations:

Moose, fields, types, typesafety, Lexical::Types

Params: Devel::Declare, Params::Validate, Params::Classify
Objects: Class::Meta, Moose

Perl's Type System

At first a look CORE types, not the language:

SCALAR (non-strict, VB-like): IV, NV, UV, PV, ...

ARRAY (non-strict): AV

HASH (non-strict): HV

Objects ("stashes", @ISA, declaration)

Perl's Type System - SCALAR

SCALAR (non-strict, VB-like)

multiple types (IV,NV,PV) per variable, context dependent.

internally upgraded: IV => PVIV => PVNV

Perl's Type System - SCALAR

SCALAR (non-strict, VB-like)

multiple types (IV,NV,PV) per variable, context dependent.

IV: integer

Perl's Type System - SCALAR

SCALAR (non-strict, VB-like)

multiple types (IV,NV,PV) per variable, context dependent.

IV - integer unblessed, untied

=>

Perl's Type System - SCALAR

SCALAR (non-strict, VB-like)

multiple types (IV,NV,PV) per variable, context dependent.

internally upgraded: IV => NV

Perl's Type System - SCALAR

SCALAR (non-strict, VB-like)

multiple types (IV,NV,PV) per variable, context dependent.

internally upgraded: IV => NV => PVNV

Perl's Type System - SCALAR

SCALAR (non-strict, VB-like)

internally upgraded: IV => PVIV => PVNV => "Objects" => Tie

Perl's Type System - SCALAR

"STASH" - Hierarchical symbol table,
used as package name for Objects. i.e. "Class pointer"

Perl's Type System - ARRAY

ARRAY (non-strict)

Keys are integers, Values any SCALAR

Perl's Type System - ARRAY

ARRAY (non-strict)

Keys are integers, Values any SCALAR

@a = ("any"12.5006, \&code, ['arrayref'], {hashref=>1});

Perl's Type System - ARRAY

ARRAY (non-strict)

Keys are integers, Values any SCALAR - flexible, untyped, big

@a = ("any"12.5006, \&code, ['arrayref'], {hashref=>1});

Typed ARRAY

Typed ARRAYs (optional, faster, less space)

Keys are integers, Values of one type only (native)

  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)

Untyped:

  my @a$#a=256;         # pre-allocate: 256 * sizeof(SV)

Typed ARRAY

  my int @a;

AvTYPED && (IOK | NOK | POK)

Typed ARRAY

  my int @a;

Declaration already possible now!

  perl -we'package int; package main; my int @a;'
  -e syntax ok

int must be a package definition.

Note: @a is declared as int, but not blessed.

Perl's Type System - HASH

HASH untyped: flexible, but big

Keys any SCALAR, Values any SCALAR

  %h = ('any' => ["any"12.5006];
        1     => 1,
        1.005 => 2.5);

Internally: Keys are stringified.

Perl's Type System - HASH

HASH untyped: flexible
Keys any SCALAR, Values any SCALAR

Typed HASH

HASH typed: fast, small

Keys STRING only, Values typed

  my string %h$h{'x'} = 'string';
  my int %h;    $h{'x'} = 1;
  my double %h$h{'x'} = 1.0;

Typed HASH

HASH typed: directer access, small
Keys STRING only, Values typed

Typed HASH

HASH typed: fast, small

Keys STRING only, Values are typed.

  my int %h$h{'any'} = 1;
  
  $h{2} = 1;
    => Wrong type: hash key no string
  
  $h{'2'} = '1';
    => Wrong type: hash value no int 

Perfect HASH

Perfect hashes - guaranteed O(1) lookup, dynamic hash function generation

study untyped hash => copies the old perl hash (HV) to new perfect hash (PH).

:const hashes are always :perfect

Perfect HASH

Perfect hash. Should be typed to optimize implementation.

  my int %h :const = ('my' => 1'your' => 2);

No need to study with :const and init on declaration.

  my %h :const = ('my' => 1'your' => 2);
  # untyped: value = SV

Perfect HASH Idioms

- Avoid copy from perl hash to perfect hash.

  my int %h :perfect;
  $h{$_}=1 for @h;
  study %h;

Perfect HASH Idioms

- Declare size in advance.

  my int %h :perfect;
  length %h = length @h;         # not legal yet, but should be
  $h{$_}=1 for @h;
  study %h;

Perfect HASH Idioms

- :const hash with computed key => values, without study

Idea 1

  my int %h :const;
  length %h = length @keys;       # not legal yet, but should be
  $h{$_} = $i++ for @keys;

Init until length is filled

Perfect HASH Idioms

- :const hash with computed key => values, without study

Idea 2

  my int %h :const = map { $h{$_} => $i++}  @keys;
=>
  my int %h :const;
  { $h{$_} = $i++ for @keys; }

Initialization on next expression, usually a block.

Perl's Type System - OBJECTS

OBJECTS: typed, but dynamic

run-time changable, mostly no compile-time optimizations possible.

Features: STASH ("class hash"), @ISA (mro), DESTROY

Perl's Type System - OBJECTS

OBJECTS: typed, but dynamic.

Class by STASH, Inheritance by @ISA (mro), magic DESTROY methods.

Four method calls possible:

Compilation of a function

Class::sub(ARGS...)

pushmark
ARGS...
gv => GV *Class::sub
entersub

Class->method()
$object->method()
Class->$method()
$object->$method()

Compilation of a static method call

Class::sub()

Class->method(ARGS...)

pushmark
const => PV "Class"
ARGS...
method_named => PV "method"
entersub

$object->method()
Class->$method()
$object->$method()

Compilation of a method call

$object->method(ARGS...)

pushmark
padsv => GV *object
ARGS...
method_named => PV "method"
entersub

Compilation of a method call

Class->$method(ARGS...)

pushmark
const => PV "Class"
ARGS...
method => GV *method
entersub

Compilation of a method call

$object->$method(ARGS...)

pushmark
padsv => GV *object
ARGS...
method => GV *method
entersub

Optimization of a static method call

Class->method()

pushmark
const => PV "Class"
ARGS...
method_named => PV "method"
entersub
=>
pushmark
const => PV "Class"
ARGS...
gv => GV *Class::method
entersub

Optimization of a static method call

Class->method(...) => &Class::method('Class', ...)

if defined &Class::method

or package Class :locked

i.e. not changed at run-time.

Note: @Class::ISA :const = qw(bla); does not help.

Summary so far

All this is possible now, without changing the language.

Just optimized implementations are missing.

More optimizations

More compile-time optimizations.

:const for variables

:locked for packages: const @ISA, no run-time created methods.

use types;

types is Artur Bergman's compile-time checking attempt from 2002, after the compiler, B::Generate and optimize.

And before optimizer, which uses types to improve the optree.

use types;

types does compile-time type-checking only.

compile-time type-optimizations in optimizer.

Problem: slower, not faster.

use types;

The idea is to make programs with use types;

faster, not slower.

And define basic scalar types from CORE

int, double and string

B::CC

The same types and declarations are used in B::CC also to optimize types even further.

B::CC - optimizing perl compiler

B::CC also needs a syntax to optionally declare simple types:

int and double (strict)

So far it was done by magic variable name suffices: $a_i, $n_d;

faster, much faster

B::CC - User Type declarations

Strict types as class, and optional type hints as attributes.

  my int $foo :const;

With use types you get type-declarations,
partial type-safety, and
type optimizations at compile-time.

SUMMARY

    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 $fooreturn $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. 

SUMMARY

    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

SUMMARY

    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. 

Questions?

Questions?

http://blogs.perl.org/users/rurban/2011/02/use-types.html