ryac 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +70 -16
  3. data/Steepfile +2 -0
  4. data/bin/ryac +41 -2
  5. data/lib/ryac/analysis/constant/collection.rb +49 -0
  6. data/lib/ryac/analysis/constant/rename_mapping.rb +15 -1
  7. data/lib/ryac/analysis/ivar/collection.rb +28 -2
  8. data/lib/ryac/analysis/lazy_regions.rb +87 -0
  9. data/lib/ryac/analysis/local_scopes.rb +110 -12
  10. data/lib/ryac/analysis/method/collection.rb +100 -3
  11. data/lib/ryac/analysis/method/rename_mapping.rb +17 -12
  12. data/lib/ryac/analysis/type_oracle.rb +7 -2
  13. data/lib/ryac/driver_file.rb +47 -0
  14. data/lib/ryac/minifier.rb +27 -26
  15. data/lib/ryac/packer.rb +127 -0
  16. data/lib/ryac/pipeline/analyzer.rb +25 -3
  17. data/lib/ryac/pipeline/concatenator.rb +127 -8
  18. data/lib/ryac/pipeline/data_types.rb +13 -5
  19. data/lib/ryac/pipeline/file_collector.rb +64 -4
  20. data/lib/ryac/pipeline/method_renamer.rb +15 -0
  21. data/lib/ryac/pipeline/stage.rb +4 -0
  22. data/lib/ryac/pipeline/stage_runner.rb +7 -3
  23. data/lib/ryac/version.rb +1 -1
  24. data/lib/ryac.rb +3 -0
  25. data/sig/ryac/analysis/constant/collection.rbs +3 -0
  26. data/sig/ryac/analysis/constant/rename_mapping.rbs +2 -1
  27. data/sig/ryac/analysis/ivar/collection.rbs +1 -0
  28. data/sig/ryac/analysis/lazy_regions.rbs +10 -0
  29. data/sig/ryac/analysis/local_scopes.rbs +9 -1
  30. data/sig/ryac/analysis/method/collection.rbs +3 -0
  31. data/sig/ryac/analysis/method/rename_mapping.rbs +3 -2
  32. data/sig/ryac/analysis/type_oracle.rbs +1 -1
  33. data/sig/ryac/driver_file.rbs +8 -0
  34. data/sig/ryac/minifier.rbs +1 -2
  35. data/sig/ryac/packer.rbs +12 -0
  36. data/sig/ryac/pipeline/analyzer.rbs +6 -0
  37. data/sig/ryac/pipeline/concatenator.rbs +16 -1
  38. data/sig/ryac/pipeline/data_types.rbs +8 -5
  39. data/sig/ryac/pipeline/file_collector.rbs +8 -3
  40. data/sig/ryac/pipeline/method_renamer.rbs +3 -0
  41. data/sig/ryac/pipeline/stage.rbs +1 -0
  42. data/sig/ryac/pipeline/stage_runner.rbs +2 -1
  43. metadata +15 -8
  44. data/bin/console +0 -11
  45. data/bin/setup +0 -8
@@ -9,13 +9,12 @@ module Ryac
9
9
 
10
10
  OPTIMIZE_PRE: Array[stage_entry]
11
11
  OPTIMIZE_POST: Array[stage_entry]
12
- ALL_VAR_FEATURES: Hash[Symbol, Hash[Symbol, bool]]
13
12
  ALL_VAR_WITH_ATTR: Hash[Symbol, Hash[Symbol, bool]]
14
13
  STABLE_STAGES: Array[stage_entry]
15
14
  STAGES: Hash[Symbol, Array[stage_entry]]
16
15
 
17
16
  def self.derive_unstable: (Array[stage_entry] stable) -> Array[stage_entry]
18
- def self.run_stages: (String code, Array[stage_entry] stages, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String]) -> Pipeline::RenameResult
17
+ def self.run_stages: (String code, Array[stage_entry] stages, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String], ?lazy_files: Array[String]) -> Pipeline::RenameResult
19
18
 
