jade-lang 0.4.0 → 0.6.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +164 -0
  3. data/CHANGELOG.md +180 -1
  4. data/README.md +5 -1
  5. data/docs/interop.md +208 -0
  6. data/docs/json.md +163 -0
  7. data/docs/lsp.md +105 -0
  8. data/docs/stdlib.md +69 -0
  9. data/docs/syntax.md +458 -0
  10. data/docs/testing.md +70 -0
  11. data/lib/jade/api.rb +244 -0
  12. data/lib/jade/cli/check.rb +97 -0
  13. data/lib/jade/cli/q.rb +47 -1
  14. data/lib/jade/cli.rb +4 -2
  15. data/lib/jade/codegen/boundary/cache.rb +1 -2
  16. data/lib/jade/codegen/boundary/specialized/list.rb +9 -4
  17. data/lib/jade/codegen/boundary/specialized/maybe.rb +15 -3
  18. data/lib/jade/codegen/boundary/specialized/record.rb +7 -3
  19. data/lib/jade/codegen/boundary/specialized.rb +7 -3
  20. data/lib/jade/codegen/emitter.rb +11 -2
  21. data/lib/jade/codegen/function_declaration.rb +7 -6
  22. data/lib/jade/codegen/helpers.rb +6 -0
  23. data/lib/jade/codegen/inlines.rb +5 -0
  24. data/lib/jade/decode.rb +332 -212
  25. data/lib/jade/frontend/fixity_fixer.rb +3 -2
  26. data/lib/jade/frontend/semantic_analysis/error/variable_not_found.rb +9 -2
  27. data/lib/jade/frontend/semantic_analysis/member_access.rb +11 -1
  28. data/lib/jade/frontend/type_checking/constraints/deriving/decodable.rb +10 -15
  29. data/lib/jade/frontend/type_checking/constraints/deriving/encodable.rb +7 -16
  30. data/lib/jade/interop/boundary.rb +12 -4
  31. data/lib/jade/interop/error.rb +25 -5
  32. data/lib/jade/lsp/converters.rb +2 -15
  33. data/lib/jade/lsp/snippets.rb +21 -3
  34. data/lib/jade/module_loader/module_name.rb +46 -0
  35. data/lib/jade/module_loader.rb +5 -0
  36. data/lib/jade/signature.rb +47 -0
  37. data/lib/jade/stdlib/calendar.rb +20 -19
  38. data/lib/jade/stdlib/clock.rb +7 -13
  39. data/lib/jade/stdlib/decimal.rb +3 -16
  40. data/lib/jade/stdlib/decode.rb +35 -12
  41. data/lib/jade/stdlib/encode.rb +9 -0
  42. data/lib/jade/stdlib/intrinsics.rb +9 -1
  43. data/lib/jade/stdlib/result.rb +1 -1
  44. data/lib/jade/stdlib/text.rb +131 -0
  45. data/lib/jade/task.rb +2 -3
  46. data/lib/jade/version.rb +1 -1
  47. metadata +14 -2
@@ -0,0 +1,131 @@
1
+ module Jade
2
+ module Stdlib
3
+ # Text representations of stdlib types, read in Ruby. Lives here rather
4
+ # than in Decimal / Clock / Calendar: those import Decode, so the
5
+ # instance cannot be registered the other way round. The types are
6
+ # compiled Jade, so constants resolve on first use.
7
+ #
8
+ # Accepts exactly what the Jade parsers did, down to `String.to_int`
9
+ # being `Integer(s, 10)` — whitespace and underscores included.
10
+ module Text
11
+ extend self
12
+
13
+ EPOCH_RATA_DIE = 719163
14
+ DAY_MS = 86_400_000
15
+
16
+ def to_decimal(s)
17
+ coefficient, exponent = s.split('e', 2)
18
+ return nil unless exponent
19
+
20
+ m = int(coefficient)
21
+ e = int(exponent)
22
+
23
+ m && e ? Jade::Decimal::Decimal[m, e] : nil
24
+ end
25
+
26
+ # No timezone offsets: `Clock.from_iso` never took them either.
27
+ def to_instant(s)
28
+ date_part, time_part = split_dt(s)
29
+ return nil unless date_part
30
+
31
+ d = to_date(date_part)
32
+ time = split_time(time_part)
33
+ return nil unless d && time
34
+
35
+ hour, minute, second, sub_ms = time
36
+ days = Jade::Calendar::Internal.to_rata_die(d) - EPOCH_RATA_DIE
37
+
38
+ Jade::Clock::Instant[
39
+ days * DAY_MS +
40
+ hour * 3_600_000 + minute * 60_000 + second * 1_000 + sub_ms
41
+ ]
42
+ end
43
+
44
+ def to_date(s)
45
+ parts = s.split('-')
46
+ return nil unless parts.length == 3
47
+
48
+ year, month, day = parts.map { int(it) }
49
+ return nil unless year && month && day
50
+
51
+ # Answers Jan outside 1..12 and never validates the day — calling
52
+ # it keeps that. Don't cache the Months: a second compile
53
+ # redefines the class.
54
+ Jade::Calendar::Date[
55
+ year,
56
+ Jade::Calendar::Internal.month_from_int(month),
57
+ day,
58
+ ]
59
+ end
60
+
61
+ # Seconds precision, always UTC. `rjust` matches `pad_to`, which
62
+ # left-pads without truncating: a negative year renders "00-5".
63
+ def from_instant(instant)
64
+ ms = instant._1
65
+ day_ms = ms % DAY_MS
66
+ d = Jade::Calendar::Internal.from_rata_die(ms / DAY_MS + EPOCH_RATA_DIE)
67
+
68
+ [
69
+ pad(d.year, 4),
70
+ '-', pad(Jade::Calendar::Internal.month_to_int(d.month), 2),
71
+ '-', pad(d.day, 2),
72
+ 'T', pad(day_ms / 3_600_000, 2),
73
+ ':', pad(day_ms % 3_600_000 / 60_000, 2),
74
+ ':', pad(day_ms % 60_000 / 1_000, 2),
75
+ 'Z',
76
+ ].join
77
+ end
78
+
79
+ private
80
+
81
+ def int(s) = Integer(s, 10, exception: false)
82
+
83
+ def pad(n, width) = n.to_s.rjust(width, '0')
84
+
85
+ def split_dt(s)
86
+ parts = s.split('T')
87
+ parts = s.split(' ') unless parts.length == 2
88
+
89
+ parts.length == 2 ? parts : nil
90
+ end
91
+
92
+ def split_time(s)
93
+ parts = strip_z(s).split(':')
94
+ return nil unless parts.length == 3
95
+
96
+ hour = int(parts[0])
97
+ minute = int(parts[1])
98
+ second, sub_ms = seconds(parts[2])
99
+
100
+ hour && minute && second && sub_ms ? [hour, minute, second, sub_ms] : nil
101
+ end
102
+
103
+ # A stray second "Z" falls through unstripped, as it did before.
104
+ def strip_z(s)
105
+ parts = s.split('Z')
106
+
107
+ parts.length == 1 || parts.length == 2 ? parts[0] : s
108
+ end
109
+
110
+ def seconds(s)
111
+ parts = s.split('.')
112
+
113
+ case parts.length
114
+ when 1 then [int(parts[0]), 0]
115
+ when 2 then [int(parts[0]), millis(int(parts[1]), parts[1].length)]
116
+ else [nil, nil]
117
+ end
118
+ end
119
+
120
+ def millis(n, digits)
121
+ return nil unless n
122
+
123
+ case digits <=> 3
124
+ when 0 then n
125
+ when -1 then n * 10.pow(3 - digits)
126
+ else n / 10.pow(digits - 3)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
data/lib/jade/task.rb CHANGED
@@ -92,9 +92,8 @@ module Jade
92
92
  private
