wardite 0.1.2 → 0.2.1

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.
@@ -0,0 +1,627 @@
1
+ # rbs_inline: enabled
2
+
3
+ module Wardite
4
+ module ValueHelper
5
+ # @rbs value: Integer
6
+ # @rbs return: I32
7
+ def I32(value)
8
+ if value < 0
9
+ $stderr.puts "debug: negative i32 value #{value} is passed, convert to unsigned"
10
+ value = as_u32(value)
11
+ end
12
+ I32.new.tap{|i| i.value = value & I32::I32_MAX }
13
+ end
14
+
15
+ # @rbs value: Integer
16
+ # @rbs return: I64
17
+ def I64(value)
18
+ if value < 0
19
+ $stderr.puts "debug: negative i64 value #{value} is passed, convert to unsigned"
20
+ value = as_u64(value)
21
+ end
22
+ I64.new.tap{|i| i.value = value & I64::I64_MAX }
23
+ end
24
+
25
+ # @rbs value: Float
26
+ # @rbs return: F32
27
+ def F32(value)
28
+ F32.new.tap{|i| i.value = value }
29
+ end
30
+
31
+ # @rbs value: Float
32
+ # @rbs return: F64
33
+ def F64(value)
34
+ F64.new.tap{|i| i.value = value }
35
+ end
36
+
37
+ private
38
+ # @rbs value: Integer
39
+ # @rbs return: Integer
40
+ def as_u32(value)
41
+ ((-value) ^ I32::I32_MAX) + 1
42
+ end
43
+
44
+ # @rbs value: Integer
45
+ # @rbs return: Integer
46
+ def as_u64(value)
47
+ ((-value) ^ I64::I64_MAX) + 1
48
+ end
49
+ end
50
+
51
+ extend ValueHelper
52
+
53
+ class I32
54
+ include ValueHelper
55
+
56
+ I32_MAX = (1<<32) - 1
57
+ # value should be stored as unsigned Integer, even in I32/I64
58
+ # when we want to access signed value, it'd be done via #value_s
59
+ attr_accessor :value #: Integer
60
+
61
+ # @rbs str: String
62
+ # @rbs size: Integer|nil
63
+ # @rbs signed: bool
64
+ # @rbs return: I32
65
+ def self.from_bytes(str, size: nil, signed: false)
66
+ v = case size
67
+ when nil
68
+ str.unpack("I!")[0]
69
+ when 8
70
+ signed ? str.unpack("c")[0] : str.unpack("C")[0]
71
+ when 16
72
+ signed ? str.unpack("s!")[0] : str.unpack("S!")[0]
73
+ end
74
+ if !v.is_a?(Integer)
75
+ raise "broken string or unsupported size: #{str.inspect} -> #{size}"
76
+ end
77
+ Wardite::I32(v)
78
+ end
79
+
80
+ # @rbs return: Integer
81
+ def memsize
82
+ 32
83
+ end
84
+
85
+ # returns a value interpreted as signed integer
86
+ # @rbs return: Integer
87
+ def value_s
88
+ (@value >> 31).zero? ?
89
+ @value :
90
+ ((-@value) ^ I32_MAX) + 1
91
+ end
92
+
93
+ # TODO: eliminate use of pack, to support mruby - in this file!
94
+ # @rbs size: Integer|nil
95
+ # @rbs return: String
96
+ def packed(size: nil)
97
+ case size
98
+ when nil
99
+ [self.value].pack("I!")
100
+ when 8
101
+ [self.value & 0xff].pack("C")
102
+ when 16
103
+ [self.value & 0xffff].pack("S!")
104
+ else
105
+ raise EvalError, "unsupported size #{size}"
106
+ end
107
+ end
108
+
109
+ # @rbs to: Symbol
110
+ # @rbs return: I32|I64|F32|F64
111
+ def wrap(to:)
112
+ raise EvalError, "unsupported operation"
113
+ end
114
+
115
+ # @rbs to: Symbol
116
+ # @rbs return: I32|I64|F32|F64
117
+ def extend_s(to:)
118
+ raise EvalError, "unsupported operation" if to != :i64
119
+ I64(value_s)
120
+ end
121
+
122
+ # @rbs to: Symbol
123
+ # @rbs return: I32|I64|F32|F64
124
+ def extend_u(to:)
125
+ raise EvalError, "unsupported operation" if to != :i64
126
+ I64(value)
127
+ end
128
+
129
+ # @rbs to: Symbol
130
+ # @rbs return: I32|I64|F32|F64
131
+ def trunc_s(to:)
132
+ raise EvalError, "unsupported operation"
133
+ end
134
+
135
+ # @rbs to: Symbol
136
+ # @rbs return: I32|I64|F32|F64
137
+ def trunc_u(to:)
138
+ raise EvalError, "unsupported operation"
139
+ end
140
+
141
+ # @rbs to: Symbol
142
+ # @rbs return: I32|I64|F32|F64
143
+ def convert_s(to:)
144
+ case to
145
+ when :f32
146
+ F32(value_s.to_f)
147
+ when :f64
148
+ F64(value_s.to_f)
149
+ else
150
+ raise EvalError, "unsupported operation"
151
+ end
152
+ end
153
+
154
+ # @rbs to: Symbol
155
+ # @rbs return: I32|I64|F32|F64
156
+ def convert_u(to:)
157
+ case to
158
+ when :f32
159
+ F32(value.to_f)
160
+ when :f64
161
+ F64(value.to_f)
162
+ else
163
+ raise EvalError, "unsupported operation"
164
+ end
165
+ end
166
+
167
+ # @rbs to: Symbol
168
+ # @rbs return: I32|I64|F32|F64
169
+ def demote(to:)
170
+ raise EvalError, "unsupported operation"
171
+
172
+ end
173
+
174
+ # @rbs to: Symbol
175
+ # @rbs return: I32|I64|F32|F64
176
+ def promote(to:)
177
+ raise EvalError, "unsupported operation"
178
+
179
+ end
180
+
181
+ # @rbs to: Symbol
182
+ # @rbs return: I32|I64|F32|F64
183
+ def reinterpret(to:)
184
+ raise EvalError, "unsupported operation" if to != :f32
185
+ v = [value].pack("I!").unpack("f")[0]
186
+ raise EvalError, "[BUG] String#unpack is broke, really?" if !v.is_a?(Float)
187
+ F32(v)
188
+ end
189
+
190
+ # I32#inspect shows signed value for convinience
191
+ def inspect
192
+ "I32(#{value_s})"
193
+ end
194
+ end
195
+
196
+ class I64
197
+ include ValueHelper
198
+
199
+ I64_MAX = (1<<64) - 1
200
+
201
+ attr_accessor :value #: Integer
202
+
203
+ # @rbs str: String
204
+ # @rbs size: Integer|nil
205
+ # @rbs signed: bool
206
+ # @rbs return: I64
207
+ def self.from_bytes(str, size: nil, signed: false)
208
+ v = case size
209
+ when nil
210
+ str.unpack("L!")[0]
211
+ when 8
212
+ signed ? str.unpack("c")[0] : str.unpack("C")[0]
213
+ when 16
214
+ signed ? str.unpack("s!")[0] : str.unpack("S!")[0]
215
+ when 32
216
+ signed ? str.unpack("i!")[0] : str.unpack("I!")[0]
217
+ end
218
+ if !v.is_a?(Integer)
219
+ raise "broken string or unsupported size: #{str.inspect} -> #{size}"
220
+ end
221
+ Wardite::I64(v)
222
+ end
223
+
224
+ # @rbs return: Integer
225
+ def memsize
226
+ 64
227
+ end
228
+
229
+ # returns a value interpreted as signed integer
230
+ # @rbs return: Integer
231
+ def value_s
232
+ (@value >> 63).zero? ?
233
+ @value :
234
+ ((-@value) ^ I64_MAX) + 1
235
+ end
236
+
237
+ # @rbs size: Integer|nil
238
+ # @rbs return: String
239
+ def packed(size: nil)
240
+ case size
241
+ when nil
242
+ [self.value].pack("L!")
243
+ when 8
244
+ [self.value & 0xff].pack("C")
245
+ when 16
246
+ [self.value & 0xffff].pack("S!")
247
+ when 32
248
+ [self.value & 0xffffffff].pack("I!")
249
+ else
250
+ raise EvalError, "unsupported size #{size}"
251
+ end
252
+ end
253
+
254
+ # @rbs to: Symbol
255
+ # @rbs return: I32|I64|F32|F64
256
+ def wrap(to:)
257
+ if to != :i32
258
+ raise EvalError, "unsupported operation #{to}"
259
+ end
260
+ I32(value % (1 << 32))
261
+ end
262
+
263
+ # @rbs to: Symbol
264
+ # @rbs return: I32|I64|F32|F64
265
+ def extend_s(to:)
266
+ raise EvalError, "unsupported operation"
267
+ end
268
+
269
+ # @rbs to: Symbol
270
+ # @rbs return: I32|I64|F32|F64
271
+ def extend_u(to:)
272
+ raise EvalError, "unsupported operation"
273
+ end
274
+
275
+ # @rbs to: Symbol
276
+ # @rbs return: I32|I64|F32|F64
277
+ def trunc_s(to:)
278
+ raise EvalError, "unsupported operation"
279
+ end
280
+
281
+ # @rbs to: Symbol
282
+ # @rbs return: I32|I64|F32|F64
283
+ def trunc_u(to:)
284
+ raise EvalError, "unsupported operation"
285
+ end
286
+
287
+ # @rbs to: Symbol
288
+ # @rbs return: I32|I64|F32|F64
289
+ def convert_s(to:)
290
+ case to
291
+ when :f32
292
+ F32(value_s.to_f)
293
+ when :f64
294
+ F64(value_s.to_f)
295
+ else
296
+ raise EvalError, "unsupported operation"
297
+ end
298
+ end
299
+
300
+ # @rbs to: Symbol
301
+ # @rbs return: I32|I64|F32|F64
302
+ def convert_u(to:)
303
+ case to
304
+ when :f32
305
+ F32(value.to_f)
306
+ when :f64
307
+ F64(value.to_f)
308
+ else
309
+ raise EvalError, "unsupported operation"
310
+ end
311
+ end
312
+
313
+ # @rbs to: Symbol
314
+ # @rbs return: I32|I64|F32|F64
315
+ def demote(to:)
316
+ raise EvalError, "unsupported operation"
317
+ end
318
+
319
+ # @rbs to: Symbol
320
+ # @rbs return: I32|I64|F32|F64
321
+ def promote(to:)
322
+ raise EvalError, "unsupported operation"
323
+ end
324
+
325
+ # @rbs to: Symbol
326
+ # @rbs return: I32|I64|F32|F64
327
+ def reinterpret(to:)
328
+ raise EvalError, "unsupported operation" if to != :f64
329
+ v = [value].pack("L!").unpack("d")[0]
330
+ raise EvalError, "[BUG] String#unpack is broke, really?" if !v.is_a?(Float)
331
+ F32(v)
332
+ end
333
+
334
+ # I64#inspect shows signed value
335
+ def inspect
336
+ "I64(#{@value})"
337
+ end
338
+ end
339
+
340
+ class F32
341
+ include ValueHelper
342
+
343
+ attr_accessor :value #: Float
344
+
345
+ # @rbs str: String
346
+ # @rbs return: F32
347
+ def self.from_bytes(str)
348
+ v = str.unpack("e")[0]
349
+ if !v.is_a?(Float)
350
+ raise "broken string or unsupported size: #{str.inspect} -> 4"
351
+ end
352
+ Wardite::F32(v)
353
+ end
354
+
355
+ # @rbs return: Integer
356
+ def memsize
357
+ 32
358
+ end
359
+
360
+ # @rbs return: :positive|:negative
361
+ def sign
362
+ upper = [0.0].pack("G")[0]&.ord&.<<(7)
363
+ if !upper
364
+ raise "[BUG] Array#pack looks broken?"
365
+ end
366
+ upper.zero? ? :positive : :negative
367
+ end
368
+
369
+ # @rbs size: Integer|nil
370
+ # @rbs return: String
371
+ def packed(size: nil)
372
+ [self.value].pack("e")
373
+ end
374
+
375
+ # @rbs to: Symbol
376
+ # @rbs return: I32|I64|F32|F64
377
+ def wrap(to:)
378
+ raise EvalError, "unsupported operation"
379
+ end
380
+
381
+ # @rbs to: Symbol
382
+ # @rbs return: I32|I64|F32|F64
383
+ def extend_s(to:)
384
+ raise EvalError, "unsupported operation"
385
+ end
386
+
387
+ # @rbs to: Symbol
388
+ # @rbs return: I32|I64|F32|F64
389
+ def extend_u(to:)
390
+ raise EvalError, "unsupported operation"
391
+ end
392
+
393
+ # @todo need more testcase...
394
+ # @see https://webassembly.github.io/spec/core/exec/numerics.html#xref-exec-numerics-op-trunc-s-mathrm-trunc-mathsf-s-m-n-z
395
+ # @rbs to: Symbol
396
+ # @rbs return: I32|I64|F32|F64
397
+ def trunc_s(to:)
398
+ v = value.to_i
399
+ case to
400
+ when :i32
401
+ if v >= 0
402
+ I32(v & (I32::I32_MAX >> 1))
403
+ else
404
+ v = v & I32::I32_MAX
405
+ if (v >> 31).zero?
406
+ raise EvalError, "[undefined behavior] detected overflow: #{value}"
407
+ end
408
+ I32(v)
409
+ end
410
+ when :i64
411
+ if v >= 0
412
+ I64(v & (I64::I64_MAX >> 1))
413
+ else
414
+ v = v & I64::I64_MAX
415
+ if (v >> 31).zero?
416
+ raise EvalError, "[undefined behavior] detected overflow: #{value}"
417
+ end
418
+ I64(v)
419
+ end
420
+ else
421
+ raise EvalError, "unsupported operation to: #{to}"
422
+ end
423
+ end
424
+
425
+ # @see https://webassembly.github.io/spec/core/exec/numerics.html#xref-exec-numerics-op-trunc-u-mathrm-trunc-mathsf-u-m-n-z
426
+ # @rbs to: Symbol
427
+ # @rbs return: I32|I64|F32|F64
428
+ def trunc_u(to:)
429
+ v = value.to_i
430
+ if v < 0
431
+ raise EvalError, "[undefined behavior] unexpected negative value"
432
+ end
433
+ case to
434
+ when :i32
435
+ v = v & I32::I32_MAX
436
+ I32(v)
437
+ when :i64
438
+ v = v & I64::I64_MAX
439
+ I64(v)
440
+ else
441
+ raise EvalError, "unsupported operation to: #{to}"
442
+ end
443
+ end
444
+
445
+ # @rbs to: Symbol
446
+ # @rbs return: I32|I64|F32|F64
447
+ def convert_s(to:)
448
+ raise EvalError, "unsupported operation"
449
+ end
450
+
451
+ # @rbs to: Symbol
452
+ # @rbs return: I32|I64|F32|F64
453
+ def convert_u(to:)
454
+ raise EvalError, "unsupported operation"
455
+ end
456
+
457
+ # @rbs to: Symbol
458
+ # @rbs return: I32|I64|F32|F64
459
+ def demote(to:)
460
+ raise EvalError, "unsupported operation"
461
+ end
462
+
463
+ # @rbs to: Symbol
464
+ # @rbs return: I32|I64|F32|F64
465
+ def promote(to:)
466
+ raise EvalError, "unsupported operation" if to != :f64
467
+ F64(value)
468
+ end
469
+
470
+ # @rbs to: Symbol
471
+ # @rbs return: I32|I64|F32|F64
472
+ def reinterpret(to:)
473
+ raise EvalError, "unsupported operation" if to != :i32
474
+ v = [value].pack("f").unpack("I!")[0]
475
+ raise EvalError, "[BUG] String#unpack is broke, really?" if !v.is_a?(Integer)
476
+ I32(v)
477
+ end
478
+
479
+ def inspect
480
+ "F32(#{@value})"
481
+ end
482
+ end
483
+
484
+ class F64
485
+ include ValueHelper
486
+
487
+ attr_accessor :value #: Float
488
+
489
+ # @rbs str: String
490
+ # @rbs return: F64
491
+ def self.from_bytes(str)
492
+ v = str.unpack("E")[0]
493
+ if !v.is_a?(Float)
494
+ raise "broken string or unsupported size: #{str.inspect} -> 8"
495
+ end
496
+ Wardite::F64(v)
497
+ end
498
+
499
+ # @rbs return: Integer
500
+ def memsize
501
+ 64
502
+ end
503
+
504
+ # @rbs return: :positive|:negative
505
+ def sign
506
+ upper = [0.0].pack("G")[0]&.ord&.<<(7)
507
+ if !upper
508
+ raise "[BUG] Array#pack looks broken?"
509
+ end
510
+ upper.zero? ? :positive : :negative
511
+ end
512
+
513
+ # @rbs size: Integer|nil
514
+ # @rbs return: String
515
+ def packed(size: nil)
516
+ [self.value].pack("E")
517
+ end
518
+
519
+ # @rbs to: Symbol
520
+ # @rbs return: I32|I64|F32|F64
521
+ def wrap(to:)
522
+ raise EvalError, "unsupported operation"
523
+ end
524
+
525
+ # @rbs to: Symbol
526
+ # @rbs return: I32|I64|F32|F64
527
+ def extend_s(to:)
528
+ raise EvalError, "unsupported operation"
529
+ end
530
+
531
+ # @rbs to: Symbol
532
+ # @rbs return: I32|I64|F32|F64
533
+ def extend_u(to:)
534
+ raise EvalError, "unsupported operation"
535
+ end
536
+
537
+ # @see the same as F32
538
+ # @rbs to: Symbol
539
+ # @rbs return: I32|I64|F32|F64
540
+ def trunc_s(to:)
541
+ v = value.to_i
542
+ case to
543
+ when :i32
544
+ if v >= 0
545
+ I32(v & (I32::I32_MAX >> 1))
546
+ else
547
+ v = v & I32::I32_MAX
548
+ if (v >> 31).zero?
549
+ raise EvalError, "[undefined behavior] detected overflow: #{value}"
550
+ end
551
+ I32(v)
552
+ end
553
+ when :i64
554
+ if v >= 0
555
+ I64(v & (I64::I64_MAX >> 1))
556
+ else
557
+ v = v & I64::I64_MAX
558
+ if (v >> 31).zero?
559
+ raise EvalError, "[undefined behavior] detected overflow: #{value}"
560
+ end
561
+ I64(v)
562
+ end
563
+ else
564
+ raise EvalError, "unsupported operation to: #{to}"
565
+ end
566
+ end
567
+
568
+ # @see the same as F32
569
+ # @rbs to: Symbol
570
+ # @rbs return: I32|I64|F32|F64
571
+ def trunc_u(to:)
572
+ v = value.to_i
573
+ if v < 0
574
+ raise EvalError, "[undefined behavior] unexpected negative value"
575
+ end
576
+ case to
577
+ when :i32
578
+ v = v & I32::I32_MAX
579
+ I32(v)
580
+ when :i64
581
+ v = v & I64::I64_MAX
582
+ I64(v)
583
+ else
584
+ raise EvalError, "unsupported operation to: #{to}"
585
+ end
586
+ end
587
+
588
+ # @rbs to: Symbol
589
+ # @rbs return: I32|I64|F32|F64
590
+ def convert_s(to:)
591
+ raise EvalError, "unsupported operation"
592
+ end
593
+
594
+ # @rbs to: Symbol
595
+ # @rbs return: I32|I64|F32|F64
596
+ def convert_u(to:)
597
+ raise EvalError, "unsupported operation"
598
+ end
599
+
600
+ # @todo no loss of digits...
601
+ # @rbs to: Symbol
602
+ # @rbs return: I32|I64|F32|F64
603
+ def demote(to:)
604
+ raise EvalError, "unsupported operation" if to != :f32
605
+ F32(value)
606
+ end
607
+
608
+ # @rbs to: Symbol
609
+ # @rbs return: I32|I64|F32|F64
610
+ def promote(to:)
611
+ raise EvalError, "unsupported operation"
612
+ end
613
+
614
+ # @rbs to: Symbol
615
+ # @rbs return: I32|I64|F32|F64
616
+ def reinterpret(to:)
617
+ raise EvalError, "unsupported operation" if to != :i64
618
+ v = [value].pack("d").unpack("L!")[0]
619
+ raise EvalError, "[BUG] String#unpack is broke, really?" if !v.is_a?(Integer)
620
+ I64(v)
621
+ end
622
+
623
+ def inspect
624
+ "F64(#{@value})"
625
+ end
626
+ end
627
+ end
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module Wardite
5
- VERSION = "0.1.2" #: String
5
+ VERSION = "0.2.1" #: String
6
6
  end
data/lib/wardite/wasi.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # rbs_inline: enabled
2
2
  module Wardite
3
3
  class WasiSnapshotPreview1
4
+ include ValueHelper
5
+
4
6
  attr_accessor :fd_table #: Array[IO]
5
7
 
6
8
  def initialize
@@ -12,12 +14,12 @@ module Wardite
12
14
  end
13
15
 
14
16
  # @rbs store: Store
15
- # @rbs args: Array[Object]
17
+ # @rbs args: Array[I32|I64|F32|F64]
16
18
  # @rbs return: Object
17
19
  def fd_write(store, args)
18
20
  iargs = args.map do |elm|
19
- if elm.is_a?(Integer)
20
- elm
21
+ if elm.is_a?(I32)
22
+ elm.value
21
23
  else
22
24
  raise Wardite::ArgumentError, "invalid type of args: #{args.inspect}"
23
25
  end
@@ -38,7 +40,7 @@ module Wardite
38
40
  nwritten += file.write(memory.data[start...(start+slen)])
39
41
  end
40
42
 
41
- memory.data[rp...(rp+4)] = [nwritten].pack("I")
43
+ memory.data[rp...(rp+4)] = [nwritten].pack("I!")
42
44
 
43
45
  0
44
46
  end