gloss 0.0.6 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests.yml +41 -0
  3. data/.gloss.yml +2 -0
  4. data/Gemfile.lock +10 -10
  5. data/README.md +5 -7
  6. data/Rakefile +5 -3
  7. data/exe/gloss +10 -13
  8. data/ext/gloss/Makefile +6 -21
  9. data/ext/gloss/lib/cr_ruby.cr +5 -4
  10. data/ext/gloss/src/cr_ast.cr +61 -71
  11. data/ext/gloss/src/gloss.cr +7 -2
  12. data/ext/gloss/src/rb_ast.cr +37 -36
  13. data/gloss.gemspec +3 -3
  14. data/lib/gloss.rb +10 -7
  15. data/lib/gloss/cli.rb +61 -40
  16. data/lib/gloss/config.rb +14 -8
  17. data/lib/gloss/errors.rb +1 -1
  18. data/lib/gloss/logger.rb +6 -6
  19. data/lib/gloss/prog_loader.rb +144 -0
  20. data/lib/gloss/scope.rb +1 -1
  21. data/lib/gloss/source.rb +1 -1
  22. data/lib/gloss/type_checker.rb +60 -32
  23. data/lib/gloss/utils.rb +38 -0
  24. data/lib/gloss/version.rb +1 -1
  25. data/lib/gloss/{builder.rb → visitor.rb} +88 -53
  26. data/lib/gloss/watcher.rb +14 -7
  27. data/lib/gloss/writer.rb +21 -10
  28. data/logo.svg +6 -0
  29. data/sig/core.rbs +2 -0
  30. data/sig/fast_blank.rbs +4 -0
  31. data/sig/{gloss.rbs → gls.rbs} +0 -0
  32. data/sig/optparse.rbs +6 -0
  33. data/sig/rubygems.rbs +9 -0
  34. data/sig/yaml.rbs +3 -0
  35. data/src/exe/gloss +19 -0
  36. data/src/lib/gloss.gl +25 -0
  37. data/src/lib/gloss/cli.gl +41 -26
  38. data/src/lib/gloss/config.gl +13 -8
  39. data/src/lib/gloss/logger.gl +2 -5
  40. data/src/lib/gloss/prog_loader.gl +138 -0
  41. data/src/lib/gloss/scope.gl +0 -2
  42. data/src/lib/gloss/type_checker.gl +57 -28
  43. data/src/lib/gloss/utils.gl +35 -0
  44. data/src/lib/gloss/version.gl +1 -1
  45. data/src/lib/gloss/{builder.gl → visitor.gl} +82 -45
  46. data/src/lib/gloss/watcher.gl +13 -8
  47. data/src/lib/gloss/writer.gl +15 -13
  48. metadata +29 -18
  49. data/.github/workflows/crystal_specs.yml +0 -26
  50. data/.github/workflows/ruby_specs.yml +0 -33
data/lib/gloss/watcher.rb CHANGED
@@ -6,11 +6,13 @@
6
6
  require "listen"
7
7
  module Gloss
8
8
  class Watcher
9
+ # @type var @listener: Listen?
10
+ @listener
9
11
  def initialize(paths)
10
12
  @paths = paths
