wardite 0.1.2 → 0.2.1

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