Slide 1

Slide 1 text

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 г.

Slide 10

Slide 10 text

Parsing [ :begin, [ :define, :fact, [ :lambda, [ :n], [ :if, [ :<=, :n, 1], 1, [ :*, :n, [ :fact, [ :-, :n, 1]]]]]] среда, 31 июля 13 г.

Slide 11

Slide 11 text

Evaluating - define nested ENVIRONMENT for each lexical scope - recursive call of eval(x, env) with a large switch-case среда, 31 июля 13 г.

Slide 12

Slide 12 text

Ruby среда, 31 июля 13 г.

Slide 13

Slide 13 text

Ripper require ‘ripper’ Ripper.sexp (‘p “hello world”’) среда, 31 июля 13 г.

Slide 14

Slide 14 text

Ripper output [:program, [[:command, [:@ident, "p", [1, 0]], [:args_add_block, [[:string_literal, [:string_content, [:@tstring_content, "Hello World", [1, 3]]]]], false]]]] среда, 31 июля 13 г.

Slide 15

Slide 15 text

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 г.

Slide 31

Slide 31 text

Thanks! среда, 31 июля 13 г.