20
19
  include Pipeline::SourcePatcher
21
20
 
@@ -0,0 +1,12 @@
1
+ module Ryac
2
+ module Packer
3
+ FORMATS: Array[Symbol]
4
+ SELF_STUB: String
5
+ ZLIB_STUB: String
6
+
7
+ def self.resolve_format: (String | Symbol value) -> Symbol
8
+ def self.pack: (String source, String | Symbol format) -> String
9
+ def self.reject_data_readers: (String source) -> void
10
+ def self.lzss_compress: (String data) -> String
11
+ end
12
+ end
@@ -8,8 +8,14 @@ module Ryac
8
8
  # kept untyped-valued because syntax_value has no Array member.
9
9
  @meta_node_map: Hash[location_key, meta_node_entry]
10
10
 
11
+ @method_policy: Symbol
12
+ @lazy_regions: Array[Prism::LambdaNode]
13
+ @alias_surface: Symbol
14
+ @scope_visible_names: Hash[scope_id, Set[String]]
15
+
11
16
  def self.prism_only: (ConcatenatedSource source) -> AnalysisResult
12
17
  def self.prism_only_from_string: (String content, ?source: ConcatenatedSource?) -> AnalysisResult
18
+ def initialize: (?method_policy: Symbol) -> void
13
19
  def call: (ConcatenatedSource source) -> AnalysisResult
14
20
  def syntax_data_for: (Prism::ProgramNode prism_ast) -> syntax_data_map
15
21
 
@@ -1,6 +1,13 @@
1
1
  module Ryac
2
2
  module Pipeline
3
3
  class Concatenator
4
+ REGISTRY_NAME: String
5
+ LOADER_NAME: String
6
+
7
+ @root: String
8
+ @registry: String?
9
+ @loader: String?
10
+
4
11
  class GraphSorter
5
12
  include TSort[String]
6
13
 
@@ -17,9 +24,17 @@ module Ryac
17
24
  def extract_cycle_from_graph: (DependencyGraph graph) -> Array[String]
18
25
  def find_cycle_dfs: (DependencyGraph graph, String node, Set[String] visited, Set[String] rec_stack, Array[String] path) -> bool
19
26
  def concatenate_files: (DependencyGraph graph, Array[String] sorted_paths) -> ConcatenatedSource
27
+ def common_root: (Array[String] paths) -> String
28
+ def relative_to_root: (String path) -> String
29
+ def lazy_key: (String path) -> String
30
+ def bundle_names: (DependencyGraph graph) -> Array[String]
31
+ def unused_name: (String base, Array[String] contents) -> String
32
+ def loader_prelude: (String registry, String loader) -> String
33
+ def lazy_registration: (String path, String content) -> String
20
34
  def collect_stdlib_requires: (FileEntry entry, Array[String] stdlib_requires) -> void
21
35
  def process_require_statements: (FileEntry entry, DependencyGraph graph, Set[String] inlined, Hash[String, String] cleaned_cache) -> String
22
- def offset_based_processing: (String content, Array[require_node_info] nodes, DependencyGraph graph, Set[String] in_class_deps, Set[String] inlined, Hash[String, String] cleaned_cache) -> String
36
+ def offset_based_processing: (String content, Array[require_node_info] nodes, DependencyGraph graph, Set[String] in_class_deps, Set[String] inlined, Hash[String, String] cleaned_cache, bool lazy_entry) -> String
37
+ def lazy_site_call: (String bytes, require_node_info node) -> String
23
38
  def line_based_processing: (String content, Array[require_node_info] require_nodes) -> String
24
39
  def resolve_node_path: (require_node_info node, DependencyGraph graph) -> String?
25
40
  def strip_outer_nesting: (String content) -> String
@@ -6,9 +6,10 @@ module Ryac
6
6
  attr_reader dependencies: Array[String]
7
7
  attr_reader require_nodes: Array[require_node_info]