93
93
 
94
94
  def decode(decoder, value)
95
- case Jade::Decode::Runner.run(decoder, value)
96
- in Jade::Result::Ok[v] then v
97
- in Jade::Result::Err[e] then fail Jade::Interop::DecodeError.new(e, value)
95
+ Jade::Decode::Runner.run!(decoder, value) do |error|
96
+ fail Jade::Interop::DecodeError.new(error, value, source: :port_return)
98
97
  end
99
98
  end
100
99
  end
data/lib/jade/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Jade
2
- VERSION = '0.4.0'
2
+ VERSION = '0.6.0'
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jade-lang
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Agustin Cornu
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-08-03 00:00:00.000000000 Z
10
+ date: 2026-08-13 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: base64
@@ -35,17 +35,26 @@ executables:
35
35
  extensions: []
36
36
  extra_rdoc_files: []
37
37
  files:
38
+ - AGENTS.md
38
39
  - CHANGELOG.md
39
40
  - LICENSE
40
41
  - README.md
42
+ - docs/interop.md
43
+ - docs/json.md
44
+ - docs/lsp.md
45
+ - docs/stdlib.md
46
+ - docs/syntax.md
47
+ - docs/testing.md
41
48
  - exe/jade
42
49
  - lib/jade.rb
50
+ - lib/jade/api.rb
43
51
  - lib/jade/ast.rb
44
52
  - lib/jade/ast/node.rb
45
53
  - lib/jade/ast/nodes.rb
46
54
  - lib/jade/ast/pretty_printer.rb
47
55
  - lib/jade/calendar/runtime.rb
48
56
  - lib/jade/cli.rb
57
+ - lib/jade/cli/check.rb
49
58
  - lib/jade/cli/fmt.rb
50
59
  - lib/jade/cli/lsp.rb
51
60
  - lib/jade/cli/q.rb
@@ -294,6 +303,7 @@ files:
294
303
  - lib/jade/module_loader/cache.rb
295
304
  - lib/jade/module_loader/dependency_graph.rb
296
305
  - lib/jade/module_loader/dependency_resolver.rb
306
+ - lib/jade/module_loader/module_name.rb
297
307
  - lib/jade/module_loader/normalize.rb
298
308
  - lib/jade/module_loader/topological_sort.rb
299
309
  - lib/jade/parsing.rb
@@ -306,6 +316,7 @@ files:
306
316
  - lib/jade/registry.rb
307
317
  - lib/jade/result.rb
308
318
  - lib/jade/runtime.rb
319
+ - lib/jade/signature.rb
309
320
  - lib/jade/source.rb
310
321
  - lib/jade/stdlib.rb
311
322
  - lib/jade/stdlib/basics.rb
@@ -328,6 +339,7 @@ files:
328
339
  - lib/jade/stdlib/show.rb
329
340
  - lib/jade/stdlib/string.rb
330
341
  - lib/jade/stdlib/task.rb
342
+ - lib/jade/stdlib/text.rb
331
343
  - lib/jade/stdlib/tuple.rb
332
344
  - lib/jade/symbol.rb
333
345
  - lib/jade/symbol/anonymous_record.rb