jade-lang 0.11.1 → 0.11.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/lib/jade/codegen/emitter.rb +55 -13
- data/lib/jade/codegen/function_call.rb +1 -1
- data/lib/jade/frontend/type_checking/inference/record_access.rb +1 -1
- data/lib/jade/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5529a34cf9b8a3d407d78642bca0281ec0a422dcded4f5875636e85f7018d7e4
|
|
4
|
+
data.tar.gz: c8da773021523ebb4d93836d8c8dee0ba0dca6acf4115f32ff46443a8dfbf08e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 26bab9740a9f008e4611a52210ec002f314e1fec4169239cd1a4aaa37eb090829a6fd20f4742ab475c169e4dc856652deddf12eca95f862f413668accdeda724
|
|
7
|
+
data.tar.gz: 243a05ffe69948767ccb7900b4e2cf443dccdb50d540f6cd16998863a6917e2742718769b742c0d0bf9f1e121aa4ee51cd85b70084ea7f26d669a1e49bf14d54
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,48 @@ All notable changes to this project are documented here. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.11.3] - 2026-09-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **A derived body can call a Jade function.** A deriver's body is an
|
|
12
|
+
s-expression over a fixed vocabulary, and none of it reached an ordinary
|
|
13
|
+
function: `:stdlib_fn` finds intrinsics, `:struct_constructor` finds
|
|
14
|
+
constructors, and `:call` needs a callee one of those produced. A deriver
|
|
15
|
+
that wanted to reuse a function had to rebuild it, and the copy drifts from
|
|
16
|
+
the original in silence.
|
|
17
|
+
|
|
18
|
+
[:call, [:fn, "Sql.Query.selected", [0]], [[:var, "q"]]]
|
|
19
|
+
|
|
20
|
+
The name resolves through the registry, which is what knows whether the
|
|
21
|
+
target is constrained — those are compiled twice, as `name` wrapping the Ruby
|
|
22
|
+
boundary and `__name__impl__` taking the dictionaries, and the boundary
|
|
23
|
+
wrapper is the wrong one to call from generated code.
|
|
24
|
+
|
|
25
|
+
Dictionaries come from the deriver's own `impl_arg`, one index per
|
|
26
|
+
constraint, in the order the callee declares them. A count that does not
|
|
27
|
+
match what the callee takes is refused where it is written, rather than
|
|
28
|
+
becoming Ruby that loads and misbehaves later. `[:impl_dict, i]` yields a
|
|
29
|
+
whole dictionary, where `[:impl_arg, i, fn]` yields one function out of one.
|
|
30
|
+
|
|
31
|
+
## [0.11.2] - 2026-09-15
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- **A constraint raised inside a field access reached nothing.**
|
|
36
|
+
`RecordAccess` built its result from the expected type alone, so whatever
|
|
37
|
+
the target raised was dropped at the dot. A function whose body is
|
|
38
|
+
`to_sel(q).cols` therefore recorded no constraint of its own: it took no
|
|
39
|
+
dictionary parameter, and the interface call inside it fell through to
|
|
40
|
+
`Runtime.impl_for`, which keys on the argument's own class. That dispatches
|
|
41
|
+
on `Q` when the interface is over the `c` inside it, and fails at the first
|
|
42
|
+
call — at run time, though both the types and the call sites were settled
|
|
43
|
+
when it compiled.
|
|
44
|
+
|
|
45
|
+
Deleting the `.cols` from the same program made it work, which is the
|
|
46
|
+
asymmetry that gave it away. It matters wherever an interface is over a type
|
|
47
|
+
a struct holds rather than the struct itself.
|
|
48
|
+
|
|
7
49
|
## [0.11.1] - 2026-09-15
|
|
8
50
|
|
|
9
51
|
### Added
|
data/lib/jade/codegen/emitter.rb
CHANGED
|
@@ -6,19 +6,19 @@ module Jade
|
|
|
6
6
|
extend self
|
|
7
7
|
extend Helpers
|
|
8
8
|
|
|
9
|
-
def emit(ir)
|
|
9
|
+
def emit(ir, registry = nil)
|
|
10
10
|
case ir
|
|
11
11
|
in [:var, expr]
|
|
12
12
|
expr
|
|
13
13
|
|
|
14
14
|
in [:!, expr]
|
|
15
|
-
"!(#{emit(expr)})"
|
|
15
|
+
"!(#{emit(expr, registry)})"
|
|
16
16
|
|
|
17
17
|
in [:and, expr1, expr2]
|
|
18
|
-
"#{emit(expr1)} && #{emit(expr2)}"
|
|
18
|
+
"#{emit(expr1, registry)} && #{emit(expr2, registry)}"
|
|
19
19
|
|
|
20
20
|
in [:==, expr1, expr2]
|
|
21
|
-
"#{emit(expr1)} == #{emit(expr2)}"
|
|
21
|
+
"#{emit(expr1, registry)} == #{emit(expr2, registry)}"
|
|
22
22
|
|
|
23
23
|
in Integer | TrueClass | FalseClass | Float
|
|
24
24
|
ir.to_s
|
|
@@ -29,24 +29,33 @@ module Jade
|
|
|
29
29
|
in [:case, subject, branches]
|
|
30
30
|
branches
|
|
31
31
|
.map { [:case_branch, *it] }
|
|
32
|
-
.map { emit(it) }
|
|
32
|
+
.map { emit(it, registry) }
|
|
33
33
|
.join("\n")
|
|
34
|
-
.then { "case #{emit(subject)}\n#{it}\nend" }
|
|
34
|
+
.then { "case #{emit(subject, registry)}\n#{it}\nend" }
|
|
35
35
|
|
|
36
36
|
in [:case_branch, pattern, body]
|
|
37
37
|
body
|
|
38
|
-
.map { emit(it) }.join('; ')
|
|
39
|
-
.then { "in #{emit(pattern)} then #{it}" }
|
|
38
|
+
.map { emit(it, registry) }.join('; ')
|
|
39
|
+
.then { "in #{emit(pattern, registry)} then #{it}" }
|
|
40
40
|
|
|
41
41
|
in [:call, callee, args]
|
|
42
42
|
args
|
|
43
|
-
.map { emit(it) }
|
|
43
|
+
.map { emit(it, registry) }
|
|
44
44
|
.join(', ')
|
|
45
|
-
.then { "#{emit(callee)}.call(#{it})"}
|
|
45
|
+
.then { "#{emit(callee, registry)}.call(#{it})"}
|
|
46
46
|
|
|
47
47
|
in [:impl_arg, index, fn]
|
|
48
48
|
"impl_arg[#{index}]['#{fn}']"
|
|
49
49
|
|
|
50
|
+
in [:impl_dict, index]
|
|
51
|
+
"impl_arg[#{index}]"
|
|
52
|
+
|
|
53
|
+
in [:fn, qualified_name]
|
|
54
|
+
fn_reference(qualified_name, [], registry)
|
|
55
|
+
|
|
56
|
+
in [:fn, qualified_name, dict_indices]
|
|
57
|
+
fn_reference(qualified_name, dict_indices, registry)
|
|
58
|
+
|
|
50
59
|
in [:stdlib_fn, name]
|
|
51
60
|
"Jade::Runtime.intr(#{name.inspect})"
|
|
52
61
|
|
|
@@ -61,18 +70,18 @@ module Jade
|
|
|
61
70
|
|
|
62
71
|
in [:list, exprs]
|
|
63
72
|
exprs
|
|
64
|
-
.map { emit(it) }
|
|
73
|
+
.map { emit(it, registry) }
|
|
65
74
|
.join(', ')
|
|
66
75
|
.then { "[#{it}]" }
|
|
67
76
|
|
|
68
77
|
in [:hash, pairs]
|
|
69
78
|
pairs
|
|
70
|
-
.map { |key, value| "#{key.inspect} => #{emit(value)}" }
|
|
79
|
+
.map { |key, value| "#{key.inspect} => #{emit(value, registry)}" }
|
|
71
80
|
.join(', ')
|
|
72
81
|
.then { it.empty? ? '{}' : "{ #{it} }" }
|
|
73
82
|
|
|
74
83
|
in [:access, expr, key]
|
|
75
|
-
"#{emit(expr)}.#{key}"
|
|
84
|
+
"#{emit(expr, registry)}.#{key}"
|
|
76
85
|
|
|
77
86
|
# patterns
|
|
78
87
|
|
|
@@ -88,6 +97,39 @@ module Jade
|
|
|
88
97
|
end
|
|
89
98
|
end
|
|
90
99
|
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def fn_reference(qualified_name, dict_indices, registry)
|
|
103
|
+
registry or fail("[:fn, #{qualified_name.inspect}] needs a registry")
|
|
104
|
+
|
|
105
|
+
*module_parts, name = qualified_name.split('.')
|
|
106
|
+
|
|
107
|
+
Symbol
|
|
108
|
+
.value_ref(module_parts.join('.'), name)
|
|
109
|
+
.then { registry.lookup(it) }
|
|
110
|
+
.then { checked_reference(it, qualified_name, dict_indices, registry) }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def checked_reference(symbol, qualified_name, dict_indices, registry)
|
|
114
|
+
wanted = dict_constraints(symbol, registry).size
|
|
115
|
+
|
|
116
|
+
unless wanted == dict_indices.size
|
|
117
|
+
fail(
|
|
118
|
+
"#{qualified_name} takes #{wanted} #{wanted == 1 ? 'dictionary' : 'dictionaries'}, " \
|
|
119
|
+
"#{dict_indices.size} given — a derived body passes one impl_arg " \
|
|
120
|
+
'index per constraint, in the order the callee declares them'
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
target = "#{internal(symbol.module_name)}.#{fn_target_name(symbol, registry)}"
|
|
125
|
+
return "#{internal(symbol.module_name)}.method(:#{fn_target_name(symbol, registry)})" if wanted.zero?
|
|
126
|
+
|
|
127
|
+
dict_indices
|
|
128
|
+
.map { "impl_arg[#{it}]" }
|
|
129
|
+
.join(', ')
|
|
130
|
+
.then { "->(*args) { #{target}(*args, #{it}) }" }
|
|
131
|
+
end
|
|
132
|
+
|
|
91
133
|
end
|
|
92
134
|
end
|
|
93
135
|
end
|
data/lib/jade/version.rb
CHANGED
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.11.
|
|
4
|
+
version: 0.11.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Agustin Cornu
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-09-
|
|
10
|
+
date: 2026-09-16 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: base64
|