So you want to design a programming language

A8e44ce1b57c2689d5a7172d15df42b5?s=47 brixen
February 15, 2013
67

So you want to design a programming language

Talk about Rubinius as a language platform at Copious.

A8e44ce1b57c2689d5a7172d15df42b5?s=128

brixen

February 15, 2013
Tweet

Transcript

  1. So you want to design a programming language COPIOUSLabs TechTalk

    15 Feb 2013
  2. Brian Shirai Rubinius Developer

  3. there will be a quiz

  4. Questions?

  5. Languages

  6. why are languages fascinating?

  7. practical or fanciful?

  8. Security

  9. 28c3: The Science of Insecurity

  10. computability

  11. predictability

  12. None
  13. None
  14. None
  15. None
  16. None
  17. data vs meta-data

  18. None
  19. None
  20. Virtual Machines

  21. Interpreter

  22. Stack vs Register

  23. Jimple

  24. Garbage collection

  25. Concurrency

  26. JIT compiler

  27. None
  28. None
  29. Parsers and compilers

  30. Parsing Expression Grammars

  31. PEGs

  32. github.com/evanphx/kpeg

  33. github.com/wycats/parsejs

  34. LPeg http://www.inf.puc-rio.br/~roberto/lpeg/

  35. None
  36. Rubinius

  37. None
  38. atomy-lang.org

  39. None
  40. fancy-lang.org

  41. Primitives

  42. class Array def [] Ruby.primitive :array_aref raise PrimitiveFailure, "Array#[] primitive

    failed" end end
  43. class Array : public Object { private: Fixnum* total_; //

    slot Tuple* tuple_; // slot public: attr_accessor(total, Fixnum); attr_accessor(tuple, Tuple); }
  44. class Array : public Object { // Ruby.primitive :array_aref Object*

    aref(STATE, Fixnum* idx); }
  45. instruction send_method(literal) [ receiver -- value ] => send flush_ip();

    Object* recv = stack_top(); InlineCache* cache = reinterpret_cast<InlineCache*>(literal); Arguments args(cache->name, recv, cNil, 0, 0); Object* ret = cache->execute(state, call_frame, args); (void)stack_pop(); CHECK_AND_PUSH(ret); end
  46. class OneArgument { public: static bool call(STATE, VMMethod* vmm, StackVariables*

    scope, Arguments& args) { if(args.total() != 1) return false; scope->set_local(0, args.get_argument(0)); return true; } };
  47. $ rbx irb(main):001:0> def hello(name) irb(main):002:1> puts "hello, #{name}" irb(main):003:1>

    end => #<Rubinius::CompiledCode hello file=(irb)>
  48. every CompiledCode object has its own interpreter

  49. def self.compile_string(string, file="(eval)", line=1) compiler = new :string, :compiled_code parser

    = compiler.parser parser.root AST::Script parser.default_transforms parser.input string, file, line compiler.run end
  50. $ rbx compile -e 'def m(a, b=1) a + b

    end' -N m -B ================== :m ================== Arguments: 1 required, 0 post, 2 total Locals: 2: a, b Stack size: 4 Lines to IP: 1: -1..14 0000: passed_arg 1 0002: goto_if_true 8 0004: meta_push_1 0005: set_local 1 # b 0007: pop 0008: push_local 0 # a 0010: push_local 1 # b 0012: meta_send_op_plus :+ 0014: ret ----------------------------------------
  51. $ rbx compile -e 'def m(a, b=1) a + b

    end' -B ============= :__script__ ============== Arguments: 0 required, 0 post, 0 total Locals: 0 Stack size: 5 Lines to IP: 1: 0..15 0000: push_rubinius 0001: push_literal :m 0003: push_literal #<Rubinius::CompiledCode m file=(snippet)> 0005: push_scope 0006: push_variables 0007: send_stack :method_visibility, 0 0010: send_stack :add_defn_method, 4 0013: pop 0014: push_true 0015: ret ----------------------------------------
  52. Ruby

  53. $ rbx irb(main):001:0> m = Rubinius::Executable.new => #<Rubinius::Executable:0xf3c>

  54. irb(main):002:0> def m.call(*args) irb(main):003:1> puts "you rang? #{args.inspect}" irb(main):004:1> end

    => #<Rubinius::CompiledCode call file=(irb)>
  55. irb(main):005:0> sc = m.singleton_class => #<Class:#<Rubinius::Executable:0xf3c>> irb(main):006:0> sc.method_table.store :hi, m,

    :public => :hi
  56. irb(main):007:0> m.hi you rang? [#<Rubinius::Executable:0xf3c>, :hi] => nil irb(main):008:0> m.hi

    "hello" you rang? [#<Rubinius::Executable:0xf3c>, :hi, "hello"] => nil
  57. Module#dynamic_method

  58. $ rbx irb(main):001:0> class Cat irb(main):002:1> dynamic_method :meow do |g|

    irb(main):003:2* g.push :self irb(main):004:2> g.push_literal "meow" irb(main):005:2> g.send :puts, 1, true irb(main):006:2> g.ret irb(main):007:2> end irb(main):008:1> end
  59. => #<Rubinius::CompiledCode meow file=(dynamic)> irb(main):009:0> Cat.new.meow meow => nil irb(main):010:0>

  60. Tools

  61. Debugger

  62. class Cat def speak puts "woof" end end Cat.new.speak

  63. None
  64. None
  65. None
  66. None
  67. None
  68. github.com/rocky/rbx-trepanning

  69. Profiler

  70. $ rbx -Xprofile -e '10000.times { |x| x * x

    + x * 2 }' Thread 1: total running time: 0.073496367s % cumulative self self total time seconds seconds calls ms/call ms/call name ------------------------------------------------------------ 70.58 0.05 0.05 1 52.05 52.05 Rubinius::Tooling.disable 12.43 0.01 0.01 10000 0.00 0.00 Object::__script__<1> {} 7.24 0.02 0.01 1 5.34 16.74 Integer#times 3.03 0.00 0.00 20000 0.00 0.00 Fixnum#* 1.61 0.00 0.00 1 1.19 1.19 Rubinius::AST::Send#bytecode 1.38 0.00 0.00 1 1.02 2.78 Rubinius::Compiler::Parser#run 1.07 0.00 0.00 1 0.79 3.58 Rubinius::Compiler.compile_eval 0.74 0.00 0.00 4 0.14 0.44 Rubinius::Compiler::Stage#run_next 0.58 0.00 0.00 1 0.42 1.75 Rubinius::Compiler::Generator#run 0.53 0.02 0.00 1 0.39 20.97 Rubinius::Loader#evals 0.19 0.05 0.00 1 0.14 52.19 Rubinius::Profiler::Instrumenter#__stop__ 0.18 0.02 0.00 1 0.13 20.58 Kernel#eval 0.15 0.00 0.00 1 0.11 3.69 Rubinius::Compiler.construct_block 0.09 0.00 0.00 1 0.06 1.25 Rubinius::AST::EvalExpression::bytecode<906> 0.06 0.00 0.00 1 0.05 1.30 Rubinius::AST::Container#container_bytecode 0.05 0.05 0.00 1 0.04 52.25 Rubinius::Loader#epilogue 0.03 0.00 0.00 1 0.02 1.32 Rubinius::AST::EvalExpression#bytecode 0.01 0.00 0.00 1 0.01 2.79 Rubinius::Compiler#run 0.01 0.05 0.00 1 0.01 52.21 Object::__script__<4> {} 0.01 0.02 0.00 1 0.01 16.75 Object::__script__<1> {} 0.01 0.02 0.00 1 0.01 16.75 Rubinius::BlockEnvironment#call_on_instance 0.01 0.05 0.00 1 0.01 52.20 Profiler__.stop_profile 0.01 0.05 0.00 1 0.00 52.19 Rubinius::Profiler::Instrumenter#stop 0.01 0.05 0.00 1 0.00 52.20 Profiler__.print_profile 24 methods called a total of 30,025 times
  71. Agent

  72. $ rbx -Xagent.start irb(main):001:0>

  73. $ rbx console VM: rbx -Xagent.start Connecting to VM on

    port 56488 Connected to localhost:56488, host type: x86_64-apple-darw console>
  74. $ console> get system var system = [ "name", "backtrace",

    "threads", "gc", "memory", "pid", "jit", ]
  75. $ console> get system.pid var system.pid = [ 69118, ]

    $ console> get system.threads var system.threads = [ "count", "backtrace", ] $ console> get system.threads.count var system.threads.count = 2
  76. Memory analysis

  77. require "rubinius/agent" agent = Rubinius::Agent.loopback agent.request :set_config, "system.memory.dump", "before.d array

    = (0..10).map { |i| "x" * rand(i) } p array agent.request :set_config, "system.memory.dump", "after.du
  78. $ rbx -I /source/heap_dump/lib/ /source/heap_dump/bin/histo.rb before.dump 20738 Rubinius::Tuple 3763200 5820

    Object 279312 5001 Rubinius::MethodTable::Bucket 280056 4388 Rubinius::CompiledMethod 877600 4388 Rubinius::InstructionSequence 140416 3269 String 209216 3166 Rubinius::CharArray 166864 1815 Rubinius::LookupTable::Bucket 87120 1130 Rubinius::LookupTable 54240 1100 Rubinius::GlobalCacheEntry 52800 1047 Rubinius::MethodTable 50256 1001 Class 100384 835 Rubinius::StaticScope 40080 676 Rubinius::AccessVariable 54080 456 Array 25536 141 Hash::Entry 7896 123 Rubinius::CompactLookupTable 15744 105 Rubinius::NativeFunction 10920 102 Rubinius::InstructionSet::OpCode 13872 46 Module 2944 46 Float 1472 46 Rubinius::IncludedModule 3312 39 Rubinius::CompiledMethod::Script 2808 22 Hash 1760
  79. $ rbx -I /source/../lib /source/.../histo.rb before.dump after.dump 54 Object 2592

    11 String 704 11 Rubinius::CharArray 440 8 Rubinius::GlobalCacheEntry 384 2 Rubinius::CompactLookupTable 256 2 Rubinius::ByteArray 2624 2 Rubinius::Tuple 184 1 Rubinius::Randomizer 48 1 Bignum 56 1 Rubinius::VariableScope 104 1 Array 56
  80. proc FS

  81. github.com/rubinius github.com/brixen @brixen

  82. Thank you

  83. the most important tech talk to watch this year is

    ________________.
  84. Questions?