Ruby in your phone
Interpreters. Ruby. iOS
Denis Lebedev
linkedin.com/in/dlebedev
среда, 31 июля 13 г.
Slide 2
Slide 2 text
Interpreters
среда, 31 июля 13 г.
Slide 3
Slide 3 text
Program execution
- execute code directly (Lisp)
- translate code to IR and execute (Python, Ruby)
- execute stored precompiled code
среда, 31 июля 13 г.
Slide 4
Slide 4 text
Ruby
1.8
slow single-pass interpreter MRI
1.9
yet another Ruby VM - YARV
среда, 31 июля 13 г.
Slide 5
Slide 5 text
Scheme
среда, 31 июля 13 г.
Slide 6
Slide 6 text
So simple
(+ 3 4 5)
среда, 31 июля 13 г.
Slide 7
Slide 7 text
NOT so simple
(begin
(define fact (lambda (n)
(if (<= n 1) 1 (* n (fact (- n 1))))))
среда, 31 июля 13 г.
Slide 8
Slide 8 text
How it works?
Program
Parser
Execution
representation
output
среда, 31 июля 13 г.
Slide 9
Slide 9 text
Rispy
http://stuff.thedeemon.com/rispy/
60 LOC scheme-interpreter
среда, 31 июля 13 г.
parse.y
Ruby parser
~11,500 LOC
среда, 31 июля 13 г.
Slide 16
Slide 16 text
iOS
среда, 31 июля 13 г.
Slide 17
Slide 17 text
Building Ruby for armvX. Fail story
- download source, build using make[x]
- build native with Clang installed on iDevice [x]
- create Xcode project, add sources, build [x]
среда, 31 июля 13 г.
Slide 18
Slide 18 text
Building Ruby for armvX. Success story
1. A lot of TIME spent configuring make
2. Building fails
2’. Some sources won’t compile -> edit/delete
3. Google some new flags -> add
4. Repeat step 1.
среда, 31 июля 13 г.
Slide 19
Slide 19 text
Building Ruby for armvX. Success story
1. A lot of TIME spent configuring make
2. Building fails
2’. Some sources won’t compile -> edit/delete
3. Google some new flags -> add
4. Repeat step 1.
libruby-static.a we’ve got ya!!!
среда, 31 июля 13 г.
Slide 20
Slide 20 text
Building Ruby extensions
1. --with-static-linked-ext flag
2. Modify content of /ext source files
3. Compile to *.a
Dynamic libraries are disabled in iOS.
среда, 31 июля 13 г.
Slide 21
Slide 21 text
Run extensions
1. Manually link each extension to libruby-static.a
2. Call “Init_xxx methods” in ObjC-code
3. Don’t forget to link encoding packages from /enc
среда, 31 июля 13 г.
Slide 22
Slide 22 text
Standard library /lib
- some extensions work out of the box
- sometimes code editing required
- modificaton of PATH variables is required
Network, dates, math, etc. is working and tested.
среда, 31 июля 13 г.
Slide 23
Slide 23 text
Usage in Obj-C
[[RubyEvaluator sharedInstance]
evaluate:@”3.times { puts 1}”]
Produces:
1
1
1
среда, 31 июля 13 г.
Slide 24
Slide 24 text
Implementation details
- Uses rb_eval_string_protect from “ruby.h”
- Omits all intermediate output :(
- Does not allow to interrupt input :( :( :(
среда, 31 июля 13 г.
Slide 25
Slide 25 text
Do yo want some C?
- Ruby allows to write ‘native’ extensions
- We use some tricks to create Ruby<>Obj-C bridge
среда, 31 июля 13 г.
Slide 26
Slide 26 text
Captureoutput.rb
class CaptureOutput < IO
def initialize
super(2)
end
def write(text)
captured_write(text)
end
def gets
captured_read
end
end
def gets
captured_read
end
buf = CaptureOutput.new
$stderr = buf
$stdout = buf
$stdin = buf
среда, 31 июля 13 г.
Slide 27
Slide 27 text
Captureoutput.c
void init_captureoutput(void (*write_callback)(VALUE
str), VALUE (*stdin_read_callback)(void)) {
stdout_write_callback = write_callback;
rb_define_method(rb_cObject, "captured_write",
object_captured_write, 1);
b_define_method(rb_cObject, "captured_read",
object_captured_read, 0);
rb_require("captureoutput");
}
среда, 31 июля 13 г.
Slide 28
Slide 28 text
RubyEvaluator.m
static void write_function(VALUE str) {
! evaluatorOutputBlock(convert(str));
}
static VALUE read_function(void) {
! NSString *input;
! do {
! ! sleep(0.1);
! ! input = evaluatorInputBlock();
! } while (!input);
!
! return str_to_VALUE(input);
}
среда, 31 июля 13 г.
Slide 29
Slide 29 text
benchmark.rb
ios-ruby ~0.6 sec
irb ~0.08 sec
factorial(10000):
среда, 31 июля 13 г.
Slide 30
Slide 30 text
https://github.com/garnett/iOSRuby
среда, 31 июля 13 г.