rubyduino 0.1.1 → 0.1.3
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 +12 -2
- data/README.md +7 -7
- data/bin/rubyduino +6 -1
- data/examples/hello.rb +5 -6
- data/lib/rubyduino/arduino_uno.rb +43 -0
- data/lib/rubyduino/sp_runtime.h +129 -18
- data/lib/rubyduino/spinel.rb +1 -1
- data/lib/rubyduino/spinel_arduino_codegen.rb +0 -41
- data/lib/rubyduino/version.rb +1 -1
- data/vendor/spinel/Makefile +29 -1
- data/vendor/spinel/spinel_codegen.rb +113 -5
- data/vendor/spinel/test/file_class_methods_int_recv.rb +20 -0
- data/vendor/spinel/test/file_class_methods_int_recv.rb.expected +3 -0
- data/vendor/spinel/test/float_array_sort.rb +18 -0
- data/vendor/spinel/test/float_array_sort.rb.expected +8 -0
- data/vendor/spinel/test/int_array_replace_expr.rb +23 -0
- data/vendor/spinel/test/int_array_replace_expr.rb.expected +7 -0
- data/vendor/spinel/test/integer_literal_no_int32_overflow.rb +29 -0
- data/vendor/spinel/test/integer_literal_no_int32_overflow.rb.expected +5 -0
- data/vendor/spinel/test/obj_class_returns_string.rb +24 -0
- data/vendor/spinel/test/obj_class_returns_string.rb.expected +2 -0
- metadata +12 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ec4285a969c2afed1449f750c1674b63f1ba5cb5b454994cfdb9356173595cb
|
|
4
|
+
data.tar.gz: 8e1dba9b348672d0aa96f4eb7645242da1e111fa36595c1f601ab9a1fa45acdf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 736ec9d0f9c5665ba2f88f647c36d0dcd1010a3e4d405d1a49a6032d1eaefaa60aecbd64a2d9e103796f9bf7443a8163370dc5951fdcd14bb589938452cc5ca7
|
|
7
|
+
data.tar.gz: 203d97b5aed491505f46e681d04aa4128dce2349ac93513d8cf307f1b8e96ddeaaa31478788c5f9aa919a028fe276cbab1b10a6c54466b69cf7ee17f2a1abc35
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
-
## [0.1.
|
|
3
|
+
## [0.1.3] - 2026-05-08
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- Add the built-in `ArduinoUNO` prelude with FFI-backed GPIO, analog read, and millisecond delay bindings
|
|
6
|
+
- Replace the legacy `system("pin13:*")` sketch API with top-level helpers like `pin_mode`, `digital_write`, and `delay_ms`
|
|
7
|
+
- Update the default hello example to use the new ArduinoUNO API
|
|
8
|
+
|
|
9
|
+
## [0.1.2] - 2026-05-08
|
|
10
|
+
|
|
11
|
+
- Update vendored Spinel revision
|
|
6
12
|
|
|
7
13
|
## [0.1.1] - 2026-05-08
|
|
8
14
|
|
|
9
15
|
- Fix avrdude discovery for installed command
|
|
16
|
+
|
|
17
|
+
## [0.1.0] - 2026-05-08
|
|
18
|
+
|
|
19
|
+
- Initial release
|
data/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# Rubyduino
|
|
3
|
+
# Rubyduino
|
|
4
|
+
[Experimental]
|
|
4
5
|
|
|
5
6
|
<img width="250" height="250" alt="image copy" src="https://github.com/user-attachments/assets/156c7d41-ed42-43f3-a720-ed2e9c12b52c" />
|
|
6
7
|
|
|
@@ -15,14 +16,13 @@ Under the hood it uses [Spinel](https://github.com/matz/spinel), a Ruby AOT comp
|
|
|
15
16
|
<img width="500" height="281" alt="IMG_0197" src="https://github.com/user-attachments/assets/d2b1cc69-647a-4f63-b090-31b13a21e5a8" />
|
|
16
17
|
|
|
17
18
|
```ruby
|
|
18
|
-
|
|
19
|
+
pin_mode(ArduinoUNO::LED_BUILTIN, ArduinoUNO::OUTPUT)
|
|
19
20
|
|
|
20
21
|
loop do
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
sleep duration
|
|
22
|
+
digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::HIGH)
|
|
23
|
+
delay_ms(100)
|
|
24
|
+
digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::LOW)
|
|
25
|
+
delay_ms(100)
|
|
26
26
|
end
|
|
27
27
|
```
|
|
28
28
|
|
data/bin/rubyduino
CHANGED
|
@@ -98,6 +98,7 @@ rubyduino_dir = File.join(root_dir, "lib/rubyduino")
|
|
|
98
98
|
parse_bin = File.join(spinel_dir, "spinel_parse")
|
|
99
99
|
codegen_rb = File.join(rubyduino_dir, "spinel_arduino_codegen.rb")
|
|
100
100
|
entry_c = File.join(rubyduino_dir, "arduino_entry.c")
|
|
101
|
+
arduino_uno_rb = File.join(rubyduino_dir, "arduino_uno.rb")
|
|
101
102
|
|
|
102
103
|
mcu = "atmega328p"
|
|
103
104
|
f_cpu = "16000000UL"
|
|
@@ -137,6 +138,7 @@ abort "rubyduino: #{source}: No such file" unless File.file?(source)
|
|
|
137
138
|
abort "rubyduino: missing Spinel checkout at #{spinel_dir}" unless Dir.exist?(spinel_dir)
|
|
138
139
|
abort "rubyduino: missing #{codegen_rb}" unless File.file?(codegen_rb)
|
|
139
140
|
abort "rubyduino: missing #{entry_c}" unless File.file?(entry_c)
|
|
141
|
+
abort "rubyduino: missing #{arduino_uno_rb}" unless File.file?(arduino_uno_rb)
|
|
140
142
|
abort "rubyduino: avr-gcc not found" unless command?("avr-gcc")
|
|
141
143
|
abort "rubyduino: avr-objcopy not found" unless command?("avr-objcopy")
|
|
142
144
|
|
|
@@ -164,9 +166,11 @@ avrdude = find_avrdude
|
|
|
164
166
|
abort "rubyduino: avrdude not found" unless avrdude
|
|
165
167
|
|
|
166
168
|
ast_tmp = File.join(Dir.tmpdir, "spinel_arduino_ast.#{$PROCESS_ID}.#{rand(1_000_000)}")
|
|
169
|
+
source_tmp = File.join(Dir.tmpdir, "rubyduino_source.#{$PROCESS_ID}.#{rand(1_000_000)}.rb")
|
|
167
170
|
begin
|
|
168
171
|
warn "Spinel: #{source} -> #{c_file}"
|
|
169
|
-
|
|
172
|
+
File.write(source_tmp, "#{File.read(arduino_uno_rb)}\n#{File.read(source)}")
|
|
173
|
+
run!(parse_bin, source_tmp, ast_tmp)
|
|
170
174
|
run!(RbConfig.ruby, codegen_rb, ast_tmp, c_file)
|
|
171
175
|
|
|
172
176
|
warn "AVR: #{c_file} -> #{hex_file}"
|
|
@@ -183,4 +187,5 @@ begin
|
|
|
183
187
|
run!(avrdude, *conf_args, "-p#{mcu}", "-carduino", "-P#{port}", "-b#{baud}", "-D", "-Uflash:w:#{hex_file}:i")
|
|
184
188
|
ensure
|
|
185
189
|
FileUtils.rm_f(ast_tmp)
|
|
190
|
+
FileUtils.rm_f(source_tmp)
|
|
186
191
|
end
|
data/examples/hello.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
pin_mode(ArduinoUNO::LED_BUILTIN, ArduinoUNO::OUTPUT)
|
|
2
2
|
|
|
3
3
|
loop do
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
sleep duration
|
|
4
|
+
digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::HIGH)
|
|
5
|
+
delay_ms(100)
|
|
6
|
+
digital_write(ArduinoUNO::LED_BUILTIN, ArduinoUNO::LOW)
|
|
7
|
+
delay_ms(100)
|
|
9
8
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module ArduinoUNO
|
|
2
|
+
LOW = 0
|
|
3
|
+
HIGH = 1
|
|
4
|
+
|
|
5
|
+
INPUT = 0
|
|
6
|
+
OUTPUT = 1
|
|
7
|
+
INPUT_PULLUP = 2
|
|
8
|
+
|
|
9
|
+
A0 = 14
|
|
10
|
+
A1 = 15
|
|
11
|
+
A2 = 16
|
|
12
|
+
A3 = 17
|
|
13
|
+
A4 = 18
|
|
14
|
+
A5 = 19
|
|
15
|
+
|
|
16
|
+
LED_BUILTIN = 13
|
|
17
|
+
|
|
18
|
+
ffi_func :pin_mode, [:uint8, :uint8], :int
|
|
19
|
+
ffi_func :digital_write, [:uint8, :uint8], :int
|
|
20
|
+
ffi_func :digital_read, [:uint8], :int
|
|
21
|
+
ffi_func :analog_read, [:uint8], :int
|
|
22
|
+
ffi_func :delay_ms, [:uint32], :void
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def pin_mode(pin, mode)
|
|
26
|
+
ArduinoUNO.pin_mode(pin, mode)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def digital_write(pin, value)
|
|
30
|
+
ArduinoUNO.digital_write(pin, value)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def digital_read(pin)
|
|
34
|
+
ArduinoUNO.digital_read(pin)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def analog_read(pin)
|
|
38
|
+
ArduinoUNO.analog_read(pin)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def delay_ms(ms)
|
|
42
|
+
ArduinoUNO.delay_ms(ms)
|
|
43
|
+
end
|
data/lib/rubyduino/sp_runtime.h
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include <stdint.h>
|
|
5
5
|
#include <stdlib.h>
|
|
6
|
+
#include <string.h>
|
|
6
7
|
#include <avr/io.h>
|
|
7
8
|
#include <util/delay.h>
|
|
8
9
|
#include <util/delay_basic.h>
|
|
@@ -46,6 +47,7 @@ static void sp_gc_mark(void *ptr) {
|
|
|
46
47
|
|
|
47
48
|
typedef struct {
|
|
48
49
|
mrb_int *data;
|
|
50
|
+
mrb_int start;
|
|
49
51
|
mrb_int len;
|
|
50
52
|
mrb_int cap;
|
|
51
53
|
} sp_IntArray;
|
|
@@ -69,6 +71,7 @@ static sp_Range sp_range_new(mrb_int first, mrb_int last) {
|
|
|
69
71
|
|
|
70
72
|
static sp_IntArray *sp_IntArray_new(void) {
|
|
71
73
|
sp_IntArray *array = (sp_IntArray *)malloc(sizeof(sp_IntArray));
|
|
74
|
+
array->start = 0;
|
|
72
75
|
array->len = 0;
|
|
73
76
|
array->cap = 4;
|
|
74
77
|
array->data = (mrb_int *)malloc(sizeof(mrb_int) * array->cap);
|
|
@@ -80,7 +83,7 @@ static void sp_IntArray_push(sp_IntArray *array, mrb_int value) {
|
|
|
80
83
|
array->cap *= 2;
|
|
81
84
|
array->data = (mrb_int *)realloc(array->data, sizeof(mrb_int) * array->cap);
|
|
82
85
|
}
|
|
83
|
-
array->data[array->len] = value;
|
|
86
|
+
array->data[array->start + array->len] = value;
|
|
84
87
|
array->len++;
|
|
85
88
|
}
|
|
86
89
|
|
|
@@ -89,7 +92,7 @@ static mrb_int sp_IntArray_length(sp_IntArray *array) {
|
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
static mrb_int sp_IntArray_get(sp_IntArray *array, mrb_int index) {
|
|
92
|
-
return array->data[index];
|
|
95
|
+
return array->data[array->start + index];
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
static sp_FloatArray *sp_FloatArray_new(void) {
|
|
@@ -117,30 +120,140 @@ static mrb_float sp_FloatArray_get(sp_FloatArray *array, mrb_int index) {
|
|
|
117
120
|
return array->data[index];
|
|
118
121
|
}
|
|
119
122
|
|
|
120
|
-
static int
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
123
|
+
static int rd_uno_valid_pin(uint8_t pin) {
|
|
124
|
+
return pin <= 19;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static volatile uint8_t *rd_uno_ddr(uint8_t pin) {
|
|
128
|
+
if (pin <= 7) {
|
|
129
|
+
return &DDRD;
|
|
124
130
|
}
|
|
125
|
-
|
|
131
|
+
if (pin <= 13) {
|
|
132
|
+
return &DDRB;
|
|
133
|
+
}
|
|
134
|
+
if (pin <= 19) {
|
|
135
|
+
return &DDRC;
|
|
136
|
+
}
|
|
137
|
+
return NULL;
|
|
126
138
|
}
|
|
127
139
|
|
|
128
|
-
static
|
|
129
|
-
if (
|
|
130
|
-
|
|
140
|
+
static volatile uint8_t *rd_uno_port(uint8_t pin) {
|
|
141
|
+
if (pin <= 7) {
|
|
142
|
+
return &PORTD;
|
|
143
|
+
}
|
|
144
|
+
if (pin <= 13) {
|
|
145
|
+
return &PORTB;
|
|
146
|
+
}
|
|
147
|
+
if (pin <= 19) {
|
|
148
|
+
return &PORTC;
|
|
149
|
+
}
|
|
150
|
+
return NULL;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static volatile uint8_t *rd_uno_pin_reg(uint8_t pin) {
|
|
154
|
+
if (pin <= 7) {
|
|
155
|
+
return &PIND;
|
|
156
|
+
}
|
|
157
|
+
if (pin <= 13) {
|
|
158
|
+
return &PINB;
|
|
159
|
+
}
|
|
160
|
+
if (pin <= 19) {
|
|
161
|
+
return &PINC;
|
|
162
|
+
}
|
|
163
|
+
return NULL;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
static uint8_t rd_uno_bit(uint8_t pin) {
|
|
167
|
+
if (pin <= 7) {
|
|
168
|
+
return pin;
|
|
169
|
+
}
|
|
170
|
+
if (pin <= 13) {
|
|
171
|
+
return pin - 8;
|
|
172
|
+
}
|
|
173
|
+
return pin - 14;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
int pin_mode(uint8_t pin, uint8_t mode) {
|
|
177
|
+
volatile uint8_t *ddr = rd_uno_ddr(pin);
|
|
178
|
+
volatile uint8_t *port = rd_uno_port(pin);
|
|
179
|
+
uint8_t mask;
|
|
180
|
+
|
|
181
|
+
if (!ddr || !port) {
|
|
182
|
+
return 1;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
mask = (uint8_t)(1 << rd_uno_bit(pin));
|
|
186
|
+
|
|
187
|
+
if (mode == 1) {
|
|
188
|
+
*ddr |= mask;
|
|
131
189
|
return 0;
|
|
132
190
|
}
|
|
133
|
-
|
|
134
|
-
|
|
191
|
+
|
|
192
|
+
if (mode == 0) {
|
|
193
|
+
*ddr &= (uint8_t)~mask;
|
|
194
|
+
*port &= (uint8_t)~mask;
|
|
135
195
|
return 0;
|
|
136
196
|
}
|
|
137
|
-
|
|
138
|
-
|
|
197
|
+
|
|
198
|
+
if (mode == 2) {
|
|
199
|
+
*ddr &= (uint8_t)~mask;
|
|
200
|
+
*port |= mask;
|
|
139
201
|
return 0;
|
|
140
202
|
}
|
|
203
|
+
|
|
141
204
|
return 1;
|
|
142
205
|
}
|
|
143
206
|
|
|
207
|
+
int digital_write(uint8_t pin, uint8_t value) {
|
|
208
|
+
volatile uint8_t *port = rd_uno_port(pin);
|
|
209
|
+
uint8_t mask;
|
|
210
|
+
|
|
211
|
+
if (!port) {
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
mask = (uint8_t)(1 << rd_uno_bit(pin));
|
|
216
|
+
|
|
217
|
+
if (value) {
|
|
218
|
+
*port |= mask;
|
|
219
|
+
} else {
|
|
220
|
+
*port &= (uint8_t)~mask;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return 0;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
int digital_read(uint8_t pin) {
|
|
227
|
+
volatile uint8_t *reg = rd_uno_pin_reg(pin);
|
|
228
|
+
|
|
229
|
+
if (!reg) {
|
|
230
|
+
return -1;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return ((*reg & (uint8_t)(1 << rd_uno_bit(pin))) != 0) ? 1 : 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
int analog_read(uint8_t pin) {
|
|
237
|
+
uint8_t channel = pin;
|
|
238
|
+
|
|
239
|
+
if (pin >= 14 && pin <= 19) {
|
|
240
|
+
channel = pin - 14;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (channel > 5 || !rd_uno_valid_pin(pin)) {
|
|
244
|
+
return -1;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
ADMUX = (uint8_t)((1 << REFS0) | channel);
|
|
248
|
+
ADCSRA = (uint8_t)((1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0));
|
|
249
|
+
ADCSRA |= (uint8_t)(1 << ADSC);
|
|
250
|
+
|
|
251
|
+
while (ADCSRA & (uint8_t)(1 << ADSC)) {
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return ADC;
|
|
255
|
+
}
|
|
256
|
+
|
|
144
257
|
static void sp_arduino_delay_ms(unsigned long ms) {
|
|
145
258
|
while (ms > 0) {
|
|
146
259
|
_delay_loop_2((uint16_t)(F_CPU / 4000UL));
|
|
@@ -148,12 +261,10 @@ static void sp_arduino_delay_ms(unsigned long ms) {
|
|
|
148
261
|
}
|
|
149
262
|
}
|
|
150
263
|
|
|
151
|
-
|
|
152
|
-
sp_arduino_delay_ms(
|
|
264
|
+
void delay_ms(uint32_t ms) {
|
|
265
|
+
sp_arduino_delay_ms(ms);
|
|
153
266
|
}
|
|
154
267
|
|
|
155
|
-
#define system(cmd) sp_arduino_system(cmd)
|
|
156
|
-
#define sleep(seconds) sp_arduino_delay_ms((unsigned long)((seconds) * 1000.0 + 0.5))
|
|
157
268
|
#define fflush(stream) ((void)0)
|
|
158
269
|
|
|
159
270
|
#endif
|
data/lib/rubyduino/spinel.rb
CHANGED
|
@@ -26,9 +26,6 @@ load_spinel_compiler
|
|
|
26
26
|
module SpinelArduinoCodegen
|
|
27
27
|
def compile_no_recv_call_expr(nid, mname)
|
|
28
28
|
case mname
|
|
29
|
-
when "sleep"
|
|
30
|
-
compile_arduino_sleep(nid)
|
|
31
|
-
"0"
|
|
32
29
|
when "rand"
|
|
33
30
|
arduino_rand = compile_arduino_rand(nid)
|
|
34
31
|
return arduino_rand if arduino_rand
|
|
@@ -41,21 +38,6 @@ module SpinelArduinoCodegen
|
|
|
41
38
|
|
|
42
39
|
private
|
|
43
40
|
|
|
44
|
-
def compile_arduino_sleep(nid)
|
|
45
|
-
args_id = @nd_arguments[nid]
|
|
46
|
-
return if args_id < 0
|
|
47
|
-
|
|
48
|
-
arg_ids = get_args(args_id)
|
|
49
|
-
return if arg_ids.empty?
|
|
50
|
-
|
|
51
|
-
arg = arg_ids.first
|
|
52
|
-
if numeric_literal_node?(arg)
|
|
53
|
-
emit_arduino_delay_literal(numeric_literal_value(arg))
|
|
54
|
-
else
|
|
55
|
-
emit(" sp_arduino_sleep_seconds(" + compile_expr(arg) + ");")
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
41
|
def compile_arduino_rand(nid)
|
|
60
42
|
args_id = @nd_arguments[nid]
|
|
61
43
|
return nil if args_id < 0
|
|
@@ -79,32 +61,9 @@ module SpinelArduinoCodegen
|
|
|
79
61
|
"((mrb_int)(#{first} + (rand() % #{span})))"
|
|
80
62
|
end
|
|
81
63
|
|
|
82
|
-
def emit_arduino_delay_literal(seconds)
|
|
83
|
-
ms = (seconds * 1000.0).round
|
|
84
|
-
parts = []
|
|
85
|
-
while ms >= 250
|
|
86
|
-
parts << "_delay_ms(250.0)"
|
|
87
|
-
ms -= 250
|
|
88
|
-
end
|
|
89
|
-
parts << "_delay_ms(#{ms}.0)" if ms > 0
|
|
90
|
-
emit(" " + parts.join("; ") + ";") unless parts.empty?
|
|
91
|
-
end
|
|
92
|
-
|
|
93
64
|
def integer_literal_node?(nid)
|
|
94
65
|
nid && nid >= 0 && @nd_type[nid] == "IntegerNode"
|
|
95
66
|
end
|
|
96
|
-
|
|
97
|
-
def numeric_literal_node?(nid)
|
|
98
|
-
nid && nid >= 0 && %w[IntegerNode FloatNode].include?(@nd_type[nid])
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def numeric_literal_value(nid)
|
|
102
|
-
if @nd_type[nid] == "IntegerNode"
|
|
103
|
-
@nd_value[nid].to_f
|
|
104
|
-
else
|
|
105
|
-
@nd_content[nid].to_f
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
67
|
end
|
|
109
68
|
|
|
110
69
|
Compiler.prepend(SpinelArduinoCodegen)
|
data/lib/rubyduino/version.rb
CHANGED
data/vendor/spinel/Makefile
CHANGED
|
@@ -122,7 +122,7 @@ PRISM_LIB = build/libprism.a
|
|
|
122
122
|
CODEGEN_STAMP := build/stamps/spinel_codegen.rb.stamp
|
|
123
123
|
PARSE_STAMP := build/stamps/spinel_parse.c.stamp
|
|
124
124
|
|
|
125
|
-
.PHONY: all parse bootstrap codegen test retest clean-test-results regen-expected bench clean install uninstall deps
|
|
125
|
+
.PHONY: all parse bootstrap codegen test retest clean-test-results regen-expected bench optcarrot clean install uninstall deps
|
|
126
126
|
|
|
127
127
|
all: parse regexp spinel_codegen$(EXE)
|
|
128
128
|
|
|
@@ -378,6 +378,34 @@ bench: spinel_parse$(EXE) $(SP_RT_LIB) spinel_codegen$(EXE)
|
|
|
378
378
|
echo "Benchmarks: $$pass pass, $$fail fail, $$err error, $$skip skip"; \
|
|
379
379
|
if [ $$fail -ne 0 ] || [ $$err -ne 0 ]; then exit 1; fi
|
|
380
380
|
|
|
381
|
+
# ---- Optcarrot integration test ----
|
|
382
|
+
#
|
|
383
|
+
# End-to-end pipeline: clone optcarrot's `experiment/spinel` branch,
|
|
384
|
+
# pack `lib/optcarrot/*.rb` into a single Ruby file via the upstream
|
|
385
|
+
# `tools/pack-for-spinel.rb`, compile through spinel, run the
|
|
386
|
+
# resulting binary against `examples/Lan_Master.nes`, and verify the
|
|
387
|
+
# output contains `fps: <num>` and `checksum: 59662` (the canonical
|
|
388
|
+
# 180-frame checksum for `--benchmark`).
|
|
389
|
+
|
|
390
|
+
OPTCARROT_DIR := build/optcarrot
|
|
391
|
+
OPTCARROT_REPO := https://github.com/mame/optcarrot.git
|
|
392
|
+
OPTCARROT_BRANCH := experiment/spinel
|
|
393
|
+
|
|
394
|
+
optcarrot: spinel_parse$(EXE) $(SP_RT_LIB) spinel_codegen$(EXE)
|
|
395
|
+
@if [ ! -d $(OPTCARROT_DIR) ]; then \
|
|
396
|
+
git clone --depth=1 --branch=$(OPTCARROT_BRANCH) $(OPTCARROT_REPO) $(OPTCARROT_DIR); \
|
|
397
|
+
fi
|
|
398
|
+
@ruby $(OPTCARROT_DIR)/tools/pack-for-spinel.rb > build/optcarrot-single.rb
|
|
399
|
+
@./spinel build/optcarrot-single.rb -o build/optcarrot-single
|
|
400
|
+
@out=$$($(TIMEOUT60) ./build/optcarrot-single 2>&1); \
|
|
401
|
+
echo "$$out"; \
|
|
402
|
+
if echo "$$out" | grep -qE "^fps: [0-9.]+$$" && echo "$$out" | grep -q "^checksum: 59662$$"; then \
|
|
403
|
+
echo "Optcarrot: OK"; \
|
|
404
|
+
else \
|
|
405
|
+
echo "Optcarrot: FAIL — expected 'fps: <num>' and 'checksum: 59662'"; \
|
|
406
|
+
exit 1; \
|
|
407
|
+
fi
|
|
408
|
+
|
|
381
409
|
# ---- Install ----
|
|
382
410
|
|
|
383
411
|
PREFIX ?= /usr/local
|
|
@@ -2934,6 +2934,18 @@ class Compiler
|
|
|
2934
2934
|
end
|
|
2935
2935
|
end
|
|
2936
2936
|
|
|
2937
|
+
# `<obj>.class` returns the class name as a string (Spinel
|
|
2938
|
+
# collapses Class/Module objects to their textual name; the
|
|
2939
|
+
# only consumers in practice are interpolation
|
|
2940
|
+
# `"#<#{self.class}>"` and `.to_s.split` chains, both of
|
|
2941
|
+
# which work fine on a plain string).
|
|
2942
|
+
if recv >= 0 && mname == "class"
|
|
2943
|
+
rt = infer_type(recv)
|
|
2944
|
+
if is_obj_type(rt) == 1
|
|
2945
|
+
return "string"
|
|
2946
|
+
end
|
|
2947
|
+
end
|
|
2948
|
+
|
|
2937
2949
|
# `recv.__sp_ieval_<N>(...)`: the rewritten form of an
|
|
2938
2950
|
# `recv.instance_eval { ... }` call. v1 only fired on top-level call
|
|
2939
2951
|
# sites, where the call's value was always discarded — so its return
|
|
@@ -3994,6 +4006,16 @@ class Compiler
|
|
|
3994
4006
|
end
|
|
3995
4007
|
return "int_array"
|
|
3996
4008
|
end
|
|
4009
|
+
# `replace(other)` returns the receiver, not a fresh array;
|
|
4010
|
+
# the inferred result must therefore preserve the receiver's
|
|
4011
|
+
# array type so that an expression-form `c = a.replace(b)`
|
|
4012
|
+
# still tags `c` as `int_array` (or whatever `a` is) rather
|
|
4013
|
+
# than falling through to `int`.
|
|
4014
|
+
if mname == "replace"
|
|
4015
|
+
if recv >= 0
|
|
4016
|
+
return infer_type(recv)
|
|
4017
|
+
end
|
|
4018
|
+
end
|
|
3997
4019
|
if mname == "pop"
|
|
3998
4020
|
if recv >= 0
|
|
3999
4021
|
rt = infer_type(recv)
|
|
@@ -4643,7 +4665,7 @@ class Compiler
|
|
|
4643
4665
|
if mname == "read" || mname == "binread"
|
|
4644
4666
|
return "string"
|
|
4645
4667
|
end
|
|
4646
|
-
if mname == "exist?"
|
|
4668
|
+
if mname == "exist?" || mname == "readable?"
|
|
4647
4669
|
return "bool"
|
|
4648
4670
|
end
|
|
4649
4671
|
if mname == "join"
|
|
@@ -17819,6 +17841,14 @@ class Compiler
|
|
|
17819
17841
|
|
|
17820
17842
|
# ---- Forward declarations ----
|
|
17821
17843
|
def emit_forward_decls
|
|
17844
|
+
# ARGV (sp_argv) is referenced from any function that uses
|
|
17845
|
+
# `ARGV.length` / `ARGV[i]`, so the declaration has to precede
|
|
17846
|
+
# all function bodies — not just main()'s. emit_main keeps the
|
|
17847
|
+
# runtime initialization (`sp_argv.len = argc - 1; ...`) where
|
|
17848
|
+
# main() can fill it in from `argc` / `argv`.
|
|
17849
|
+
emit_raw("typedef struct{const char**data;mrb_int len;}sp_Argv;")
|
|
17850
|
+
emit_raw("static sp_Argv sp_argv;")
|
|
17851
|
+
emit_raw("")
|
|
17822
17852
|
# Emit block helper functions accumulated during collection
|
|
17823
17853
|
if @block_funcs != ""
|
|
17824
17854
|
emit_raw(@block_funcs)
|
|
@@ -20806,9 +20836,6 @@ class Compiler
|
|
|
20806
20836
|
|
|
20807
20837
|
def emit_main
|
|
20808
20838
|
stmts = get_body_stmts(@root_id)
|
|
20809
|
-
emit_raw("typedef struct{const char**data;mrb_int len;}sp_Argv;")
|
|
20810
|
-
emit_raw("static sp_Argv sp_argv;")
|
|
20811
|
-
emit_raw("")
|
|
20812
20839
|
emit_raw("int main(int argc,char**argv){")
|
|
20813
20840
|
emit_raw(" sp_argv.len=argc-1;sp_argv.data=(const char**)malloc(sizeof(const char*)*(argc>1?argc-1:1));{int _i;for(_i=0;_i<sp_argv.len;_i++)sp_argv.data[_i]=sp_str_dup_external(argv[_i+1]);}")
|
|
20814
20841
|
if @needs_rand == 1
|
|
@@ -21303,7 +21330,16 @@ class Compiler
|
|
|
21303
21330
|
exit(1)
|
|
21304
21331
|
end
|
|
21305
21332
|
if t == "IntegerNode"
|
|
21306
|
-
|
|
21333
|
+
# Suffix with `LL` so the literal is `long long` rather than
|
|
21334
|
+
# `int` in the emitted C. Without it, an expression of int
|
|
21335
|
+
# literals whose product exceeds int32 (e.g. APU mixer
|
|
21336
|
+
# constant `24329 * 256 * 500 = 3,114,112,000`) overflows
|
|
21337
|
+
# at constant-folding time and the C compiler emits a wrong
|
|
21338
|
+
# value. Plain literals at runtime sites get implicitly
|
|
21339
|
+
# promoted to mrb_int (= long long) on assignment, but
|
|
21340
|
+
# constant-init expressions are evaluated by the C compiler
|
|
21341
|
+
# using the literals' declared type.
|
|
21342
|
+
return @nd_value[nid].to_s + "LL"
|
|
21307
21343
|
end
|
|
21308
21344
|
if t == "FloatNode"
|
|
21309
21345
|
return @nd_content[nid]
|
|
@@ -26285,6 +26321,37 @@ class Compiler
|
|
|
26285
26321
|
end
|
|
26286
26322
|
return "sp_IntArray_sort(" + rc + ")"
|
|
26287
26323
|
end
|
|
26324
|
+
# `pack("C*")` — the only format Spinel implements: each
|
|
26325
|
+
# int element is written as a byte into a freshly allocated
|
|
26326
|
+
# NUL-terminated string. Sufficient for the optcarrot save-
|
|
26327
|
+
# RAM `@wrk.pack("C*")` shape and the symmetric inverse of
|
|
26328
|
+
# `String#bytes` we already support. Other format strings
|
|
26329
|
+
# fall through to the unresolved-call warning.
|
|
26330
|
+
if mname == "pack" && recv_type == "int_array"
|
|
26331
|
+
args_id = @nd_arguments[nid]
|
|
26332
|
+
if args_id >= 0
|
|
26333
|
+
a_pk = get_args(args_id)
|
|
26334
|
+
if a_pk.length == 1 && @nd_type[a_pk[0]] == "StringNode" && @nd_content[a_pk[0]] == "C*"
|
|
26335
|
+
tmp = new_temp
|
|
26336
|
+
ntmp = new_temp
|
|
26337
|
+
itmp = new_temp
|
|
26338
|
+
emit(" mrb_int " + ntmp + " = sp_IntArray_length(" + rc + ");")
|
|
26339
|
+
emit(" char *" + tmp + " = sp_str_alloc(" + ntmp + ");")
|
|
26340
|
+
emit(" for (mrb_int " + itmp + " = 0; " + itmp + " < " + ntmp + "; " + itmp + "++) " + tmp + "[" + itmp + "] = (char)sp_IntArray_get(" + rc + ", " + itmp + ");")
|
|
26341
|
+
emit(" " + tmp + "[" + ntmp + "] = 0;")
|
|
26342
|
+
return tmp
|
|
26343
|
+
end
|
|
26344
|
+
end
|
|
26345
|
+
end
|
|
26346
|
+
# `replace(other)` in expression position: the stmt-form
|
|
26347
|
+
# arm in compile_*_stmt only fires when the call's value is
|
|
26348
|
+
# discarded; in expression position (e.g. last stmt of a
|
|
26349
|
+
# method body, or rvalue of an assignment) we still need to
|
|
26350
|
+
# emit the side effect *and* yield the receiver as the
|
|
26351
|
+
# value. Use the comma operator so the result is `rc`.
|
|
26352
|
+
if mname == "replace" && recv_type == "int_array"
|
|
26353
|
+
return "(sp_IntArray_replace(" + rc + ", " + compile_arg0(nid) + "), " + rc + ")"
|
|
26354
|
+
end
|
|
26288
26355
|
# take_while / drop_while: block-driven prefix scan. take_while
|
|
26289
26356
|
# collects elements from the front while the block stays truthy;
|
|
26290
26357
|
# drop_while skips them and returns the rest. Mirrors the
|
|
@@ -26539,6 +26606,14 @@ class Compiler
|
|
|
26539
26606
|
if mname == "difference"
|
|
26540
26607
|
return "sp_FloatArray_difference(" + rc + ", " + compile_arg0(nid) + ")"
|
|
26541
26608
|
end
|
|
26609
|
+
if mname == "sort"
|
|
26610
|
+
# Non-bang: yield a fresh sorted copy. Mirror the
|
|
26611
|
+
# `sp_FloatArray_shuffle` pattern (new + replace) so the
|
|
26612
|
+
# source array is left untouched.
|
|
26613
|
+
tmp = new_temp
|
|
26614
|
+
emit(" sp_FloatArray *" + tmp + " = sp_FloatArray_new(); sp_FloatArray_replace(" + tmp + ", " + rc + "); sp_FloatArray_sort_bang(" + tmp + ");")
|
|
26615
|
+
return tmp
|
|
26616
|
+
end
|
|
26542
26617
|
end
|
|
26543
26618
|
if is_ptr_array_type(recv_type) == 1
|
|
26544
26619
|
elem_type = ptr_array_elem_type(recv_type)
|
|
@@ -27529,9 +27604,32 @@ class Compiler
|
|
|
27529
27604
|
if mname == "exist?"
|
|
27530
27605
|
return "sp_file_exist(" + compile_arg0(nid) + ")"
|
|
27531
27606
|
end
|
|
27607
|
+
if mname == "readable?"
|
|
27608
|
+
# Reuse the exist check: on every platform Spinel
|
|
27609
|
+
# targets, a fopen-able file is also readable from
|
|
27610
|
+
# the same process. Distinguishing the two would
|
|
27611
|
+
# need access(2), which isn't worth a runtime fn for
|
|
27612
|
+
# the dead-code optcarrot battery-save path that
|
|
27613
|
+
# surfaced this.
|
|
27614
|
+
return "sp_file_exist(" + compile_arg0(nid) + ")"
|
|
27615
|
+
end
|
|
27532
27616
|
if mname == "delete"
|
|
27533
27617
|
return "(sp_file_delete(" + compile_arg0(nid) + "), 0)"
|
|
27534
27618
|
end
|
|
27619
|
+
if mname == "binwrite"
|
|
27620
|
+
# NOTE: `sp_file_write` uses fputs, so an embedded NUL
|
|
27621
|
+
# in the payload truncates the write — fine for the
|
|
27622
|
+
# optcarrot save-RAM dead-code path that surfaced
|
|
27623
|
+
# this, not safe for general binary use.
|
|
27624
|
+
args_id_bw = @nd_arguments[nid]
|
|
27625
|
+
if args_id_bw >= 0
|
|
27626
|
+
a_bw = get_args(args_id_bw)
|
|
27627
|
+
if a_bw.length >= 2
|
|
27628
|
+
return "(sp_file_write(" + compile_expr(a_bw[0]) + ", " + compile_expr(a_bw[1]) + "), 0)"
|
|
27629
|
+
end
|
|
27630
|
+
end
|
|
27631
|
+
return "0"
|
|
27632
|
+
end
|
|
27535
27633
|
if mname == "join"
|
|
27536
27634
|
args_id = @nd_arguments[nid]
|
|
27537
27635
|
if args_id >= 0
|
|
@@ -27864,6 +27962,16 @@ class Compiler
|
|
|
27864
27962
|
if @cls_is_value_type[ci] == 1
|
|
27865
27963
|
arrow = "."
|
|
27866
27964
|
end
|
|
27965
|
+
# `<obj>.class` — collapse to the class name as a string
|
|
27966
|
+
# literal. Spinel doesn't allocate runtime Class objects,
|
|
27967
|
+
# but the typical consumers (interpolation in inspect,
|
|
27968
|
+
# `.to_s.split("::").last` shape) all treat the result as
|
|
27969
|
+
# a string. Underscore-flattened nested module names
|
|
27970
|
+
# (`Optcarrot_NES`) render as-is rather than the original
|
|
27971
|
+
# `Optcarrot::NES` form; the loss is cosmetic.
|
|
27972
|
+
if mname == "class"
|
|
27973
|
+
return c_string_literal(cname)
|
|
27974
|
+
end
|
|
27867
27975
|
# attr_reader
|
|
27868
27976
|
readers = @cls_attr_readers[ci].split(";")
|
|
27869
27977
|
j = 0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# `File.readable?` and `File.binwrite` — class-method stubs in
|
|
2
|
+
# the `rcname == "File"` dispatch block, plus `IntArray#pack("C*")`
|
|
3
|
+
# which is the symmetric inverse of `String#bytes`.
|
|
4
|
+
#
|
|
5
|
+
# Surfaced via optcarrot's battery-save dead code path:
|
|
6
|
+
# `return unless File.readable?(sav)` and
|
|
7
|
+
# `File.binwrite(sav, @wrk.pack("C*"))`.
|
|
8
|
+
#
|
|
9
|
+
# `readable?` reuses the exist check (close enough on POSIX).
|
|
10
|
+
# `binwrite` reuses `sp_file_write` — fputs-based, so embedded
|
|
11
|
+
# NULs truncate; acceptable for the NUL-free use sites that
|
|
12
|
+
# exist in practice.
|
|
13
|
+
|
|
14
|
+
path = "/tmp/spinel_file_class_test"
|
|
15
|
+
|
|
16
|
+
File.binwrite(path, [72, 105, 33].pack("C*")) # "Hi!"
|
|
17
|
+
puts File.readable?(path)
|
|
18
|
+
puts File.read(path)
|
|
19
|
+
File.delete(path)
|
|
20
|
+
puts File.exist?(path)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# `Array#sort` (non-bang) on a float array. Surfaced via
|
|
2
|
+
# optcarrot's `@fps_history.sort[(@fps_history.length * 0.05).floor]`
|
|
3
|
+
# p95 calculation. Mirrors the existing int_array sort path —
|
|
4
|
+
# yields a fresh sorted array; the source stays untouched.
|
|
5
|
+
|
|
6
|
+
a = [3.5, 1.25, 2.0, 0.75, 4.125]
|
|
7
|
+
b = a.sort
|
|
8
|
+
puts b.length
|
|
9
|
+
|
|
10
|
+
i = 0
|
|
11
|
+
while i < b.length
|
|
12
|
+
puts b[i]
|
|
13
|
+
i = i + 1
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Source unchanged.
|
|
17
|
+
puts a[0]
|
|
18
|
+
puts a[1]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# `Array#replace` in *expression* position on an int_array.
|
|
2
|
+
# The stmt-form arm has long supported this; the expr-form was
|
|
3
|
+
# missing — unresolved-call warning + literal `0` emitted.
|
|
4
|
+
# Surfaced via optcarrot's `def load_battery; ...; @wrk.replace(sav.bytes); end`,
|
|
5
|
+
# where the call sits at the tail of the method (its value is
|
|
6
|
+
# the implicit return).
|
|
7
|
+
|
|
8
|
+
a = [1, 2, 3]
|
|
9
|
+
b = [10, 20, 30, 40]
|
|
10
|
+
|
|
11
|
+
# Expression position: assigned. Should yield the (mutated) `a`.
|
|
12
|
+
c = a.replace(b)
|
|
13
|
+
|
|
14
|
+
# `a` mutated in place
|
|
15
|
+
puts a[0]
|
|
16
|
+
puts a[1]
|
|
17
|
+
puts a[2]
|
|
18
|
+
puts a[3]
|
|
19
|
+
puts a.length
|
|
20
|
+
|
|
21
|
+
# `c` is the same array (replace returns the receiver)
|
|
22
|
+
puts c[0]
|
|
23
|
+
puts c.length
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Spinel's integers are mrb_int (long long); Ruby integers don't
|
|
2
|
+
# overflow in the same range. But emitting a plain `24329 * 256 *
|
|
3
|
+
# 500` in C lets the C compiler fold the constant using `int`
|
|
4
|
+
# arithmetic, overflowing at 3,114,112,000 to a wrong negative
|
|
5
|
+
# result on 32-bit-int platforms.
|
|
6
|
+
#
|
|
7
|
+
# Surfaced via optcarrot's `APU::Mixer::TND_1 = 100 * 24329 * 256
|
|
8
|
+
# / 500`-shaped constant expressions whose intermediate products
|
|
9
|
+
# clear int32 max. Same hazard for any constant-init expression
|
|
10
|
+
# of integer literals whose folded result exceeds INT_MAX.
|
|
11
|
+
#
|
|
12
|
+
# Fix: emit the `LL` suffix on every IntegerNode literal so
|
|
13
|
+
# operands carry `long long` type at the C level. Runtime
|
|
14
|
+
# expressions assigned to `mrb_int` slots already promoted
|
|
15
|
+
# implicitly; only constant-init contexts (where the C compiler
|
|
16
|
+
# folds before any assignment) saw the overflow.
|
|
17
|
+
|
|
18
|
+
# Each chain straddles int32: max 2^31 - 1 = 2,147,483,647.
|
|
19
|
+
A = 24329 * 256 * 500 # 3,114,112,000
|
|
20
|
+
B = 100000 * 100000 # 10,000,000,000
|
|
21
|
+
C = 65535 * 65535 # 4,294,836,225
|
|
22
|
+
D = 2 ** 40 # 1,099,511,627,776
|
|
23
|
+
E = 1_000_000_000 + 1_000_000_000 # 2,000,000,000 — sum overflow
|
|
24
|
+
|
|
25
|
+
puts A
|
|
26
|
+
puts B
|
|
27
|
+
puts C
|
|
28
|
+
puts D
|
|
29
|
+
puts E
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# `<user_obj>.class` collapses to the class name as a string.
|
|
2
|
+
# Spinel doesn't allocate runtime Class objects, so the only
|
|
3
|
+
# coherent representation for `obj.class` is the textual name.
|
|
4
|
+
# The two real-world consumers in optcarrot are:
|
|
5
|
+
# 1. `"#<#{ self.class }>"`-style interpolation in `inspect`
|
|
6
|
+
# 2. `self.class.to_s.split("::").last`-style introspection
|
|
7
|
+
# Both work fine if `.class` simply yields the class name as a
|
|
8
|
+
# string (the second loses the `::` namespace because Spinel
|
|
9
|
+
# flattens nested modules with `_`, but that's a cosmetic loss).
|
|
10
|
+
|
|
11
|
+
class Foo
|
|
12
|
+
def to_s
|
|
13
|
+
"<" + self.class + ">"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Bar
|
|
18
|
+
def label
|
|
19
|
+
self.class.to_s
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
puts Foo.new.to_s # => <Foo>
|
|
24
|
+
puts Bar.new.label # => Bar
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubyduino
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joseph Schito
|
|
@@ -27,6 +27,7 @@ files:
|
|
|
27
27
|
- examples/hello.rb
|
|
28
28
|
- lib/rubyduino.rb
|
|
29
29
|
- lib/rubyduino/arduino_entry.c
|
|
30
|
+
- lib/rubyduino/arduino_uno.rb
|
|
30
31
|
- lib/rubyduino/sp_runtime.h
|
|
31
32
|
- lib/rubyduino/spinel.rb
|
|
32
33
|
- lib/rubyduino/spinel_arduino_codegen.rb
|
|
@@ -345,6 +346,10 @@ files:
|
|
|
345
346
|
- vendor/spinel/test/fiber_yield_across_method_call.rb.expected
|
|
346
347
|
- vendor/spinel/test/file_basename_gc.rb
|
|
347
348
|
- vendor/spinel/test/file_basename_gc.rb.expected
|
|
349
|
+
- vendor/spinel/test/file_class_methods_int_recv.rb
|
|
350
|
+
- vendor/spinel/test/file_class_methods_int_recv.rb.expected
|
|
351
|
+
- vendor/spinel/test/float_array_sort.rb
|
|
352
|
+
- vendor/spinel/test/float_array_sort.rb.expected
|
|
348
353
|
- vendor/spinel/test/forward_call_class_method_inherited_init.rb
|
|
349
354
|
- vendor/spinel/test/forward_call_class_method_inherited_init.rb.expected
|
|
350
355
|
- vendor/spinel/test/forward_call_class_method_inherited_init_int_array.rb
|
|
@@ -407,6 +412,8 @@ files:
|
|
|
407
412
|
- vendor/spinel/test/inspect.rb.expected
|
|
408
413
|
- vendor/spinel/test/instance_eval_trampoline.rb
|
|
409
414
|
- vendor/spinel/test/instance_eval_trampoline.rb.expected
|
|
415
|
+
- vendor/spinel/test/int_array_replace_expr.rb
|
|
416
|
+
- vendor/spinel/test/int_array_replace_expr.rb.expected
|
|
410
417
|
- vendor/spinel/test/int_bracket_skip_sym_idx.rb
|
|
411
418
|
- vendor/spinel/test/int_bracket_skip_sym_idx.rb.expected
|
|
412
419
|
- vendor/spinel/test/int_keyed_hash_lookup_as_array.rb
|
|
@@ -417,6 +424,8 @@ files:
|
|
|
417
424
|
- vendor/spinel/test/integer_div.rb.expected
|
|
418
425
|
- vendor/spinel/test/integer_div_by_zero.rb
|
|
419
426
|
- vendor/spinel/test/integer_div_by_zero.rb.expected
|
|
427
|
+
- vendor/spinel/test/integer_literal_no_int32_overflow.rb
|
|
428
|
+
- vendor/spinel/test/integer_literal_no_int32_overflow.rb.expected
|
|
420
429
|
- vendor/spinel/test/interp_method_widening.rb
|
|
421
430
|
- vendor/spinel/test/interp_method_widening.rb.expected
|
|
422
431
|
- vendor/spinel/test/interp_symbol.rb
|
|
@@ -560,6 +569,8 @@ files:
|
|
|
560
569
|
- vendor/spinel/test/nullable.rb.expected
|
|
561
570
|
- vendor/spinel/test/obj_array.rb
|
|
562
571
|
- vendor/spinel/test/obj_array.rb.expected
|
|
572
|
+
- vendor/spinel/test/obj_class_returns_string.rb
|
|
573
|
+
- vendor/spinel/test/obj_class_returns_string.rb.expected
|
|
563
574
|
- vendor/spinel/test/object_new_sentinel.rb
|
|
564
575
|
- vendor/spinel/test/object_new_sentinel.rb.expected
|
|
565
576
|
- vendor/spinel/test/object_truthy.rb
|