8
8
  attr_reader in_class_dependencies: Array[String]
9
+ attr_reader lazy: bool
9
10
 
10
- def self.new: (path: String, content: String, dependencies: Array[String], require_nodes: Array[require_node_info], ?in_class_dependencies: Array[String]) -> FileEntry
11
- def initialize: (path: String, content: String, dependencies: Array[String], require_nodes: Array[require_node_info], ?in_class_dependencies: Array[String]) -> void
11
+ def self.new: (path: String, content: String, dependencies: Array[String], require_nodes: Array[require_node_info], ?in_class_dependencies: Array[String], ?lazy: bool) -> FileEntry
12
+ def initialize: (path: String, content: String, dependencies: Array[String], require_nodes: Array[require_node_info], ?in_class_dependencies: Array[String], ?lazy: bool) -> void
12
13
  end
13
14
 
14
15
  class DependencyGraph
@@ -20,6 +21,7 @@ module Ryac
20
21
  def initialize: () -> void
21
22
  def add_file: (FileEntry entry) -> void
22
23
  def paths: () -> Array[String]
24
+ def lazy_paths: () -> Array[String]
23
25
  def []: (String path) -> FileEntry?
24
26
  def size: () -> Integer
25
27
  def empty?: () -> bool
@@ -39,10 +41,11 @@ module Ryac
39
41
  attr_reader original_size: Integer
40
42
  attr_reader stdlib_requires: Array[String]
41
43
  attr_reader rbs_files: Hash[String, String]
44
+ attr_reader lazy_files: Array[String]
42
45
 
43
- def self.new: (content: String, ?file_boundaries: Array[FileBoundary], ?original_size: Integer?, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String]) -> ConcatenatedSource
44
- def initialize: (content: String, ?file_boundaries: Array[FileBoundary], ?original_size: Integer?, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String]) -> void
45
- def with: (?content: String, ?file_boundaries: Array[FileBoundary], ?original_size: Integer, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String]) -> ConcatenatedSource
46
+ def self.new: (content: String, ?file_boundaries: Array[FileBoundary], ?original_size: Integer?, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String], ?lazy_files: Array[String]) -> ConcatenatedSource
47
+ def initialize: (content: String, ?file_boundaries: Array[FileBoundary], ?original_size: Integer?, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String], ?lazy_files: Array[String]) -> void
48
+ def with: (?content: String, ?file_boundaries: Array[FileBoundary], ?original_size: Integer, ?stdlib_requires: Array[String], ?rbs_files: Hash[String, String], ?lazy_files: Array[String]) -> ConcatenatedSource
46
49
  end
47
50
 
48
51
  class AnalysisResult
@@ -1,12 +1,16 @@
1
1
  module Ryac
2
2
  module Pipeline
3
3
  # resolved_path is absent for :require_stdlib nodes; every node records
4
- # whether it sits inside a class/module body and/or a method body.
5
- type require_node_info = { type: Symbol, path: String, line: Integer, start_offset: Integer, length: Integer, in_class: bool, in_method: bool, ?resolved_path: String }
4
+ # whether it sits inside a class/module body and/or a method body. A
5
+ # :require_lazy node carries the byte layout of its interpolated
6
+ # argument, which the Concatenator respells into a loader call.
7
+ type lazy_require_site = { dir: String, arg_start_offset: Integer, arg_end_offset: Integer, prefix_start_offset: Integer, prefix_length: Integer, suffix_start_offset: Integer? }
8
+ type require_node_info = { type: Symbol, path: String, line: Integer, start_offset: Integer, length: Integer, in_class: bool, in_method: bool, ?resolved_path: String, ?lazy: lazy_require_site }
6
9
 
7
10
  class FileCollector
8
11
  @graph: DependencyGraph
9
12
  @visited: Set[String]
13
+ @pending_lazy: Array[String]
10
14
  @gem_names: Array[String]
11
15
  @project_roots: Array[String]
12
16
 
