rlang 0.4.1 → 0.6.0
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/CHANGELOG.md +19 -3
- data/Gemfile.lock +4 -6
- data/README +11 -0
- data/README.md +18 -10
- data/bin/rlang +17 -5
- data/docs/RlangCompiler.md +5 -1
- data/docs/RlangManual.md +98 -20
- data/examples/fib/fib.rb +5 -1
- data/lib/builder/rlang/compiler.rb +2 -21
- data/lib/rlang/lib/array/array32.rb +59 -0
- data/lib/rlang/lib/array/array64.rb +56 -0
- data/lib/rlang/lib/array.rb +6 -0
- data/lib/rlang/lib/base64.rb +223 -0
- data/lib/rlang/lib/io.rb +75 -0
- data/lib/rlang/lib/kernel.rb +23 -0
- data/lib/rlang/lib/malloc.rb +12 -8
- data/lib/rlang/lib/memory.rb +102 -2
- data/lib/rlang/lib/object.rb +40 -4
- data/lib/rlang/lib/rlang.rb +29 -0
- data/lib/rlang/lib/rlang_core.rb +15 -0
- data/lib/rlang/lib/string.rb +106 -8
- data/lib/rlang/lib/type/i32.rb +43 -0
- data/lib/rlang/lib/type/i64.rb +2 -0
- data/lib/rlang/lib/unistd.rb +1 -2
- data/lib/rlang/lib/wasi.rb +184 -0
- data/lib/rlang/parser/attr.rb +9 -13
- data/lib/rlang/parser/const.rb +105 -1
- data/lib/rlang/parser/cvar.rb +11 -7
- data/lib/rlang/parser/data.rb +17 -6
- data/lib/rlang/parser/export.rb +4 -3
- data/lib/rlang/parser/ext/integer.rb +3 -1
- data/lib/rlang/parser/ext/type.rb +30 -1
- data/lib/rlang/parser/global.rb +10 -2
- data/lib/rlang/parser/ivar.rb +3 -7
- data/lib/rlang/parser/klass.rb +8 -35
- data/lib/rlang/parser/method.rb +36 -12
- data/lib/rlang/parser/module.rb +143 -0
- data/lib/rlang/parser/wgenerator.rb +462 -168
- data/lib/rlang/parser/wnode.rb +387 -142
- data/lib/rlang/parser/wtype.rb +30 -7
- data/lib/rlang/parser.rb +506 -231
- data/lib/rlang/version.rb +1 -1
- data/lib/rlang.rb +3 -0
- data/lib/ruby/mirror/rstring.rb +16 -0
- data/lib/utils/exceptions.rb +12 -0
- data/rlang.gemspec +4 -4
- metadata +25 -13
- data/lib/rlang/lib.rb +0 -11
@@ -0,0 +1,56 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# 4 bytes object array class
|
6
|
+
require_relative '../memory'
|
7
|
+
require_relative '../object'
|
8
|
+
require_relative '../type'
|
9
|
+
require_relative '../string'
|
10
|
+
|
11
|
+
|
12
|
+
class Array64
|
13
|
+
attr_reader :count, :ptr
|
14
|
+
|
15
|
+
# count: number of elements in Array
|
16
|
+
# Array elements are native types or
|
17
|
+
# pointers to objects
|
18
|
+
# Arrays are fixed size for now
|
19
|
+
def initialize(count)
|
20
|
+
# Avoid allocating 0 bytes in memory
|
21
|
+
if count == 0
|
22
|
+
@ptr = 0
|
23
|
+
else
|
24
|
+
# Memory size is count * 8 bytes
|
25
|
+
@ptr = Object.allocate(count << 3)
|
26
|
+
end
|
27
|
+
@count = count
|
28
|
+
end
|
29
|
+
|
30
|
+
def size; @count; end
|
31
|
+
def length; @count; end
|
32
|
+
def empty?; self.size == 0; end
|
33
|
+
|
34
|
+
def [](idx)
|
35
|
+
result :I64
|
36
|
+
raise "Index out of bound" if idx >= @count || idx < -@count
|
37
|
+
# offset in memory for elt #idx is idx * 8
|
38
|
+
Memory.load64(@ptr + (idx << 3))
|
39
|
+
end
|
40
|
+
|
41
|
+
def []=(idx, value)
|
42
|
+
arg value: :I64
|
43
|
+
result :I64
|
44
|
+
raise "Index out of bound" if idx >= @count || idx < -@count
|
45
|
+
# offset in memory for elt #idx is idx * 8
|
46
|
+
Memory.store64(@ptr + (idx << 3), value)
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
def free
|
51
|
+
result :none
|
52
|
+
Object.free(@ptr)
|
53
|
+
Object.free(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# Rlang WebAssembly compiler
|
2
|
+
# Copyright (c) 2019-2022, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
|
5
|
+
require 'kernel'
|
6
|
+
require 'string'
|
7
|
+
require 'array'
|
8
|
+
|
9
|
+
module Base64
|
10
|
+
|
11
|
+
include Kernel
|
12
|
+
|
13
|
+
BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
14
|
+
BASE64_CHARS_URLSAFE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
|
15
|
+
PAD = "="
|
16
|
+
LINE_SEP = "\n" # Would be "\r\n" on Windows
|
17
|
+
|
18
|
+
# Tables of valid ASCII char maps for Base64 decoding.
|
19
|
+
# -1 : the char is invalid
|
20
|
+
# >= 0 : the binary value to use for decoding (note: the '=' sign is also 0)
|
21
|
+
#
|
22
|
+
BASE64_CHAR_MAP =
|
23
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
24
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
|
25
|
+
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
|
26
|
+
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
|
27
|
+
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
28
|
+
51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
29
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
30
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
31
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
32
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
33
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
34
|
+
|
35
|
+
BASE64_CHAR_MAP_URLSAFE =
|
36
|
+
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
37
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
|
38
|
+
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,
|
39
|
+
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26,
|
40
|
+
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
|
41
|
+
51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
42
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
43
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
44
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
45
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
46
|
+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
|
47
|
+
|
48
|
+
|
49
|
+
# Generic base 64 encoding
|
50
|
+
# Derived from
|
51
|
+
# http://www.java2s.com/Code/Java/Development-Class/AfastandmemoryefficientclasstoencodeanddecodetoandfromBASE64infullaccordancewithRFC2045.htm)
|
52
|
+
def self._encode64(bin, line_sep, base64_chars)
|
53
|
+
arg bin: :String, base64_chars: :String
|
54
|
+
local str: :String
|
55
|
+
result :String
|
56
|
+
|
57
|
+
# Check special case
|
58
|
+
return "" if bin.empty?
|
59
|
+
slen = bin.length
|
60
|
+
|
61
|
+
# Number of even 24 bits (groups of 3 bytes)
|
62
|
+
elen = (slen / 3) * 3
|
63
|
+
# Encoded character count
|
64
|
+
ccnt = ((slen - 1) / 3 + 1) << 2
|
65
|
+
# Size of encoded string (incl. line separators)
|
66
|
+
# Note : Ruby implementation always add a \n at the end
|
67
|
+
# hence the +1
|
68
|
+
dlen = ccnt
|
69
|
+
dlen += ((ccnt - 1) / 60 + 1) * LINE_SEP.length if line_sep
|
70
|
+
|
71
|
+
# Allocate the proper size for encoded string
|
72
|
+
# to avoid allocating many string objects during
|
73
|
+
# concatenation
|
74
|
+
str = String.new(0, dlen)
|
75
|
+
|
76
|
+
# Encode even 24 bits
|
77
|
+
s=0; d=0; cc=0
|
78
|
+
while s < elen
|
79
|
+
# Copy next three bytes into lower 24 bits of int,
|
80
|
+
# paying attention to sign.
|
81
|
+
i = bin[s].ord << 16 | bin[s+1].ord << 8 | bin[s+2].ord
|
82
|
+
s += 3
|
83
|
+
|
84
|
+
# Encode the int into four chars
|
85
|
+
str[d] = base64_chars[(i >> 18) & 0x3f]; d += 1
|
86
|
+
str[d] = base64_chars[(i >> 12) & 0x3f]; d += 1
|
87
|
+
str[d] = base64_chars[(i >> 6) & 0x3f]; d += 1
|
88
|
+
str[d] = base64_chars[i & 0x3f]; d += 1
|
89
|
+
cc += 1
|
90
|
+
|
91
|
+
# Add optional line separator each 60 chars in Ruby
|
92
|
+
if (line_sep && cc == 15 && d < dlen - 1)
|
93
|
+
str[d] = LINE_SEP; d += LINE_SEP.length
|
94
|
+
cc = 0
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Pad and encode last bits if source isn't even 24 bits.
|
99
|
+
left = slen - elen # 0 - 2
|
100
|
+
if left > 0
|
101
|
+
# Prepare the last int
|
102
|
+
i = bin[elen].ord << 10
|
103
|
+
i |= (bin[slen - 1].ord << 2) if left == 2
|
104
|
+
|
105
|
+
# Set last four chars
|
106
|
+
str[d] = base64_chars[i >> 12]; d += 1
|
107
|
+
str[d] = base64_chars[(i >> 6) & 0x3f]; d += 1
|
108
|
+
if left == 2
|
109
|
+
str[d] = base64_chars[i & 0x3f]
|
110
|
+
else
|
111
|
+
str[d] = PAD
|
112
|
+
end
|
113
|
+
d += 1
|
114
|
+
str[d] = PAD; d += 1
|
115
|
+
end
|
116
|
+
|
117
|
+
str[d] = LINE_SEP if line_sep
|
118
|
+
return str
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
# Decodes a BASE64 encoded String. All illegal characters will be
|
123
|
+
# ignored and can handle both arrays with and without line separators.
|
124
|
+
#
|
125
|
+
# Derived from
|
126
|
+
# http://www.java2s.com/Code/Java/Development-Class/AfastandmemoryefficientclasstoencodeanddecodetoandfromBASE64infullaccordancewithRFC2045.htm)
|
127
|
+
|
128
|
+
def self._decode64(str, base64_chars, base64_char_map)
|
129
|
+
arg str: :String, base64_chars: :String, base64_char_map: :Array32
|
130
|
+
local bin: :String
|
131
|
+
result :String
|
132
|
+
|
133
|
+
# Check special case
|
134
|
+
return "" if (slen = str.length) == 0
|
135
|
+
|
136
|
+
# Count illegal characters (including '\r', '\n') to know what
|
137
|
+
# size the returned array will be, so we don't have to reallocate
|
138
|
+
# & copy it later.
|
139
|
+
# Number of separator characters. (Actually illegal characters,
|
140
|
+
# but that's a bonus...)
|
141
|
+
sepcnt = 0; i = 0
|
142
|
+
while i < slen
|
143
|
+
sepcnt += 1 if base64_char_map[str[i].ord] < 0
|
144
|
+
i += 1
|
145
|
+
end
|
146
|
+
|
147
|
+
# Check that legal chars (including '=') are evenly divideable
|
148
|
+
# by 4 as specified in RFC 2045.
|
149
|
+
return "" if (slen - sepcnt) % 4 != 0
|
150
|
+
|
151
|
+
# Count padding chars from the end
|
152
|
+
pad = 0; i = slen-1
|
153
|
+
while i > 0 && base64_char_map[str[i].ord] <= 0
|
154
|
+
pad += 1 if str[i] == PAD
|
155
|
+
i -= 1
|
156
|
+
end
|
157
|
+
|
158
|
+
# Preallocate String of exact length
|
159
|
+
len = ((slen - sepcnt) * 6 >> 3) - pad
|
160
|
+
bin = String.new(0, len)
|
161
|
+
|
162
|
+
# Go on decoding
|
163
|
+
s = 0; d = 0
|
164
|
+
while d < len
|
165
|
+
# Assemble 3 bytes into an int from 4 valid characters.
|
166
|
+
i = 0; j = 0
|
167
|
+
while j < 4
|
168
|
+
c = base64_char_map[str[s].ord]; s += 1
|
169
|
+
# j increases only if a valid char is found
|
170
|
+
if c != -1
|
171
|
+
i |= c << (18 - j * 6)
|
172
|
+
j += 1
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Now decode the int and add 3 chars to the bin string
|
177
|
+
bin[d] = (i >> 16 & 0xff).chr; d += 1
|
178
|
+
if d < len
|
179
|
+
bin[d] = (i >> 8 & 0xff).chr; d += 1
|
180
|
+
if d < len
|
181
|
+
bin[d] = (i & 0xff).chr; d += 1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
return bin
|
187
|
+
end
|
188
|
+
|
189
|
+
def self.decode64(str)
|
190
|
+
arg str: :String
|
191
|
+
result :String
|
192
|
+
self._decode64(str, BASE64_CHARS, BASE64_CHAR_MAP)
|
193
|
+
end
|
194
|
+
|
195
|
+
def self.encode64(bin)
|
196
|
+
arg bin: :String
|
197
|
+
result :String
|
198
|
+
self._encode64(bin, 1, BASE64_CHARS)
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.strict_decode64(str)
|
202
|
+
arg str: :String
|
203
|
+
self._decode64(str, BASE64_CHARS, BASE64_CHAR_MAP)
|
204
|
+
end
|
205
|
+
|
206
|
+
def self.strict_encode64(bin)
|
207
|
+
arg bin: :String
|
208
|
+
result :String
|
209
|
+
self._encode64(bin, 0, BASE64_CHARS)
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.urlsafe_decode64(str)
|
213
|
+
arg str: :String
|
214
|
+
self._decode64(str, BASE64_CHARS_URLSAFE, BASE64_CHAR_MAP_URLSAFE)
|
215
|
+
end
|
216
|
+
|
217
|
+
def self.urlsafe_encode64(bin)
|
218
|
+
arg bin: :String
|
219
|
+
result :String
|
220
|
+
self._encode64(bin, 0, BASE64_CHARS_URLSAFE)
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
data/lib/rlang/lib/io.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# IO class for all basic input and output operations
|
6
|
+
|
7
|
+
require_relative './wasi'
|
8
|
+
|
9
|
+
class IO
|
10
|
+
attr_accessor :fd
|
11
|
+
|
12
|
+
@@num_bytes_written = 0
|
13
|
+
@@num_bytes_read = 0
|
14
|
+
|
15
|
+
def initialize(fd)
|
16
|
+
@fd = fd
|
17
|
+
end
|
18
|
+
|
19
|
+
def write(stg)
|
20
|
+
arg stg: :String
|
21
|
+
ciovec = WASI::CIOVec.new(1)
|
22
|
+
ciovec << stg
|
23
|
+
errno = WASI.fd_write(@fd, ciovec.ciovs.ptr, 1, @@num_bytes_written.addr)
|
24
|
+
ciovec.free
|
25
|
+
errno
|
26
|
+
end
|
27
|
+
|
28
|
+
def print(stg)
|
29
|
+
self.write(stg)
|
30
|
+
end
|
31
|
+
|
32
|
+
def puts(stg)
|
33
|
+
arg stg: :String
|
34
|
+
result :none
|
35
|
+
ciovec = WASI::CIOVec.new(2)
|
36
|
+
ciovec << stg
|
37
|
+
ciovec << "\n"
|
38
|
+
errno = WASI.fd_write(@fd, ciovec.ciovs.ptr, 2, @@num_bytes_written.addr)
|
39
|
+
ciovec.free
|
40
|
+
end
|
41
|
+
|
42
|
+
def read
|
43
|
+
result :String
|
44
|
+
local stg: :String
|
45
|
+
iovec = WASI::IOVec.new(1)
|
46
|
+
errno = WASI.fd_read(@fd, iovec.iovs.ptr, 1, @@num_bytes_read.addr)
|
47
|
+
# -1 below because of \0 terminated string
|
48
|
+
stg = String.new(iovec.iovs[0], @@num_bytes_read-1)
|
49
|
+
# Nullify the iovs entry used by the String object so it is not freed
|
50
|
+
iovec.iovs[0] = 0
|
51
|
+
iovec.free
|
52
|
+
stg
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
STDIN = IO.new
|
58
|
+
STDOUT = IO.new
|
59
|
+
STDERR = IO.new
|
60
|
+
|
61
|
+
module Kernel
|
62
|
+
|
63
|
+
def puts(stg)
|
64
|
+
arg stg: :String
|
65
|
+
result :none
|
66
|
+
STDOUT.puts(stg)
|
67
|
+
end
|
68
|
+
|
69
|
+
def print(stg)
|
70
|
+
arg stg: :String
|
71
|
+
result :none
|
72
|
+
STDOUT.print(stg)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Kernel methods
|
6
|
+
#
|
7
|
+
# Most of the Kernel methods are defined in other files
|
8
|
+
# to avoid requiring classes that rely on Kernel methods
|
9
|
+
# themselves.
|
10
|
+
|
11
|
+
class String; end
|
12
|
+
|
13
|
+
module Kernel
|
14
|
+
|
15
|
+
def raise(msg)
|
16
|
+
arg msg: :String
|
17
|
+
result :none
|
18
|
+
#$! = msg
|
19
|
+
#STDERR.puts msg
|
20
|
+
inline wat: '(unreachable)', wtype: :none
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/rlang/lib/malloc.rb
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
# For a detailed explanation of the allocator code see
|
9
9
|
# https://gnuchops.wordpress.com/2013/02/26/memory-allocator-for-embedded-system-k-r-ritchie-book/
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
require_relative './memory'
|
12
|
+
require_relative './unistd'
|
13
13
|
|
14
14
|
# minimum number of units to request
|
15
15
|
$NALLOC = 1024
|
@@ -30,13 +30,14 @@ $NALLOC = 1024
|
|
30
30
|
|
31
31
|
# Allocate some unused memory space to make
|
32
32
|
# sure so that freep doesn't point to memory
|
33
|
-
# address 0 because it has a
|
34
|
-
# Allocate 20 bytes (
|
35
|
-
DAta
|
33
|
+
# address 0 because it has a special meaning
|
34
|
+
# Allocate 20 bytes (4 x I32 integers)
|
35
|
+
DAta.align(4)
|
36
|
+
DAta[:dummy_malloc_data] = [0, 0, 0, 0]
|
36
37
|
|
37
38
|
class Header
|
38
39
|
attr_accessor :ptr, :size
|
39
|
-
attr_type ptr: :Header, size: :
|
40
|
+
attr_type ptr: :Header, size: :UI32
|
40
41
|
end
|
41
42
|
|
42
43
|
class Malloc
|
@@ -47,13 +48,15 @@ class Malloc
|
|
47
48
|
# declare ahead of time because is used in
|
48
49
|
# the code before it is actually defined
|
49
50
|
result :Malloc, :free, :nil
|
51
|
+
result :Malloc, :morecore, :Header
|
50
52
|
|
51
53
|
# -------- Dynamic Memory Allocator Functions -----------
|
52
54
|
|
53
55
|
# malloc: allocate n bytes of memory and return pointer
|
54
56
|
# to data block
|
55
57
|
def self.malloc(nbytes)
|
56
|
-
|
58
|
+
arg nbytes: :UI32
|
59
|
+
local p: :Header, prevp: :Header, nunits: :UI32
|
57
60
|
|
58
61
|
# allocate memory by chunk of units (the unit is
|
59
62
|
# the size of a Header object here)
|
@@ -105,6 +108,7 @@ class Malloc
|
|
105
108
|
|
106
109
|
# morecore: ask system for more memory
|
107
110
|
def self.morecore(nu)
|
111
|
+
arg nu: :UI32
|
108
112
|
result :Header
|
109
113
|
local up: :Header
|
110
114
|
|
@@ -120,7 +124,7 @@ class Malloc
|
|
120
124
|
|
121
125
|
# Free memory block
|
122
126
|
def self.free(ap)
|
123
|
-
arg ap: :
|
127
|
+
arg ap: :UI32
|
124
128
|
result :none
|
125
129
|
local bp: :Header, p: :Header
|
126
130
|
|
data/lib/rlang/lib/memory.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Web Assembly memory access methods
|
6
|
+
#
|
2
7
|
|
3
8
|
class Memory
|
4
9
|
|
@@ -25,5 +30,100 @@ class Memory
|
|
25
30
|
idx += 1
|
26
31
|
end
|
27
32
|
end
|
28
|
-
|
33
|
+
|
34
|
+
def self.load32_8(addr)
|
35
|
+
arg addr: :I32
|
36
|
+
result :I32
|
37
|
+
inline wat: '(i32.load8_u (local.get $addr))',
|
38
|
+
wtype: :I32
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.load32_16(addr)
|
42
|
+
arg addr: :I32
|
43
|
+
result :I32
|
44
|
+
inline wat: '(i32.load16_u (local.get $addr))',
|
45
|
+
wtype: :I32
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.load32(addr)
|
49
|
+
arg addr: :I32
|
50
|
+
result :I32
|
51
|
+
inline wat: '(i32.load (local.get $addr))',
|
52
|
+
wtype: :I32
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.load64_8(addr)
|
56
|
+
arg addr: :I32
|
57
|
+
result :I64
|
58
|
+
inline wat: '(i64.load8_u (local.get $addr))',
|
59
|
+
wtype: :I64
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.load64_16(addr)
|
63
|
+
arg addr: :I32
|
64
|
+
result :I64
|
65
|
+
inline wat: '(i64.load16_u (local.get $addr))',
|
66
|
+
wtype: :I64
|
67
|
+
end
|
68
|
+
def self.load64_32(addr)
|
69
|
+
arg addr: :I32
|
70
|
+
result :I64
|
71
|
+
inline wat: '(i64.load32_u (local.get $addr))',
|
72
|
+
wtype: :I64
|
73
|
+
end
|
74
|
+
def self.load64(addr)
|
75
|
+
arg addr: :I32
|
76
|
+
result :I64
|
77
|
+
inline wat: '(i64.load (local.get $addr))',
|
78
|
+
wtype: :I64
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.store32_8(addr, value)
|
82
|
+
arg addr: :I32, value: :I32
|
83
|
+
result :none
|
84
|
+
inline wat: '(i32.store8 (local.get $addr) (local.get $value))',
|
85
|
+
wtype: :none
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.store32_16(addr, value)
|
89
|
+
arg addr: :I32, value: :I32
|
90
|
+
result :none
|
91
|
+
inline wat: '(i32.store16 (local.get $addr) (local.get $value))',
|
92
|
+
wtype: :none
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.store32(addr, value)
|
96
|
+
arg addr: :I32, value: :I32
|
97
|
+
result :none
|
98
|
+
inline wat: '(i32.store (local.get $addr) (local.get $value))',
|
99
|
+
wtype: :none
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.store64_8(addr, value)
|
103
|
+
arg addr: :I32, value: :I64
|
104
|
+
result :none
|
105
|
+
inline wat: '(i64.store8 (local.get $addr) (local.get $value))',
|
106
|
+
wtype: :none
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.store64_16(addr, value)
|
110
|
+
arg addr: :I32, value: :I64
|
111
|
+
result :none
|
112
|
+
inline wat: '(i64.store16 (local.get $addr) (local.get $value))',
|
113
|
+
wtype: :none
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.store64_32(addr, value)
|
117
|
+
arg addr: :I32, value: :I64
|
118
|
+
result :none
|
119
|
+
inline wat: '(i64.store32 (local.get $addr) (local.get $value))',
|
120
|
+
wtype: :none
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.store64(addr, value)
|
124
|
+
arg addr: :I32, value: :I64
|
125
|
+
result :none
|
126
|
+
inline wat: '(i64.store (local.get $addr) (local.get $value))',
|
127
|
+
wtype: :none
|
128
|
+
end
|
29
129
|
end
|
data/lib/rlang/lib/object.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Base Object class
|
6
|
+
|
1
7
|
require_relative './malloc'
|
8
|
+
require_relative './kernel'
|
9
|
+
require_relative './string'
|
2
10
|
|
3
11
|
class Object
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def self.
|
12
|
+
|
13
|
+
include Kernel
|
14
|
+
|
15
|
+
def self.allocate(nbytes)
|
8
16
|
result :I32
|
9
17
|
Malloc.malloc(nbytes)
|
10
18
|
end
|
@@ -13,4 +21,32 @@ class Object
|
|
13
21
|
result :none
|
14
22
|
Malloc.free(object_ptr)
|
15
23
|
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
result :String
|
27
|
+
"Object <addr>"
|
28
|
+
end
|
29
|
+
|
30
|
+
def object_id
|
31
|
+
result :I32
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def eql?(object)
|
36
|
+
result :I32
|
37
|
+
inline wat: '(i32.eq
|
38
|
+
(local.get $_self_)
|
39
|
+
(local.get $object))',
|
40
|
+
wtype: :I32,
|
41
|
+
ruby: 'self.object_id == object.object_id'
|
42
|
+
end
|
43
|
+
|
44
|
+
def ==(object)
|
45
|
+
self.eql?(object)
|
46
|
+
end
|
47
|
+
|
48
|
+
def !=(object)
|
49
|
+
!(self == object)
|
50
|
+
end
|
51
|
+
|
16
52
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Rlang standard library classes and modules
|
6
|
+
# and runtime initialization
|
7
|
+
#
|
8
|
+
require_relative './rlang_core'
|
9
|
+
require_relative './wasi'
|
10
|
+
require_relative './io'
|
11
|
+
|
12
|
+
class Rlang
|
13
|
+
def self.init
|
14
|
+
# WASI init: setup ARGC, ARGV, etc...
|
15
|
+
errno = WASI.init
|
16
|
+
|
17
|
+
# IO init: setup fd of stdin, out and err
|
18
|
+
# This code cannot be executed within io.rb
|
19
|
+
# as STDxxx can only be used after io.rb is
|
20
|
+
# compiled
|
21
|
+
STDIN.fd = WASI::STDIN_FD
|
22
|
+
STDOUT.fd = WASI::STDOUT_FD
|
23
|
+
STDERR.fd = WASI::STDERR_FD
|
24
|
+
$stdin = STDIN
|
25
|
+
$stdout = STDOUT
|
26
|
+
$stderr = STDERR
|
27
|
+
errno
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Rubinius WebAssembly VM
|
2
|
+
# Copyright (c) 2019-2020, Laurent Julliard and contributors
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Rlang core library classes and modules
|
6
|
+
#
|
7
|
+
|
8
|
+
require_relative './memory'
|
9
|
+
require_relative './unistd'
|
10
|
+
require_relative './malloc'
|
11
|
+
require_relative './object'
|
12
|
+
require_relative './kernel'
|
13
|
+
require_relative './string'
|
14
|
+
require_relative './array'
|
15
|
+
require_relative './type'
|