11
13
  (if @paths.empty?
12
14
  @paths = [File.join(Dir.pwd, Config.src_dir)]
13
- @only = /\.gl$/
15
+ @only = /(?:(\.gl|(?:(?<=\/)[^\.\/]+))\z|\A[^\.\/]+\z)/
14
16
  else
15
17
  file_names = Array.new
16
18
  paths = Array.new
@@ -32,14 +34,14 @@ module Gloss
32
34
  def watch()
33
35
  Gloss.logger
34
36
  .info("Now listening for changes in #{@paths.join(", ")}")
35
- listener = Listen.to(*@paths, latency: 2, only: @only) { |modified, added, removed|
37
+ @listener ||= Listen.to(*@paths, latency: 2, only: @only) { |modified, added, removed|
36
38
  modified.+(added)
37
39
  .each() { |f|
38
40
  Gloss.logger
39
41
  .info("Rewriting #{f}")
40
42
  content = File.read(f)
41
43
  err = catch(:"error") { ||
42
- Writer.new(Builder.new(Parser.new(content)
44
+ Writer.new(Visitor.new(Parser.new(content)
43
45
  .run)
44
46
  .run, f)
45
47
  .run
@@ -64,13 +66,18 @@ nil }
64
66
  }
65
67
  }
66
68
  begin
67
- listener.start
69
+ @listener.start
68
70
  sleep
69
71
  rescue Interrupt
70
- Gloss.logger
71
- .info("Interrupt signal received, shutting down")
72
- exit(0)
72
+ kill
73
73
  end
74
74
  end
75
+ def kill()
76
+ Gloss.logger
77
+ .info("Interrupt signal received, shutting down")
78
+ (if @listener
79
+ @listener.stop
80
+ end)
81
+ end
75
82
  end
76
83
  end
data/lib/gloss/writer.rb CHANGED
@@ -3,20 +3,13 @@
3
3
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
4
  ##### See src/ to make changes
5
5
 
6
- require "pathname"
6
+ require "pathname"
7
7
  require "fileutils"
8
8
  module Gloss
9
- module Utils
10
- module_function
11
- def src_path_to_output_path(src_path)
12
- src_path.sub("#{Config.src_dir}/", "")
13
- .sub(/\.gl$/, ".rb")
14
- end
15
- end
16
9
  class Writer
17
- include Utils
18
- def initialize(content, src_path, output_path = Pathname.new(src_path_to_output_path(src_path)))
10
+ def initialize(content, src_path, output_path = Pathname.new(Utils.src_path_to_output_path(src_path)))
19
11
  @content = content
12
+ @src_path = src_path
20
13
  @output_path = output_path
21
14
  end
22
15
  def run()
@@ -25,8 +18,26 @@ module Gloss
25
18
  FileUtils.mkdir_p(@output_path.parent)
26
19
  end
27
20
  File.open(@output_path, "wb") { |file|
21
+ sb = shebang
22
+ (if sb
23
+ file.puts(sb)
24
+ end)
28
25
  file.puts(@content)
29
26
  }
30
27
  end
28
+ private def shebang()
29
+ (if @output_path.executable?
30
+ first_line = File.open(@src_path) { |f|
31
+ f.readline
32
+ }
33
+ (if first_line.start_with?("#!")
34
+ first_line
35
+ else
36
+ nil
37
+ end)
38
+ else
39
+ nil
40
+ end)
41
+ end
31
42
  end
32
43
  end
data/logo.svg ADDED
@@ -0,0 +1,6 @@
1
+ <svg width="171px" height="100px" xmlns="http://www.w3.org/2000/svg" viewBox="175 25 150 150" style="background-color: transparent;" preserveAspectRatio="xMidYMid"><defs><filter id="editing-golden" x="-100%" y="-100%" width="300%" height="300%"><feFlood flood-color="#000000" result="flood"></feFlood><feFlood flood-color="#eaa5a5" result="flood-light"></feFlood><feComposite operator="in" in="flood" in2="SourceAlpha" result="flood-comp"></feComposite><feGaussianBlur in="flood-comp" stdDeviation="3" result="blur"></feGaussianBlur><feOffset in="blur" dy="3" result="offset-blur"></feOffset><feComponentTransfer in="offset-blur" result="comp-blur"><feFuncA type="linear" slope="0.7" intercept="-0.1"></feFuncA></feComponentTransfer><feSpecularLighting surfaceScale="200" specularConstant="20" specularExponent="1" lighting-color="#fff" in="blur" result="specular"><fePointLight x="-250" y="-250" z="3500"></fePointLight></feSpecularLighting><feComponentTransfer in="specular" result="inspecular"><feFuncA type="linear" slope="-1" intercept="1"></feFuncA></feComponentTransfer><feComposite operator="in" in="flood-light" in2="inspecular" result="inspecular2"></feComposite><feComposite operator="in" in="inspecular2" in2="SourceAlpha" result="light"></feComposite><feMerge><feMergeNode in="comp-blur"></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode><feMergeNode in="light"></feMergeNode></feMerge></filter></defs><g filter="url(#editing-golden)"><g transform="translate(119.08499717712402, 130.10500073432922)"><path d="M27.50-50.40L27.50-50.40L27.50-50.40Q23.22-39.91 23.22-30.87L23.22-30.87L23.22-30.87Q23.22-21.83 26.91-17.55L26.91-17.55L26.91-17.55Q30.60-13.27 38.84-13.27L38.84-13.27L38.84-13.27Q43.76-13.27 47.51-16.80L47.51-16.80L47.51-16.80Q48.69-25.57 49.43-28.46L49.43-28.46L49.43-28.46Q51.25-35.52 55.00-35.52L55.00-35.52L55.00-35.52Q57.99-35.52 60.67-31.40L60.67-31.40L60.67-31.40Q63.34-27.29 63.24-24.40L63.24-24.40L63.24-24.40Q63.24-19.58 59.38-6.53L59.38-6.53L59.38-6.53Q66.88-12.20 76.61-23.33L76.61-23.33L76.61-23.33Q78.00-24.93 78.97-24.93L78.97-24.93L78.97-24.93Q80.46-24.93 80.46-21.40L80.46-21.40L80.46-21.40Q80.46-14.55 73.62-6.79L73.62-6.79L73.62-6.79Q66.77 0.96 55.43 5.56L55.43 5.56L55.43 5.56Q54.57 7.60 54.03 9.42L54.03 9.42L54.03 9.42Q53.50 11.23 52.64 13.80L52.64 13.80L52.64 13.80Q51.79 16.37 49.65 19.42L49.65 19.42L49.65 19.42Q47.51 22.47 44.30 24.61L44.30 24.61L44.30 24.61Q37.45 29.32 28.62 29.32L28.62 29.32L28.62 29.32Q19.79 29.32 13.86 25.41L13.86 25.41L13.86 25.41Q7.92 21.51 7.92 14.66L7.92 14.66L7.92 14.66Q7.92 11.34 11.13 9.20L11.13 9.20L11.13 9.20Q14.34 7.06 19.47 5.51L19.47 5.51L19.47 5.51Q24.61 3.96 31.03 2.78L31.03 2.78L31.03 2.78Q37.45 1.60 43.87 0.11L43.87 0.11L43.87 0.11Q44.73-2.35 45.15-4.49L45.15-4.49L45.15-4.49Q40.98-1.28 34.88-1.28L34.88-1.28L34.88-1.28Q22.15-1.28 14.87-6.53L14.87-6.53L14.87-6.53Q6.42-12.63 6.42-25.57L6.42-25.57L6.42-25.57Q6.42-42.48 14.98-57.67L14.98-57.67L14.98-57.67Q12.41-60.67 10.81-63.93L10.81-63.93L10.81-63.93Q9.20-67.20 9.20-68.91L9.20-68.91L9.20-68.91Q9.20-71.90 11.34-71.80L11.34-71.80L11.34-71.80Q12.73-71.80 14.55-70.08L14.55-70.08L14.55-70.08Q16.37-68.37 17.49-67.20L17.49-67.20L17.49-67.20Q18.62-66.02 19.90-65.06L19.90-65.06L19.90-65.06Q25.47-72.12 32.96-76.50L32.96-76.50L32.96-76.50Q40.45-80.89 49.43-80.89L49.43-80.89L49.43-80.89Q58.42-80.89 63.45-77.58L63.45-77.58L63.45-77.58Q68.48-74.26 68.48-66.02L68.48-66.02L68.48-66.02Q68.48-57.78 62.11-52.32L62.11-52.32L62.11-52.32Q55.75-46.87 44.41-46.87L44.41-46.87L44.41-46.87Q36.59-46.87 27.50-50.40ZM31.03-57.67L31.03-57.67L31.03-57.67Q36.91-55.10 45.26-55.10L45.26-55.10L45.26-55.10Q50.40-55.10 53.50-57.89L53.50-57.89L53.50-57.89Q56.60-60.67 56.60-63.93L56.60-63.93L56.60-63.93Q56.60-67.20 54.52-68.75L54.52-68.75L54.52-68.75Q52.43-70.30 49.01-70.30L49.01-70.30L49.01-70.30Q38.73-70.30 31.03-57.67ZM27.39 21.08L27.39 21.08L27.39 21.08Q34.67 21.08 40.13 10.16L40.13 10.16L40.13 10.16Q34.24 11.66 30.17 12.52L30.17 12.52L30.17 12.52Q26.11 13.38 23.59 14.02L23.59 14.02L23.59 14.02Q21.08 14.66 19.96 15.30L19.96 15.30L19.96 15.30Q18.83 15.94 18.83 17.12L18.83 17.12L18.83 17.12Q18.83 19.15 21.56 20.06L21.56 20.06L21.56 20.06Q24.29 20.97 27.39 21.08ZM98.97 0.32L98.97 0.32L98.97 0.32Q83.67 0.43 78.11-11.13L78.11-11.13L78.11-11.13Q76.18-15.19 76.18-21.35L76.18-21.35L76.18-21.35Q76.18-27.50 77.25-34.45L77.25-34.45L77.25-34.45Q79.39-48.36 85.49-60.13L85.49-60.13L85.49-60.13Q88.60-66.13 92.45-70.41L92.45-70.41L92.45-70.41Q100.90-79.82 111.28-79.72L111.28-79.72L111.28-79.72Q115.88-79.72 118.50-77.20L118.50-77.20L118.50-77.20Q121.12-74.69 121.12-69.98L121.12-69.98L121.12-69.98Q121.12-65.27 118.34-60.51L118.34-60.51L118.34-60.51Q115.56-55.75 111.23-50.66L111.23-50.66L111.23-50.66Q106.89-45.58 101.65-40.02L101.65-40.02L101.65-40.02Q96.41-34.45 91.38-27.93L91.38-27.93L91.38-23.65L91.38-23.65Q91.38-17.66 93.95-14.87L93.95-14.87L93.95-14.87Q96.51-12.09 99.94-12.09L99.94-12.09L99.94-12.09Q109.14-12.09 116.20-21.19L116.20-21.19L116.20-21.19Q119.09-24.93 120.59-24.93L120.59-24.93L120.59-24.93Q122.09-24.93 122.09-21.29L122.09-21.29L122.09-21.29Q122.09-17.66 120.11-13.86L120.11-13.86L120.11-13.86Q118.13-10.06 114.92-6.90L114.92-6.90L114.92-6.90Q111.71-3.75 107.53-1.71L107.53-1.71L107.53-1.71Q103.36 0.32 98.97 0.32ZM104.75-57.14L104.75-57.14L104.75-57.14Q107-59.92 108.28-62.17L108.28-62.17L108.28-62.17Q109.57-64.41 109.57-66.82L109.57-66.82L109.57-66.82Q109.57-69.23 107.86-69.23L107.86-69.23L107.86-69.23Q104.11-69.23 99.56-61.52L99.56-61.52L99.56-61.52Q95.02-53.82 92.77-41.30L92.77-41.30L92.77-41.30Q96.41-46.87 99.46-50.61L99.46-50.61L99.46-50.61Q102.51-54.36 104.75-57.14ZM159.00-9.10L159.00-9.10L159.00-9.10Q150.55 0.86 138.73 0.86L138.73 0.86L138.73 0.86Q126.90 0.86 121.02-5.19L121.02-5.19L121.02-5.19Q115.13-11.23 115.24-20.22L115.24-20.22L115.24-20.22Q115.13-32.96 123.26-42.16L123.26-42.16L123.26-42.16Q131.40-51.36 144.56-51.36L144.56-51.36L144.56-51.36Q150.55-51.36 154.19-49.86L154.19-49.86L154.19-49.86Q160.50-47.29 160.50-45.05L160.50-45.05L160.50-45.05Q160.50-43.34 151.67-43.28L151.67-43.28L151.67-43.28Q142.84-43.23 136.91-37.18L136.91-37.18L136.91-37.18Q130.97-31.14 130.97-21.93L130.97-21.93L130.97-21.93Q130.97-17.12 133.80-13.86L133.80-13.86L133.80-13.86Q136.64-10.59 141.83-10.59L141.83-10.59L141.83-10.59Q147.02-10.59 150.44-12.73L150.44-12.73L150.44-12.73Q142.84-17.87 142.84-27.61L142.84-27.61L142.84-27.61Q142.74-32.74 146.54-36.97L146.54-36.97L146.54-36.97Q150.33-41.20 156.27-41.25L156.27-41.25L156.27-41.25Q162.21-41.30 164.78-37.98L164.78-37.98L164.78-37.98Q167.35-34.67 167.35-29.48L167.35-29.48L167.35-29.48Q167.35-24.29 164.89-18.51L164.89-18.51L165.53-18.51L165.53-18.51Q170.24-18.62 173.66-21.83L173.66-21.83L173.66-21.83Q174.94-23.11 175.85-24.07L175.85-24.07L175.85-24.07Q176.76-25.04 177.73-25.04L177.73-25.04L177.73-25.04Q179.22-25.04 179.22-21.51L179.22-21.51L179.22-21.51Q179.22-14.98 175.37-11.72L175.37-11.72L175.37-11.72Q171.52-8.45 166.87-8.45L166.87-8.45L166.87-8.45Q162.21-8.45 159.00-9.10ZM158.04-21.51L158.04-21.51L158.04-21.51Q159.86-25.36 159.86-29.00L159.86-29.00L159.86-29.00Q159.86-32.63 157.50-32.63L157.50-32.63L157.50-32.63Q156.54-32.63 155.90-31.24L155.90-31.24L155.90-31.24Q155.26-29.85 155.26-28.57L155.26-28.57L155.26-28.57Q155.26-24.29 158.04-21.51ZM198.27-51.84L198.27-51.84L198.27-51.84Q205.44-51.89 208.97-49.17L208.97-49.17L208.97-49.17Q212.50-46.44 212.50-41.36L212.50-41.36L212.50-41.36Q212.50-36.27 209.45-32.69L209.45-32.69L209.45-32.69Q206.40-29.10 202.02-27.61L202.02-27.61L202.02-27.61Q205.12-24.40 207.63-21.08L207.63-21.08L207.63-21.08Q210.15-17.76 210.15-14.12L210.15-14.12L210.15-14.12Q210.15-6.96 204.48-3.05L204.48-3.05L204.48-3.05Q198.81 0.86 188.69 0.86L188.69 0.86L188.69 0.86Q178.58 0.86 173.55-3.16L173.55-3.16L173.55-3.16Q168.53-7.17 168.53-12.25L168.53-12.25L168.53-12.25Q168.53-17.33 171.04-21.51L171.04-21.51L171.04-21.51Q173.55-25.68 176.44-25.68L176.44-25.68L176.44-25.68Q178.16-25.68 178.90-24.45L178.90-24.45L178.90-24.45Q179.65-23.22 181.69-17.33L181.69-17.33L181.69-17.33Q182.44-15.19 184.15-13.27L184.15-13.27L184.15-13.27Q188.11-8.88 196.67-8.88L196.67-8.88L196.67-8.88Q195.38-12.95 192.55-15.89L192.55-15.89L192.55-15.89Q189.71-18.83 186.93-21.61L186.93-21.61L186.93-21.61Q184.15-24.40 182.01-27.55L182.01-27.55L182.01-27.55Q179.87-30.71 179.87-34.99L179.87-34.99L179.87-34.99Q179.87-42.69 185.64-47.51L185.64-47.51L185.64-47.51Q191.10-51.79 198.27-51.84ZM197.84-31.99L197.84-31.99L197.84-31.99Q202.12-36.59 202.12-39.38L202.12-39.38L202.12-39.38Q202.12-40.66 201.21-41.68L201.21-41.68L201.21-41.68Q200.30-42.69 198.59-42.69L198.59-42.69L198.59-42.69Q196.88-42.69 195.33-42.27L195.33-42.27L195.33-42.27Q193.78-41.84 192.81-41.62L192.81-41.62L192.81-41.62Q192.81-37.56 197.84-31.99ZM241.18-51.84L241.18-51.84L241.18-51.84Q248.35-51.89 251.88-49.17L251.88-49.17L251.88-49.17Q255.41-46.44 255.41-41.36L255.41-41.36L255.41-41.36Q255.41-36.27 252.36-32.69L252.36-32.69L252.36-32.69Q249.31-29.10 244.92-27.61L244.92-27.61L244.92-27.61Q248.03-24.40 250.54-21.08L250.54-21.08L250.54-21.08Q253.06-17.76 253.06-14.12L253.06-14.12L253.06-14.12Q253.06-6.96 247.38-3.05L247.38-3.05L247.38-3.05Q241.71 0.86 231.60 0.86L231.60 0.86L231.60 0.86Q221.49 0.86 216.46-3.16L216.46-3.16L216.46-3.16Q211.43-7.17 211.43-12.25L211.43-12.25L211.43-12.25Q211.43-17.33 213.95-21.51L213.95-21.51L213.95-21.51Q216.46-25.68 219.35-25.68L219.35-25.68L219.35-25.68Q221.06-25.68 221.81-24.45L221.81-24.45L221.81-24.45Q222.56-23.22 224.59-17.33L224.59-17.33L224.59-17.33Q225.34-15.19 227.05-13.27L227.05-13.27L227.05-13.27Q231.01-8.88 239.57-8.88L239.57-8.88L239.57-8.88Q238.29-12.95 235.45-15.89L235.45-15.89L235.45-15.89Q232.62-18.83 229.84-21.61L229.84-21.61L229.84-21.61Q227.05-24.40 224.91-27.55L224.91-27.55L224.91-27.55Q222.77-30.71 222.77-34.99L222.77-34.99L222.77-34.99Q222.77-42.69 228.55-47.51L228.55-47.51L228.55-47.51Q234.01-51.79 241.18-51.84ZM240.75-31.99L240.75-31.99L240.75-31.99Q245.03-36.59 245.03-39.38L245.03-39.38L245.03-39.38Q245.03-40.66 244.12-41.68L244.12-41.68L244.12-41.68Q243.21-42.69 241.50-42.69L241.50-42.69L241.50-42.69Q239.79-42.69 238.24-42.27L238.24-42.27L238.24-42.27Q236.68-41.84 235.72-41.62L235.72-41.62L235.72-41.62Q235.72-37.56 240.75-31.99Z" fill="#ae0606"></path></g></g><style>text {
2
+ font-size: 64px;
3
+ font-family: Arial Black;
4
+ dominant-baseline: central;
5
+ text-anchor: middle;
6
+ }</style></svg>
data/sig/core.rbs ADDED
@@ -0,0 +1,2 @@
1
+ class Any < Object
2
+ end
@@ -0,0 +1,4 @@
1
+ class String
2
+ def blank?: () -> bool
3
+ def blank_as?: () -> bool
4
+ end
File without changes
data/sig/optparse.rbs ADDED
@@ -0,0 +1,6 @@
1
+ # TODO: remove once stdlib gets types for this. Note - RBS
2
+ # already provides some types for this from its `sig` directory - so
3
+ # only adding #parse here
4
+ class OptionParser
5
+ def parse: (Array[String] argv) -> untyped
6
+ end
data/sig/rubygems.rbs ADDED
@@ -0,0 +1,9 @@
1
+ module Gem
2
+ class ConsoleUI
3
+ attr_reader outs: StringIO
4
+ end
5
+
6
+ def self.ui: () -> Gem::ConsoleUI
7
+
8
+ def self.suffixes: () -> Array[String]
9
+ end
data/sig/yaml.rbs ADDED
@@ -0,0 +1,3 @@
1
+ class Yaml
2
+ def safe_load: (String) -> untyped
3
+ end
data/src/exe/gloss ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gloss"
5
+
6
+ begin
7
+ Gloss::CLI.new(ARGV).run
8
+ rescue SystemExit
9
+ # raised by `abort` or `exit`; no op
10
+ rescue => e
11
+ abort <<~MSG
12
+ Unexpected error: #{e.class.name}
13
+ Message: #{e.message}
14
+ Trace:
15
+ #{e.backtrace.join("\n")}
16
+
17
+ This is probably a bug and may warrant a bug report at https://github.com/johansenja/gloss/issues
18
+ MSG
19
+ end
data/src/lib/gloss.gl ADDED
@@ -0,0 +1,25 @@
1
+ require "rbs"
2
+ require "json"
3
+ require "steep"
4
+ require "fast_blank"
5
+
6
+ require "gloss/version"
7
+ require "gloss/cli"
8
+ require "gloss/watcher"
9
+ require "gloss/type_checker"
10
+ require "gloss/parser"
11
+ require "gloss/initializer"
12
+ require "gloss/config"
13
+ require "gloss/writer"
14
+ require "gloss/source"
15
+ require "gloss/scope"
16
+ require "gloss/visitor"
17
+ require "gloss/errors"
18
+ require "gloss/logger"
19
+ require "gloss/prog_loader"
20
+ require "gloss/utils"
21
+
22
+ require "gls"
23
+
24
+ EMPTY_ARRAY = Array.new.freeze
25
+ EMPTY_HASH = {}.freeze
data/src/lib/gloss/cli.gl CHANGED
@@ -12,44 +12,59 @@ module Gloss
12
12
  files = @argv[1..-1]
13
13
  err_msg = catch :error do
14
14
  case command
15
- when "watch"
16
- files = files.map do |f|
17
- path = Pathname.new(f).absolute? ? f : File.join(Dir.pwd, f)
18
- if Pathname.new(path).exist?
19
- path
20
- else
21
- throw :error, "Pathname #{f} does not exist"
22
- end
23
- end
24
- Watcher.new(files).watch
25
- when "build"
26
- (files.empty? ? Dir.glob("#{Config.src_dir}/**/*.gl") : files).each do |fp|
27
- Gloss.logger.info "Building #{fp}"
28
- content = File.read(fp)
29
- tree_hash = Parser.new(content).run
30
- type_checker = TypeChecker.new
31
- rb_output = Builder.new(tree_hash, type_checker).run
32
- type_checker.run(rb_output)
33
-
34
- Gloss.logger.info "Writing #{fp}"
35
- Writer.new(rb_output, fp).run
36
- end
37
15
  when "init"
38
16
  force = false
39
17
  OptionParser.new do |opt|
40
18
  opt.on("--force", "-f") { force = true }
41
19
  end.parse(@argv)
42
20
  Initializer.new(force).run
21
+ when "version", "--version", "-v"
22
+ puts Gloss::VERSION
23
+ when "watch", "build"
24
+ type_checker = ProgLoader.new.run
25
+ if command == "watch"
26
+ files = files.map do |f|
27
+ path = Pathname.new(f).absolute? ? f : File.join(Dir.pwd, f)
28
+ if Pathname.new(path).exist?
29
+ path
30
+ else
31
+ throw :error, "Pathname #{f} does not exist"
32
+ end
33
+ end
34
+ Watcher.new(files).watch
35
+ elsif command == "build"
36
+ entry_tree = Parser.new(File.read(Config.entrypoint)).run
37
+ Visitor.new(entry_tree, type_checker).run
38
+ files = Dir.glob("#{Config.src_dir}/**/*.gl") if files.empty?
39
+ files.each do |fp|
40
+ fp = File.absolute_path(fp)
41
+ preloaded_output = OUTPUT_BY_PATH.fetch(fp) { nil }
42
+ if preloaded_output
43
+ rb_output = preloaded_output
44
+ else
45
+ Gloss.logger.info "Building #{fp}"
46
+ content = File.read(fp)
47
+ tree_hash = Parser.new(content).run
48
+ rb_output = Visitor.new(tree_hash, type_checker).run
49
+ end
50
+ Gloss.logger.info "Type checking #{fp}"
51
+ type_checker.run(fp, rb_output)
52
+ end
53
+ # ensure all files are type checked before anything is written
54
+ files.each do |fp|
55
+ fp = File.absolute_path(fp)
56
+ rb_output = OUTPUT_BY_PATH.fetch(fp)
57
+ Gloss.logger.info "Writing #{fp}"
58
+ Writer.new(rb_output, fp).run
59
+ end
60
+ end
43
61
  else
44
62
  throw :error, "Gloss doesn't know how to #{command}"
45
63
  end
46
64
  nil
47
65
  end
48
66
 
49
- if err_msg
50
- Gloss.logger.fatal err_msg
51
- exit 1
52
- end
67
+ abort err_msg if err_msg
53
68
  end
54
69
  end
55
70
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "ostruct"
4
2
  require "yaml"
5
3
 
@@ -9,13 +7,20 @@ module Gloss
9
7
  default_config: {
10
8
  frozen_string_literals: true,
11
9
  src_dir: "src",
10
+ entrypoint: nil,
11
+ strict_require: false,
12
+ type_checking_strictness: "strict"
12
13
  }
13
14
  )
14
15
 
15
- user_config = if File.exist?(CONFIG_PATH)
16
- YAML.safe_load(File.read(CONFIG_PATH))
17
- else
18
- Config.default_config
19
- end
20
- Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
16
+ def self.load_config
17
+ user_config = if File.exist?(File.absolute_path(File.join(Dir.pwd, CONFIG_PATH)))
18
+ YAML.safe_load(File.read(CONFIG_PATH))
19
+ else
20
+ Config.default_config
21
+ end
22
+ Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
23
+ end
24
+
25
+ load_config
21
26
  end
@@ -15,12 +15,9 @@ module Gloss
15
15
  nil => nil,
16
16
  "" => nil
17
17
  }.fetch env_log_level
18
- @logger = Logger.new(real_log_level ? STDOUT : nil)
19
- formatter = Logger::Formatter.new
20
- @logger.formatter = proc do |severity, datetime, progname, msg|
21
- formatter.call(severity, datetime, progname, msg)
18
+ @logger = Logger.new(real_log_level ? STDOUT : IO::NULL).tap do |l|
19
+ l.level = real_log_level if real_log_level
22
20
  end
23
- @logger
24
21
  end
25
22
  end
26
23
  end
@@ -0,0 +1,138 @@
1
+ require "rubygems/gem_runner"
2
+
3
+ module Gloss
4
+ OUTPUT_BY_PATH = Hash.new
5
+
6
+ class ProgLoader
7
+ attr_reader :type_checker
8
+
9
+ def initialize
10
+ entrypoint = Config.entrypoint
11
+ if entrypoint == nil || entrypoint == ""
12
+ throw :error, "Entrypoint is not yet set in .gloss.yml"
13
+ end
14
+ @files_to_process = [
15
+ Utils.absolute_path(Config.entrypoint),
16
+ # __dir__ is typed as String? - but it shouldn't be nil here
17
+ Utils.absolute_path(File.join((__dir__||""), "..", "..", "sig", "core.rbs"))
18
+ ]
19
+ @processed_files = Set.new
20
+ @type_checker = TypeChecker.new
21
+ end
22
+
23
+ def run
24
+ @files_to_process.each do |path_string|
25
+ # currently steep would give an `unexpected jump` if next was used
26
+ unless @processed_files.member?(path_string) || OUTPUT_BY_PATH.[](path_string)
27
+ Gloss.logger.debug "Loading #{path_string}"
28
+ path = Utils.absolute_path(path_string)
29
+ file_contents = File.open(path).read
30
+ contents_tree = Parser.new(file_contents).run
31
+ on_new_file_referenced = proc do |ps, relative|
32
+ ps.each do |pa|
33
+ if relative
34
+ handle_require_relative pa, path_string
35
+ else
36
+ handle_require pa
37
+ end
38
+ end
39
+ end
40
+ OUTPUT_BY_PATH.[](path_string) = Visitor.new(contents_tree, @type_checker, on_new_file_referenced).run
41
+ @processed_files.add path_string
42
+ end
43
+ end
44
+
45
+ @type_checker
46
+ end
47
+
48
+ STDLIB_TYPE_DEPENDENCIES = {
49
+ "yaml" => %w[pstore dbm],
50
+ "rbs" => %w[logger set tsort],
51
+ "logger" => %w[monitor],
52
+ }
53
+
54
+ private def handle_require(path)
55
+ if path.start_with? "."
56
+ base = File.join(Dir.pwd, path)
57
+ fp = base + ".gl"
58
+ if File.exist? fp
59
+ @files_to_process << fp
60
+ end
61
+ return
62
+ end
63
+
64
+ # look for .gl file if the "require" refers to the lib directory of current project dir
65
+ full = File.absolute_path("#{File.join(Config.src_dir, "lib", path)}.gl")
66
+ pathn = Pathname.new full
67
+ if pathn.file?
68
+ @files_to_process << pathn.to_s
69
+ else
70
+ # no .gl file available - .rbs file available?
71
+ # TODO: verify file is still actually requireable
72
+ pathn = Pathname.new("#{File.join(Dir.pwd, "sig", path)}.rbs")
73
+ gem_path = Utils.gem_path_for(path)
74
+ if gem_path
75
+ sig_files = Dir.glob(File.absolute_path(File.join(gem_path, "..", "sig", "**", "*.rbs")))
76
+ if sig_files.length.positive?
77
+ sig_files.each do |fp|
78
+ @type_checker.load_sig_path fp
79
+ end
80
+ @processed_files.add path
81
+ rbs_type_deps = STDLIB_TYPE_DEPENDENCIES.fetch(path) { nil }
82
+ if rbs_type_deps
83
+ rbs_type_deps.each { |d| handle_require d }
84
+ end
85
+ return
86
+ end
87
+ end
88
+
89
+ if pathn.file?
90
+ @type_checker.load_sig_path(pathn.to_s)
91
+ @processed_files.add pathn.to_s
92
+ else
93
+ rbs_stdlib_dir = File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "stdlib", path))
94
+ if Pathname.new(rbs_stdlib_dir).exist?
95
+ load_rbs_from_require_path(path)
96
+ rbs_type_deps = STDLIB_TYPE_DEPENDENCIES.fetch(path) { nil }
97
+ if rbs_type_deps
98
+ rbs_type_deps.each { |d| load_rbs_from_require_path d }
99
+ end
100
+ elsif Config.strict_require
101
+ throw :error, "Cannot resolve require path for #{path}"
102
+ else
103
+ Gloss.logger.debug "No path found for #{path}"
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ private def handle_require_relative(path, source_file)
110
+ base = File.join(source_file, "..", path)
111
+ pn : String? = nil
112
+ exts = %w[.gl].concat(Gem.suffixes)
113
+ exts.each do |ext|
114
+ full = File.absolute_path(base + ext)
115
+ pn = full if File.exist?(full)
116
+ end
117
+
118
+ if pn
119
+ @files_to_process << pn unless @files_to_process.include? pn
120
+ elsif Config.strict_require
121
+ throw :error, "Cannot resolve relative path for #{path}"
122
+ else
123
+ Gloss.logger.debug "No path found for #{path}"
124
+ end
125
+ end
126
+
127
+ private def rbs_stdlib_path_for(libr)
128
+ File.absolute_path(File.join(@type_checker.rbs_gem_dir, "..", "stdlib", libr))
129
+ end
130
+
131
+ private def load_rbs_from_require_path(path)
132
+ Dir.glob(File.join(rbs_stdlib_path_for(path), "**", "*.rbs")).each do |fp|
133
+ @type_checker.load_sig_path(fp)
134
+ @processed_files.add fp
135
+ end
136
+ end
137
+ end
138
+ end