@@ -14,7 +18,7 @@ module Ryac
14
18
 
15
19
  private
16
20
 
17
- def collect_file: (String file_path, ?required_from: String?, ?line: Integer?) -> void
21
+ def collect_file: (String file_path, ?required_from: String?, ?line: Integer?, ?lazy: bool) -> void
18
22
  def extract_require_nodes: (String file_path, String content) -> Array[require_node_info]
19
23
  def traverse_for_requires: (Prism::Node? node, Array[require_node_info] nodes, String file_path, ?in_method: bool, ?in_class: bool) -> void
20
24
  def handle_call_node: (Prism::CallNode node, Array[require_node_info] nodes, String file_path, ?in_method: bool, ?in_class: bool) -> void
@@ -22,6 +26,7 @@ module Ryac
22
26
  def handle_require: (Prism::CallNode node, Array[require_node_info] nodes, String file_path, ?in_method: bool, ?in_class: bool) -> void
23
27
  def handle_autoload: (Prism::CallNode node, Array[require_node_info] nodes, String file_path, ?in_method: bool, ?in_class: bool) -> void
24
28
  def dir_interpolated_path: (Prism::Node path_arg) -> String?
29
+ def collect_lazy_candidates: (Prism::CallNode node, Prism::Node arg, Array[require_node_info] nodes, String file_path, in_class: bool) -> void
25
30
  def ensure_load_paths: (Array[String] require_paths) -> void
26
31
  def collect_rbs_files: (Array[String] entry_paths) -> void
27
32
  def collect_rbs_stdlib_files: () -> void
@@ -5,7 +5,10 @@ module Ryac
5
5
 
6
6
  @negated_transforms: Hash[location_key, bool]
7
7
  @source_bytes: String
8
+ @policy: Symbol
8
9
 
10
+ def initialize: (?policy: Symbol) -> void
11
+ def analysis_options: () -> Hash[Symbol, untyped]
9
12
  def needs_analysis?: () -> bool
10
13
  def collect: (StageContext ctx, Array[patch_entry] patches) -> void
11
14
 
@@ -16,6 +16,7 @@ module Ryac
16
16
  def self.new: (**untyped) -> Stage
17
17
  def needs_analysis?: () -> bool
18
18
  def fixpoint?: () -> bool
19
+ def analysis_options: () -> Hash[Symbol, untyped]
19
20
  def collect: (StageContext ctx, Array[patch_entry] patches) -> void
20
21
  def finish: (StageContext ctx) -> void
21
22
  def call: (String input) -> String
@@ -5,8 +5,9 @@ module Ryac
5
5
 
6
6
  @stdlib_requires: Array[String]
7
7
  @rbs_files: Hash[String, String]
8
+ @lazy_files: Array[String]
8
9
 
9
- def initialize: (?stdlib_requires: Array[String], ?rbs_files: Hash[String, String]) -> void
10
+ def initialize: (?stdlib_requires: Array[String], ?rbs_files: Hash[String, String], ?lazy_files: Array[String]) -> void
10
11
  def call: (String code, Array[Minifier::stage_entry] stage_defs) -> RenameResult
11
12
 
12
13
  private
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ryac
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ahogappa
@@ -58,10 +58,13 @@ dependencies:
58
58
  - !ruby/object:Gem::Version
59
59
  version: 4.1.0
60
60
  description: 'Ryac minifies Ruby source code using Prism AST transformations and TypeProf
61
- type inference. It supports multi-file bundling via require_relative, two compression
62
- levels (stable: whitespace removal, constant folding, constant/variable renaming;
63
- unstable: adds method renaming), and preserves functional equivalence through scope-aware
64
- analysis.'
61
+ type inference. It bundles a program''s require_relative and autoload graph into
62
+ one file (dynamic requires become lazy regions), compacts and folds the AST, renames
63
+ constants, variables and methods with compatibility aliases for the names a caller
64
+ outside the bundle may still use, and can emit the result as a self-extracting file.
65
+ Two levels: stable renames a method only when type inference resolved every caller;
66
+ unstable also renames methods with unresolved callers. Ryac is under active development:
67
+ its architecture, interfaces and output format may change between releases.'
65
68
  email:
