1. class CompUnit::PrecompilationId {
  2. has $.id;
  3. my $cache-lock = Lock.new;
  4. my %cache;
  5. method new(Str:D $id) {
  6. $cache-lock.protect: {
  7. %cache{$id} //= 2 < $id.chars < 64 && $id ~~ /^<[A..Za..z0..9._-]>+$/
  8. ?? self.bless(:$id)
  9. !! die "Invalid precompilation id: $id"
  10. }
  11. }
  12. method Str() { $!id }
  13. method IO() { $!id.IO }
  14. method substr(|c) { $!id.substr(|c) }
  15. }
  16. role CompUnit::PrecompilationDependency {
  17. method id(--> CompUnit::PrecompilationId:D) { ... }
  18. method src(--> Str:D) { ... }
  19. method spec(--> CompUnit::DependencySpecification:D) { ... }
  20. method checksum(--> Str:D) { ... }
  21. method Str() {
  22. "$.id $.src $.spec"
  23. }
  24. method serialize(--> Str:D) { ... }
  25. method deserialize(Str, --> CompUnit::PrecompilationDependency:D) { ... }
  26. }
  27. role CompUnit::PrecompilationUnit {
  28. method id(--> CompUnit::PrecompilationId:D) { ... }
  29. method path(--> IO::Path:D) { ... }
  30. method modified(--> Instant:D) { ... }
  31. method dependencies(--> Array[CompUnit::PrecompilationDependency]) { ... }
  32. method bytecode(--> Buf:D) { ... }
  33. method checksum(--> Str:D) { ... }
  34. method source-checksum(--> Str:D) { ... }
  35. method bytecode-handle(--> IO::Handle:D) { ... }
  36. method close(--> Nil) { ... }
  37. method is-up-to-date(CompUnit::PrecompilationDependency $dependency, Bool :$check-source --> Bool) {
  38. my $RMD = $*RAKUDO_MODULE_DEBUG;
  39. if $check-source { # a repo changed, so maybe it's a change in our source file
  40. my $source-checksum = $.source-checksum;
  41. my $srcIO = CompUnit::RepositoryRegistry.file-for-spec($dependency.src) // $dependency.src.IO;
  42. unless $srcIO {
  43. return False unless $srcIO.e;
  44. }
  45. my $current-source-checksum := nqp::sha1($srcIO.slurp(:enc<iso-8859-1>));
  46. $RMD(
  47. "$.path\nspec: $dependency.spec()\nsource: $srcIO\n"
  48. ~ "source-checksum: $source-checksum\ncurrent-source-checksum: $current-source-checksum"
  49. ) if $RMD;
  50. return False if $source-checksum ne $current-source-checksum;
  51. }
  52. $RMD("dependency checksum $dependency.checksum() unit: $.checksum()") if $RMD;
  53. $.checksum eq $dependency.checksum
  54. }
  55. }
  56. class CompUnit::PrecompilationDependency::File does CompUnit::PrecompilationDependency {
  57. has CompUnit::PrecompilationId $.id;
  58. has Str $.src;
  59. has Str $.checksum is rw;
  60. has Str $!serialized-spec;
  61. has CompUnit::DependencySpecification $.spec;
  62. method source-name() {
  63. "$.src ($.spec.short-name())"
  64. }
  65. method deserialize(Str $str) {
  66. my ($id, $src, $checksum, $spec) = $str.split("\0", 4);
  67. nqp::p6bindattrinvres(
  68. self.new(:id(CompUnit::PrecompilationId.new($id)), :$src, :$checksum),
  69. CompUnit::PrecompilationDependency::File,
  70. '$!serialized-spec',
  71. $spec,
  72. );
  73. }
  74. method spec(--> CompUnit::DependencySpecification:D) {
  75. $!spec //= $!serialized-spec
  76. ?? do {
  77. use MONKEY-SEE-NO-EVAL;
  78. EVAL $!serialized-spec;
  79. }
  80. !! Nil;
  81. }
  82. method serialize(--> Str:D) {
  83. "$.id\0$.src\0$.checksum\0{$!serialized-spec ?? $!serialized-spec !! $!spec.perl}"
  84. }
  85. method Str() {
  86. "$.id $.src $.checksum {$!serialized-spec ?? $!serialized-spec !! $!spec.perl}"
  87. }
  88. }