mt-lang 0.3.1 → 0.3.2
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/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/tooling/linter/imports_platform.rb +10 -0
- data/lib/milk_tea/tooling/linter/release_rules.rb +24 -3
- data/lib/milk_tea/tooling/linter/visitors.rb +1 -0
- data/std/iter.mt +304 -0
- data/std/mem/ptr.mt +12 -0
- data/std/simd.mt +100 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed7c9f0e80bb1fcfc3b458b277a0a2eda3b55ca295950af89c99a769b74e4be2
|
|
4
|
+
data.tar.gz: 4eb3fdfcbdb1557b3ed87a1f60ce8704f1f1de943e58e2c096318fc802da55a2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f900ebf361a8f2c8acec00fb63ccae9d6b23cd6059ba2edc27b4a3c89fe288453498d9aca753cba2b1139db6b69a82e52038e976c5d4b692d052845735afd754
|
|
7
|
+
data.tar.gz: 0a2bffc30d6485314ef351fb3917696298978798494e8eb655b27ed045c2d0c74674ab53d2c8b8764241b1e07fef092c3bbd6b35b73451d0237ac250a4d7a21c
|
data/lib/milk_tea/base.rb
CHANGED
|
@@ -18,6 +18,7 @@ module MilkTea
|
|
|
18
18
|
local_name = import.alias_name || import.path.parts.last
|
|
19
19
|
next if ignored_binding_name?(local_name)
|
|
20
20
|
next if used.include?(local_name)
|
|
21
|
+
next if import_provides_extending_methods?(import)
|
|
21
22
|
|
|
22
23
|
@warnings << Warning.new(
|
|
23
24
|
path: @path,
|
|
@@ -31,6 +32,15 @@ module MilkTea
|
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
|
|
35
|
+
def import_provides_extending_methods?(import)
|
|
36
|
+
return false unless @sema_facts.respond_to?(:imports)
|
|
37
|
+
|
|
38
|
+
module_binding = @sema_facts.imports[import.alias_name || import.path.parts.last]
|
|
39
|
+
return false unless module_binding&.respond_to?(:methods)
|
|
40
|
+
|
|
41
|
+
module_binding.methods.any?
|
|
42
|
+
end
|
|
43
|
+
|
|
34
44
|
def check_platform_api_drift(source_file)
|
|
35
45
|
resolved_path = self.class.resolve_lint_path(@path)
|
|
36
46
|
return unless resolved_path&.end_with?(".mt")
|
|
@@ -239,16 +239,37 @@ module MilkTea
|
|
|
239
239
|
true
|
|
240
240
|
elsif stmt.is_a?(AST::Assignment) && stmt.value.is_a?(AST::Identifier) && stmt.value.name == name
|
|
241
241
|
true
|
|
242
|
+
elsif stmt.is_a?(AST::ReturnStmt) && own_cast_in_unsafe?(stmt.value, name)
|
|
243
|
+
true
|
|
242
244
|
else
|
|
243
245
|
false
|
|
244
246
|
end
|
|
245
247
|
end
|
|
246
248
|
end
|
|
247
249
|
|
|
250
|
+
def own_cast_in_unsafe?(expr, name)
|
|
251
|
+
case expr
|
|
252
|
+
when AST::UnsafeExpr
|
|
253
|
+
case expr.expression
|
|
254
|
+
when AST::PrefixCast
|
|
255
|
+
expr.expression.expression.is_a?(AST::Identifier) && expr.expression.expression.name == name
|
|
256
|
+
end
|
|
257
|
+
else
|
|
258
|
+
false
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
248
262
|
def own_struct_field_transfer?(expr, name)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
263
|
+
case expr
|
|
264
|
+
when AST::Call
|
|
265
|
+
expr.arguments.any? do |arg|
|
|
266
|
+
next unless arg.is_a?(AST::Argument)
|
|
267
|
+
|
|
268
|
+
arg.value.is_a?(AST::Identifier) && arg.value.name == name ||
|
|
269
|
+
own_struct_field_transfer?(arg.value, name)
|
|
270
|
+
end
|
|
271
|
+
else
|
|
272
|
+
false
|
|
252
273
|
end
|
|
253
274
|
end
|
|
254
275
|
|
|
@@ -152,6 +152,7 @@ module MilkTea
|
|
|
152
152
|
column: statement.column,
|
|
153
153
|
var: statement.kind == :var
|
|
154
154
|
)
|
|
155
|
+
with_scope { visit_statement_list(statement.else_body) } if statement.else_body
|
|
155
156
|
check_redundant_type_annotation(statement)
|
|
156
157
|
flag_redundant_widening_cast(statement.value) if statement.type && statement.value
|
|
157
158
|
record_ptr_candidate(statement)
|
data/std/iter.mt
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
## std.iter — composable, lazy iteration adaptors.
|
|
2
|
+
##
|
|
3
|
+
## Each source/adaptor creates heap-allocated state linked through
|
|
4
|
+
## function pointers. Release walks the chain to free all allocations.
|
|
5
|
+
## Callbacks use fn types (function pointers, no captures).
|
|
6
|
+
##
|
|
7
|
+
## iter_map stores the mapped value inline in the adaptor state and
|
|
8
|
+
## returns a pointer to it — no per-item allocation.
|
|
9
|
+
##
|
|
10
|
+
## Usage:
|
|
11
|
+
## import std.iter
|
|
12
|
+
## let it = iter.from_array(ref_of(arr))
|
|
13
|
+
## let it2 = iter.iter_filter(it, pred)
|
|
14
|
+
## let v = iter.collect_vec(it2)
|
|
15
|
+
|
|
16
|
+
import std.mem.heap as heap
|
|
17
|
+
import std.mem.ptr as ptr
|
|
18
|
+
import std.vec as v
|
|
19
|
+
|
|
20
|
+
## ── Core Iter type ───────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
struct Iter[T]:
|
|
23
|
+
state: ptr[void]
|
|
24
|
+
next_fn: fn(state: ptr[void]) -> ptr[T]?
|
|
25
|
+
release_fn: fn(state: ptr[void]) -> void
|
|
26
|
+
|
|
27
|
+
## ── Ownership helpers ────────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
public function own_to_ptr[T](owned: own[T]) -> ptr[void]:
|
|
30
|
+
return unsafe: ptr[void]<-owned
|
|
31
|
+
|
|
32
|
+
## ── Source: Vec ─────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
public function from_vec[T](vec: ref[v.Vec[T]]) -> Iter[T]:
|
|
35
|
+
return from_span(vec.as_span())
|
|
36
|
+
|
|
37
|
+
## ── Source: array ────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
public function from_array[T, N](arr: ref[array[T, N]]) -> Iter[T]:
|
|
40
|
+
return from_span(arr.as_span())
|
|
41
|
+
|
|
42
|
+
## ── .as_iter() extending blocks ──────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
extending v.Vec[T]:
|
|
45
|
+
public editable function as_iter() -> Iter[T]:
|
|
46
|
+
return from_vec(ref_of(this))
|
|
47
|
+
|
|
48
|
+
extending array[T, N]:
|
|
49
|
+
public editable function as_iter() -> Iter[T]:
|
|
50
|
+
return from_array[T, N](ref_of(this))
|
|
51
|
+
|
|
52
|
+
extending span[T]:
|
|
53
|
+
public function as_iter() -> Iter[T]:
|
|
54
|
+
return from_span(this)
|
|
55
|
+
|
|
56
|
+
## ── Source: span ─────────────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
struct SpanIterState[T]:
|
|
59
|
+
sp: span[T]
|
|
60
|
+
index: ptr_uint
|
|
61
|
+
|
|
62
|
+
public function span_advance[T](state: ptr[void]) -> ptr[T]?:
|
|
63
|
+
let s = unsafe: ptr[SpanIterState[T]]<-state
|
|
64
|
+
let _this = unsafe: read(s)
|
|
65
|
+
if _this.index >= _this.sp.len:
|
|
66
|
+
return null
|
|
67
|
+
let item = unsafe: _this.sp.data + _this.index
|
|
68
|
+
unsafe: read(s).index += 1
|
|
69
|
+
return item
|
|
70
|
+
|
|
71
|
+
public function span_release[T](state: ptr[void]) -> void:
|
|
72
|
+
let s = unsafe: ptr[SpanIterState[T]]<-state
|
|
73
|
+
heap.release[SpanIterState[T]](s)
|
|
74
|
+
|
|
75
|
+
public function from_span[T](sp: span[T]) -> Iter[T]:
|
|
76
|
+
let state = heap.must_alloc[SpanIterState[T]](1)
|
|
77
|
+
state.index = 0
|
|
78
|
+
state.sp = sp
|
|
79
|
+
let p = own_to_ptr(state)
|
|
80
|
+
return Iter[T](state = p, next_fn = span_advance[T], release_fn = span_release[T])
|
|
81
|
+
|
|
82
|
+
## ── Adaptor: Filter ──────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
struct FilterState[T]:
|
|
85
|
+
inner: Iter[T]
|
|
86
|
+
pred: fn(value: T) -> bool
|
|
87
|
+
|
|
88
|
+
public function filter_advance[T](state: ptr[void]) -> ptr[T]?:
|
|
89
|
+
let s = unsafe: ptr[FilterState[T]]<-state
|
|
90
|
+
let _this = unsafe: read(s)
|
|
91
|
+
var item = _this.inner.next_fn(_this.inner.state)
|
|
92
|
+
while item != null:
|
|
93
|
+
if _this.pred(item.load()):
|
|
94
|
+
return item
|
|
95
|
+
item = _this.inner.next_fn(_this.inner.state)
|
|
96
|
+
return null
|
|
97
|
+
|
|
98
|
+
public function filter_release[T](state: ptr[void]) -> void:
|
|
99
|
+
let s = unsafe: ptr[FilterState[T]]<-state
|
|
100
|
+
let _this = unsafe: read(s)
|
|
101
|
+
_this.inner.release_fn(_this.inner.state)
|
|
102
|
+
heap.release[FilterState[T]](s)
|
|
103
|
+
|
|
104
|
+
public function iter_filter[T](iter: Iter[T], pred: fn(value: T) -> bool) -> Iter[T]:
|
|
105
|
+
let state = heap.must_alloc[FilterState[T]](1)
|
|
106
|
+
state.inner = iter
|
|
107
|
+
state.pred = pred
|
|
108
|
+
let p = own_to_ptr(state)
|
|
109
|
+
return Iter[T](state = p, next_fn = filter_advance[T], release_fn = filter_release[T])
|
|
110
|
+
|
|
111
|
+
## ── Adaptor: Map ─────────────────────────────────────────────────────
|
|
112
|
+
|
|
113
|
+
struct MapState[T, U]:
|
|
114
|
+
inner: Iter[T]
|
|
115
|
+
map_fn: fn(value: T) -> U
|
|
116
|
+
current: U
|
|
117
|
+
|
|
118
|
+
public function map_advance[T, U](state: ptr[void]) -> ptr[U]?:
|
|
119
|
+
let s = unsafe: ptr[MapState[T, U]]<-state
|
|
120
|
+
let current_offset = offset_of(MapState[T, U], current)
|
|
121
|
+
let p = unsafe: read(s)
|
|
122
|
+
let item = p.inner.next_fn(p.inner.state) else:
|
|
123
|
+
return null
|
|
124
|
+
let base: ptr[ubyte] = unsafe: ptr[ubyte]<-s
|
|
125
|
+
let field_ptr = unsafe: base + ptr_uint<-current_offset
|
|
126
|
+
let target: ptr[U] = unsafe: ptr[U]<-field_ptr
|
|
127
|
+
target.store(p.map_fn(item.load()))
|
|
128
|
+
return target
|
|
129
|
+
|
|
130
|
+
public function map_release[T, U](state: ptr[void]) -> void:
|
|
131
|
+
let s = unsafe: ptr[MapState[T, U]]<-state
|
|
132
|
+
let _this = unsafe: read(s)
|
|
133
|
+
_this.inner.release_fn(_this.inner.state)
|
|
134
|
+
heap.release[MapState[T, U]](s)
|
|
135
|
+
|
|
136
|
+
public function iter_map[T, U](iter: Iter[T], f: fn(value: T) -> U) -> Iter[U]:
|
|
137
|
+
let state = heap.must_alloc[MapState[T, U]](1)
|
|
138
|
+
state.inner = iter
|
|
139
|
+
state.map_fn = f
|
|
140
|
+
let p = own_to_ptr(state)
|
|
141
|
+
return Iter[U](state = p, next_fn = map_advance[T, U], release_fn = map_release[T, U])
|
|
142
|
+
|
|
143
|
+
## ── Adaptor: Take ────────────────────────────────────────────────────
|
|
144
|
+
|
|
145
|
+
struct TakeState[T]:
|
|
146
|
+
inner: Iter[T]
|
|
147
|
+
remaining: int
|
|
148
|
+
|
|
149
|
+
public function take_advance[T](state: ptr[void]) -> ptr[T]?:
|
|
150
|
+
let s = unsafe: ptr[TakeState[T]]<-state
|
|
151
|
+
let _this = unsafe: read(s)
|
|
152
|
+
if _this.remaining <= 0:
|
|
153
|
+
return null
|
|
154
|
+
unsafe: read(s).remaining -= 1
|
|
155
|
+
return _this.inner.next_fn(_this.inner.state)
|
|
156
|
+
|
|
157
|
+
public function take_release[T](state: ptr[void]) -> void:
|
|
158
|
+
let s = unsafe: ptr[TakeState[T]]<-state
|
|
159
|
+
let _this = unsafe: read(s)
|
|
160
|
+
_this.inner.release_fn(_this.inner.state)
|
|
161
|
+
heap.release[TakeState[T]](s)
|
|
162
|
+
|
|
163
|
+
public function iter_take[T](iter: Iter[T], n: int) -> Iter[T]:
|
|
164
|
+
let state = heap.must_alloc[TakeState[T]](1)
|
|
165
|
+
state.inner = iter
|
|
166
|
+
state.remaining = n
|
|
167
|
+
let p = own_to_ptr(state)
|
|
168
|
+
return Iter[T](state = p, next_fn = take_advance[T], release_fn = take_release[T])
|
|
169
|
+
|
|
170
|
+
## ── Adaptor: Skip ────────────────────────────────────────────────────
|
|
171
|
+
|
|
172
|
+
struct SkipState[T]:
|
|
173
|
+
inner: Iter[T]
|
|
174
|
+
skip_count: int
|
|
175
|
+
|
|
176
|
+
public function skip_advance[T](state: ptr[void]) -> ptr[T]?:
|
|
177
|
+
let s = unsafe: ptr[SkipState[T]]<-state
|
|
178
|
+
let _this = unsafe: read(s)
|
|
179
|
+
while _this.skip_count > 0:
|
|
180
|
+
let _ = _this.inner.next_fn(_this.inner.state) else:
|
|
181
|
+
return null
|
|
182
|
+
unsafe: read(s).skip_count -= 1
|
|
183
|
+
return _this.inner.next_fn(_this.inner.state)
|
|
184
|
+
|
|
185
|
+
public function skip_release[T](state: ptr[void]) -> void:
|
|
186
|
+
let s = unsafe: ptr[SkipState[T]]<-state
|
|
187
|
+
let _this = unsafe: read(s)
|
|
188
|
+
_this.inner.release_fn(_this.inner.state)
|
|
189
|
+
heap.release[SkipState[T]](s)
|
|
190
|
+
|
|
191
|
+
public function iter_skip[T](iter: Iter[T], n: int) -> Iter[T]:
|
|
192
|
+
let state = heap.must_alloc[SkipState[T]](1)
|
|
193
|
+
state.inner = iter
|
|
194
|
+
state.skip_count = n
|
|
195
|
+
let p = own_to_ptr(state)
|
|
196
|
+
return Iter[T](state = p, next_fn = skip_advance[T], release_fn = skip_release[T])
|
|
197
|
+
|
|
198
|
+
## ── Adaptor: Enumerate ────────────────────────────────────────────────
|
|
199
|
+
|
|
200
|
+
struct Enumerated[T]:
|
|
201
|
+
index: ptr_uint
|
|
202
|
+
value: T
|
|
203
|
+
|
|
204
|
+
struct EnumerateState[T]:
|
|
205
|
+
inner: Iter[T]
|
|
206
|
+
index: ptr_uint
|
|
207
|
+
current: Enumerated[T]
|
|
208
|
+
|
|
209
|
+
public function enum_advance[T](state: ptr[void]) -> ptr[Enumerated[T]]?:
|
|
210
|
+
let s = unsafe: ptr[EnumerateState[T]]<-state
|
|
211
|
+
let current_offset = offset_of(EnumerateState[T], current)
|
|
212
|
+
let p = unsafe: read(s)
|
|
213
|
+
let item = p.inner.next_fn(p.inner.state) else:
|
|
214
|
+
return null
|
|
215
|
+
let base: ptr[ubyte] = unsafe: ptr[ubyte]<-s
|
|
216
|
+
let field_ptr = unsafe: base + ptr_uint<-current_offset
|
|
217
|
+
let target: ptr[Enumerated[T]] = unsafe: ptr[Enumerated[T]]<-field_ptr
|
|
218
|
+
target.store(Enumerated[T](index = p.index, value = item.load()))
|
|
219
|
+
unsafe: read(s).index += 1
|
|
220
|
+
return target
|
|
221
|
+
|
|
222
|
+
public function enum_release[T](state: ptr[void]) -> void:
|
|
223
|
+
let s = unsafe: ptr[EnumerateState[T]]<-state
|
|
224
|
+
let _this = unsafe: read(s)
|
|
225
|
+
_this.inner.release_fn(_this.inner.state)
|
|
226
|
+
heap.release[EnumerateState[T]](s)
|
|
227
|
+
|
|
228
|
+
public function iter_enumerate[T](iter: Iter[T]) -> Iter[Enumerated[T]]:
|
|
229
|
+
let state = heap.must_alloc[EnumerateState[T]](1)
|
|
230
|
+
state.inner = iter
|
|
231
|
+
state.index = 0
|
|
232
|
+
let p = own_to_ptr(state)
|
|
233
|
+
let enum_it = Iter[Enumerated[T]](state = p, next_fn = enum_advance[T], release_fn = enum_release[T])
|
|
234
|
+
return enum_it
|
|
235
|
+
|
|
236
|
+
## ── Consumer: Fold ───────────────────────────────────────────────────
|
|
237
|
+
|
|
238
|
+
public function iter_fold[T, U](iter: Iter[T], init: U, f: fn(accum: U, value: T) -> U) -> U:
|
|
239
|
+
var accum = init
|
|
240
|
+
var item = iter.next_fn(iter.state)
|
|
241
|
+
while item != null:
|
|
242
|
+
accum = f(accum, item.load())
|
|
243
|
+
item = iter.next_fn(iter.state)
|
|
244
|
+
iter.release_fn(iter.state)
|
|
245
|
+
return accum
|
|
246
|
+
|
|
247
|
+
## ── Consumer: Find ───────────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
public function iter_find[T](iter: Iter[T], pred: fn(value: T) -> bool) -> Option[T]:
|
|
250
|
+
var item = iter.next_fn(iter.state)
|
|
251
|
+
while item != null:
|
|
252
|
+
if pred(item.load()):
|
|
253
|
+
let val = item.load()
|
|
254
|
+
iter.release_fn(iter.state)
|
|
255
|
+
return Option[T].some(value = val)
|
|
256
|
+
item = iter.next_fn(iter.state)
|
|
257
|
+
iter.release_fn(iter.state)
|
|
258
|
+
return Option[T].none
|
|
259
|
+
|
|
260
|
+
## ── Consumer: Any ────────────────────────────────────────────────────
|
|
261
|
+
|
|
262
|
+
public function iter_any[T](iter: Iter[T], pred: fn(value: T) -> bool) -> bool:
|
|
263
|
+
var item = iter.next_fn(iter.state)
|
|
264
|
+
while item != null:
|
|
265
|
+
if pred(item.load()):
|
|
266
|
+
iter.release_fn(iter.state)
|
|
267
|
+
return true
|
|
268
|
+
item = iter.next_fn(iter.state)
|
|
269
|
+
iter.release_fn(iter.state)
|
|
270
|
+
return false
|
|
271
|
+
|
|
272
|
+
## ── Consumer: All ────────────────────────────────────────────────────
|
|
273
|
+
|
|
274
|
+
public function iter_all[T](iter: Iter[T], pred: fn(value: T) -> bool) -> bool:
|
|
275
|
+
var item = iter.next_fn(iter.state)
|
|
276
|
+
while item != null:
|
|
277
|
+
if not pred(item.load()):
|
|
278
|
+
iter.release_fn(iter.state)
|
|
279
|
+
return false
|
|
280
|
+
item = iter.next_fn(iter.state)
|
|
281
|
+
iter.release_fn(iter.state)
|
|
282
|
+
return true
|
|
283
|
+
|
|
284
|
+
## ── Consumer: Count ──────────────────────────────────────────────────
|
|
285
|
+
|
|
286
|
+
public function iter_count[T](iter: Iter[T]) -> ptr_uint:
|
|
287
|
+
var count: ptr_uint = 0
|
|
288
|
+
var item = iter.next_fn(iter.state)
|
|
289
|
+
while item != null:
|
|
290
|
+
count += 1
|
|
291
|
+
item = iter.next_fn(iter.state)
|
|
292
|
+
iter.release_fn(iter.state)
|
|
293
|
+
return count
|
|
294
|
+
|
|
295
|
+
## ── Collect: Vec ─────────────────────────────────────────────────────
|
|
296
|
+
|
|
297
|
+
public function collect_vec[T](iter: Iter[T]) -> v.Vec[T]:
|
|
298
|
+
var result = v.Vec[T].create()
|
|
299
|
+
var item = iter.next_fn(iter.state)
|
|
300
|
+
while item != null:
|
|
301
|
+
result.push(item.load())
|
|
302
|
+
item = iter.next_fn(iter.state)
|
|
303
|
+
iter.release_fn(iter.state)
|
|
304
|
+
return result
|
data/std/mem/ptr.mt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## Pointer load/store — safe wrappers around unsafe: read(ptr).
|
|
2
|
+
##
|
|
3
|
+
## import std.mem.ptr as ptr
|
|
4
|
+
## p.store(42)
|
|
5
|
+
## let v = p.load()
|
|
6
|
+
|
|
7
|
+
extending ptr[T]:
|
|
8
|
+
public function load() -> T:
|
|
9
|
+
return unsafe: read(this)
|
|
10
|
+
|
|
11
|
+
public function store(value: T) -> void:
|
|
12
|
+
unsafe: read(this) = value
|
data/std/simd.mt
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
## SIMD helpers — load, store, and reduction operations
|
|
2
|
+
## for the built-in simd[T, N] type constructor.
|
|
3
|
+
##
|
|
4
|
+
## Load and store use unsafe ptr casts internally; the user-facing
|
|
5
|
+
## surface is safe because only valid pointer dereferencing is involved.
|
|
6
|
+
##
|
|
7
|
+
## Usage:
|
|
8
|
+
## import std.simd as simd
|
|
9
|
+
## let v = simd.load_aligned_float4(ptr)
|
|
10
|
+
## let s = simd.horizontal_sum_float4(v)
|
|
11
|
+
|
|
12
|
+
import std.mem.ptr as ptr
|
|
13
|
+
|
|
14
|
+
## ── simd[float, 4] ──────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
public function load_aligned_float4(p: ptr[float]) -> simd[float, 4]:
|
|
17
|
+
let sp = unsafe: ptr[simd[float, 4]]<-p
|
|
18
|
+
return sp.load()
|
|
19
|
+
|
|
20
|
+
public function load_unaligned_float4(p: ptr[float]) -> simd[float, 4]:
|
|
21
|
+
return load_aligned_float4(p)
|
|
22
|
+
|
|
23
|
+
public function store_aligned_float4(p: ptr[float], value: simd[float, 4]) -> void:
|
|
24
|
+
let sp = unsafe: ptr[simd[float, 4]]<-p
|
|
25
|
+
sp.store(value)
|
|
26
|
+
|
|
27
|
+
public function store_unaligned_float4(p: ptr[float], value: simd[float, 4]) -> void:
|
|
28
|
+
store_aligned_float4(p, value)
|
|
29
|
+
|
|
30
|
+
public function horizontal_sum_float4(v: simd[float, 4]) -> float:
|
|
31
|
+
return v[0] + v[1] + v[2] + v[3]
|
|
32
|
+
|
|
33
|
+
public function dot_float4(a: simd[float, 4], b: simd[float, 4]) -> float:
|
|
34
|
+
return horizontal_sum_float4(a * b)
|
|
35
|
+
|
|
36
|
+
## ── simd[int, 4] ────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
public function load_aligned_int4(p: ptr[int]) -> simd[int, 4]:
|
|
39
|
+
let sp = unsafe: ptr[simd[int, 4]]<-p
|
|
40
|
+
return sp.load()
|
|
41
|
+
|
|
42
|
+
public function load_unaligned_int4(p: ptr[int]) -> simd[int, 4]:
|
|
43
|
+
return load_aligned_int4(p)
|
|
44
|
+
|
|
45
|
+
public function store_aligned_int4(p: ptr[int], value: simd[int, 4]) -> void:
|
|
46
|
+
let sp = unsafe: ptr[simd[int, 4]]<-p
|
|
47
|
+
sp.store(value)
|
|
48
|
+
|
|
49
|
+
public function store_unaligned_int4(p: ptr[int], value: simd[int, 4]) -> void:
|
|
50
|
+
store_aligned_int4(p, value)
|
|
51
|
+
|
|
52
|
+
public function horizontal_sum_int4(v: simd[int, 4]) -> int:
|
|
53
|
+
return v[0] + v[1] + v[2] + v[3]
|
|
54
|
+
|
|
55
|
+
public function dot_int4(a: simd[int, 4], b: simd[int, 4]) -> int:
|
|
56
|
+
return horizontal_sum_int4(a * b)
|
|
57
|
+
|
|
58
|
+
## ── simd[float, 8] (AVX) ────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
public function load_aligned_float8(p: ptr[float]) -> simd[float, 8]:
|
|
61
|
+
let sp = unsafe: ptr[simd[float, 8]]<-p
|
|
62
|
+
return sp.load()
|
|
63
|
+
|
|
64
|
+
public function load_unaligned_float8(p: ptr[float]) -> simd[float, 8]:
|
|
65
|
+
return load_aligned_float8(p)
|
|
66
|
+
|
|
67
|
+
public function store_aligned_float8(p: ptr[float], value: simd[float, 8]) -> void:
|
|
68
|
+
let sp = unsafe: ptr[simd[float, 8]]<-p
|
|
69
|
+
sp.store(value)
|
|
70
|
+
|
|
71
|
+
public function store_unaligned_float8(p: ptr[float], value: simd[float, 8]) -> void:
|
|
72
|
+
store_aligned_float8(p, value)
|
|
73
|
+
|
|
74
|
+
public function horizontal_sum_float8(v: simd[float, 8]) -> float:
|
|
75
|
+
return v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6] + v[7]
|
|
76
|
+
|
|
77
|
+
public function dot_float8(a: simd[float, 8], b: simd[float, 8]) -> float:
|
|
78
|
+
return horizontal_sum_float8(a * b)
|
|
79
|
+
|
|
80
|
+
## ── simd[double, 2] ─────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
public function load_aligned_double2(p: ptr[double]) -> simd[double, 2]:
|
|
83
|
+
let sp = unsafe: ptr[simd[double, 2]]<-p
|
|
84
|
+
return sp.load()
|
|
85
|
+
|
|
86
|
+
public function load_unaligned_double2(p: ptr[double]) -> simd[double, 2]:
|
|
87
|
+
return load_aligned_double2(p)
|
|
88
|
+
|
|
89
|
+
public function store_aligned_double2(p: ptr[double], value: simd[double, 2]) -> void:
|
|
90
|
+
let sp = unsafe: ptr[simd[double, 2]]<-p
|
|
91
|
+
sp.store(value)
|
|
92
|
+
|
|
93
|
+
public function store_unaligned_double2(p: ptr[double], value: simd[double, 2]) -> void:
|
|
94
|
+
store_aligned_double2(p, value)
|
|
95
|
+
|
|
96
|
+
public function horizontal_sum_double2(v: simd[double, 2]) -> double:
|
|
97
|
+
return v[0] + v[1]
|
|
98
|
+
|
|
99
|
+
public function dot_double2(a: simd[double, 2], b: simd[double, 2]) -> double:
|
|
100
|
+
return horizontal_sum_double2(a * b)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mt-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -489,6 +489,7 @@ files:
|
|
|
489
489
|
- std/http.mt
|
|
490
490
|
- std/http/server.mt
|
|
491
491
|
- std/intern.mt
|
|
492
|
+
- std/iter.mt
|
|
492
493
|
- std/jobs.mt
|
|
493
494
|
- std/json.mt
|
|
494
495
|
- std/libc.mt
|
|
@@ -505,6 +506,7 @@ files:
|
|
|
505
506
|
- std/mem/endian.mt
|
|
506
507
|
- std/mem/heap.mt
|
|
507
508
|
- std/mem/pool.mt
|
|
509
|
+
- std/mem/ptr.mt
|
|
508
510
|
- std/mem/stack.mt
|
|
509
511
|
- std/mem/tracking.mt
|
|
510
512
|
- std/miniaudio.mt
|
|
@@ -552,6 +554,7 @@ files:
|
|
|
552
554
|
- std/sdl3/runtime.mt
|
|
553
555
|
- std/serialize.mt
|
|
554
556
|
- std/set.mt
|
|
557
|
+
- std/simd.mt
|
|
555
558
|
- std/sparse_set.mt
|
|
556
559
|
- std/spatial.mt
|
|
557
560
|
- std/sqlite3.mt
|
|
@@ -586,7 +589,7 @@ metadata:
|
|
|
586
589
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
587
590
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
588
591
|
post_install_message: |
|
|
589
|
-
Milk Tea 0.3.
|
|
592
|
+
Milk Tea 0.3.2 installed!
|
|
590
593
|
|
|
591
594
|
System requirements:
|
|
592
595
|
- A C compiler (gcc or clang) must be available on PATH
|