66
69
  - ahogappa@gmail.com
67
70
  executables:
@@ -73,9 +76,7 @@ files:
73
76
  - README.md
74
77
  - Rakefile
75
78
  - Steepfile
76
- - bin/console
77
79
  - bin/ryac
78
- - bin/setup
79
80
  - lib/ryac.rb
80
81
  - lib/ryac/analysis/constant/collection.rb
81
82
  - lib/ryac/analysis/constant/rename_mapping.rb
@@ -85,6 +86,7 @@ files:
85
86
  - lib/ryac/analysis/ivar/collection.rb
86
87
  - lib/ryac/analysis/keyword/collection.rb
87
88
  - lib/ryac/analysis/keyword/rename_mapping.rb
89
+ - lib/ryac/analysis/lazy_regions.rb
88
90
  - lib/ryac/analysis/local_scopes.rb
89
91
  - lib/ryac/analysis/method/collection.rb
90
92
  - lib/ryac/analysis/method/rename_mapping.rb
@@ -95,10 +97,12 @@ files:
95
97
  - lib/ryac/analysis/site_bucket_mapping.rb
96
98
  - lib/ryac/analysis/type_oracle.rb
97
99
  - lib/ryac/ast_utils.rb
100
+ - lib/ryac/driver_file.rb
98
101
  - lib/ryac/errors.rb
99
102
  - lib/ryac/gem_resolver.rb
100
103
  - lib/ryac/minifier.rb
101
104
  - lib/ryac/name_generator.rb
105
+ - lib/ryac/packer.rb
102
106
  - lib/ryac/pipeline/analyzer.rb
103
107
  - lib/ryac/pipeline/attr_decl_shorten.rb
104
108
  - lib/ryac/pipeline/boolean_shorten.rb
@@ -133,6 +137,7 @@ files:
133
137
  - sig/ryac/analysis/ivar/collection.rbs
134
138
  - sig/ryac/analysis/keyword/collection.rbs
135
139
  - sig/ryac/analysis/keyword/rename_mapping.rbs
140
+ - sig/ryac/analysis/lazy_regions.rbs
136
141
  - sig/ryac/analysis/local_scopes.rbs
137
142
  - sig/ryac/analysis/method/collection.rbs
138
143
  - sig/ryac/analysis/method/rename_mapping.rbs
@@ -143,10 +148,12 @@ files:
143
148
  - sig/ryac/analysis/site_bucket_mapping.rbs
144
149
  - sig/ryac/analysis/type_oracle.rbs
145
150
  - sig/ryac/ast_utils.rbs
151
+ - sig/ryac/driver_file.rbs
146
152
  - sig/ryac/errors.rbs
147
153
  - sig/ryac/gem_resolver.rbs
148
154
  - sig/ryac/minifier.rbs
149
155
  - sig/ryac/name_generator.rbs
156
+ - sig/ryac/packer.rbs
150
157
  - sig/ryac/pipeline/analyzer.rbs
151
158
  - sig/ryac/pipeline/attr_decl_shorten.rbs
152
159
  - sig/ryac/pipeline/boolean_shorten.rbs
@@ -178,9 +185,9 @@ homepage: https://github.com/ahogappa/ryac
178
185
  licenses:
179
186
  - MIT
180
187
  metadata:
181
- homepage_uri: https://github.com/ahogappa/ryac
182
188
  source_code_uri: https://github.com/ahogappa/ryac
183
189
  changelog_uri: https://github.com/ahogappa/ryac/releases
190
+ rubygems_mfa_required: 'true'
184
191
  rdoc_options: []
185
192
  require_paths:
186
193
  - lib
data/bin/console DELETED
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler/setup"
5
- require "ryac"
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- require "irb"
11
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here