wardite 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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.2" #: 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