wardite 0.2.0 → 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.
data/lib/wardite/value.rb CHANGED
@@ -1,39 +1,479 @@
1
1
  # rbs_inline: enabled
2
2
 
3
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
+
4
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
5
59
  attr_accessor :value #: Integer
6
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
+
7
93
  # TODO: eliminate use of pack, to support mruby - in this file!
94
+ # @rbs size: Integer|nil
8
95
  # @rbs return: String
9
- def packed
10
- [self.value].pack("I")
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
11
107
  end
12
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
13
191
  def inspect
14
- "I32(#{@value})"
192
+ "I32(#{value_s})"
15
193
  end
16
194
  end
17
195
 
18
196
  class I64
197
+ include ValueHelper
198
+
199
+ I64_MAX = (1<<64) - 1
200
+
19
201
  attr_accessor :value #: Integer
20
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
21
238
  # @rbs return: String
22
- def packed
23
- [self.value].pack("L")
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)
24
332
  end
25
333
 
334
+ # I64#inspect shows signed value
26
335
  def inspect
27
336
  "I64(#{@value})"
28
337
  end
29
338
  end
30
339
 
31
340
  class F32
32
- attr_accessor :value #: Float
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
33
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
34
370
  # @rbs return: String
35
- def packed
36
- [self.value].pack("f")
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)
37
477
  end
38
478
 
39
479
  def inspect
@@ -42,41 +482,146 @@ module Wardite
42
482
  end
43
483
 
44
484
  class F64
45
- attr_accessor :value #: Float
485
+ include ValueHelper
486
+
487
+ attr_accessor :value #: Float
46
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
47
514
  # @rbs return: String
48
- def packed
49
- [self.value].pack("d")
515
+ def packed(size: nil)
516
+ [self.value].pack("E")
50
517
  end
51
518
 
52
- def inspect
53
- "F64(#{@value})"
519
+ # @rbs to: Symbol
520
+ # @rbs return: I32|I64|F32|F64
521
+ def wrap(to:)
522
+ raise EvalError, "unsupported operation"
54
523
  end
55
- end
56
524
 
57
- module ValueHelper
58
- # @rbs value: Integer
59
- # @rbs return: I32
60
- def I32(value)
61
- I32.new.tap{|i| i.value = value }
525
+ # @rbs to: Symbol
526
+ # @rbs return: I32|I64|F32|F64
527
+ def extend_s(to:)
528
+ raise EvalError, "unsupported operation"
62
529
  end
63
530
 
64
- # @rbs value: Integer
65
- # @rbs return: I64
66
- def I64(value)
67
- I64.new.tap{|i| i.value = value }
531
+ # @rbs to: Symbol
532
+ # @rbs return: I32|I64|F32|F64
533
+ def extend_u(to:)
534
+ raise EvalError, "unsupported operation"
68
535
  end
69
536
 
70
- # @rbs value: Float
71
- # @rbs return: F32
72
- def F32(value)
73
- F32.new.tap{|i| i.value = value }
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
74
566
  end
75
567
 
76
- # @rbs value: Float
77
- # @rbs return: F64
78
- def F64(value)
79
- F64.new.tap{|i| i.value = value }
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})"
80
625
  end
81
626
  end
82
627
  end
@@ -2,5 +2,5 @@
2
2
  # rbs_inline: enabled
3
3
 
4
4
  module Wardite
5
- VERSION = "0.2.0" #: String
5
+ VERSION = "0.2.1" #: String
6
6
  end
data/lib/wardite/wasi.rb CHANGED
@@ -40,7 +40,7 @@ module Wardite
40
40
  nwritten += file.write(memory.data[start...(start+slen)])
41
41
  end
42
42
 
43
- memory.data[rp...(rp+4)] = [nwritten].pack("I")
43
+ memory.data[rp...(rp+4)] = [nwritten].pack("I!")
44
44
 
45
45
  0
46
46
  end