use strict;
use warnings;
use experimental 'signatures';
use YAML 'Dump';

#### This is the start of the (quickly written) syntax sugar

#### Note: the BEGIN block is to set things up at compile time so I don't
#### need a separate Pulumi.pm file because this code is being written on
#### the fly to demonstrate possibilities.

BEGIN {

package Pulumi {

  $INC{'Pulumi.pm'} = __FILE__;

  package Pulumi::ThisHash {
    use base qw(Tie::Hash);
    sub TIEHASH ($class, @) {
      bless {}, $class;
    }
    sub FETCH ($self, $key) {
      return '${'.$key.'}';
    }
  }

  use Exporter 'import';

  our @EXPORT = qw(pulumi variable resource output invoke);

  {
    no feature 'signatures'; # revert to old school prototypes for block syntax
    sub pulumi (&) {
      local our $Current = {};
      local %_;
      tie %_, 'Pulumi::ThisHash';
      $_[0]->();
      $Current;
    }
  }

  foreach my $type (qw(variable output resource)) {
    eval qq!
      sub ${type} (\$name, \$value) {
        (our \$Current)->{"${type}s"}{\$name} = \$value;
      }
    !
  }

  sub invoke ($name, $args, %meta) {
    my @return = ($meta{returning} ? (Return => $meta{returning}) : ());
    +{
      Function => $name,
      Arguments => $args,
      @return,
    };
  }
}

package aws::ec2 {
  sub AUTOLOAD {
    Pulumi::invoke(our $AUTOLOAD =~ s/::/:/gr, @_);
  }
}

package eks {
  sub AUTOLOAD {
    +{
      type => our $AUTOLOAD =~ s/::/:/gr,
      properties => { @_ }
    };
  }
}

} ## end of BEGIN

#### This is the end of the (quickly written) syntax sugar)

#### And now this is the result, which produces the same output:

use Pulumi;

my $pulumi = pulumi {

  variable vpcId =>
    aws::ec2::getVpc({ default => 'true' }, returning => 'id');

  variable subnetIds =>
    aws::ec2::getSubnetIds({ vpcId => $_{vpcId} }, returning => 'ids');

  resource cluster => eks::Cluster(
    vpcId => $_{vpcId},
    subnetIds => $_{subnetIds},
    instanceType => 't2.medium',
    desiredCapacity => 2,
    minSize => 1,
    maxSize => 2,
  );

  output kubeconfig => $_{'cluster.kubeconfig'};
};

print Dump( $pulumi );
