public
Description: Rubinius, the Ruby VM
Homepage: http://rubini.us
Clone URL: git://github.com/evanphx/rubinius.git
Added some basic docs on primitives to README-C++.
brixen (author)
Fri Jul 18 15:21:39 -0700 2008
commit  a5650c5a70b5e4c277d75ff5ea25e58b2b96b5b9
tree    e17d29ed8f08bca55960a329817002f4ab4b7798
parent  165ac45049e9647fdadb94da07ef20b3e58bbe30
...
24
25
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
0
@@ -24,3 +24,99 @@
0
 + ...And `git push` to send back any of your commits to the C++ branch.
0
     - Same here with the Rbx Rake tasks.
0
 
0
+
0
+ Building the VM
0
+-----------------
0
+
0
+ # nn the vm subdirectory
0
+ $ rake vm
0
+
0
+
0
+ Compiling to .rbc with MRI
0
+----------------------------
0
+
0
+MRI can be used to compile Ruby files to bytecode, which can then be run by
0
+the VM. To compile 'file.rb' to 'file.rbc':
0
+
0
+ # in the root of the cpp directory
0
+ $ ruby lib/compiler/mri_compile.rb -frbx-kernel file.rb file.rbc
0
+
0
+
0
+ Running bytecode with the VM
0
+------------------------------
0
+
0
+Once a Ruby file has been compiled to bytecode (.rbc), it can be run by the VM
0
+with the following command:
0
+
0
+ # in the vm subdirectory
0
+ $ ./vm file.rbc
0
+
0
+
0
+ Primitives
0
+------------
0
+
0
+Primitives are normal methods on C++ classes. Comment annotation links the C++
0
+method to a symbol with which the primitive is accessed in Ruby code.
0
+
0
+For example, consider the Ruby LookupTable class:
0
+
0
+class LookupTable
0
+ def [](key)
0
+ Ruby.primitive :lookuptable_fetch
0
+ raise PrimitiveFailure, "LookupTable#[] primitive failed"
0
+ end
0
+end
0
+
0
+In the C++ file, rbx/vm/builtin_lookuptable.hpp, the primitive is annotated:
0
+
0
+namespace rubinius {
0
+ class LookupTable : public Object {
0
+ // ...
0
+
0
+ // Ruby.primitive :lookuptable_fetch
0
+ OBJECT fetch(STATE, OBJECT key);
0
+ }
0
+}
0
+
0
+The magic for this happens in rbx/vm/field_extract.rb and the output goes to
0
+rbx/vm/gen/primitives_declare.hpp and rbx/vm/gen/primitives_glue.gen.cpp.
0
+
0
+
0
+ Overloaded C++ Methods as Primitives
0
+--------------------------------------
0
+
0
+There are two ways to annotate the C++ methods as primitives. If there is a
0
+single C++ method, use 'Ruby.primitive :name_of_primitive'. If there are
0
+multiple C++ methods (i.e. overloaded methods), use 'Ruby.primitive!
0
+:name_of_primitive'. The difference is the '!' method for defining overloaded
0
+methods as primitives. The resulting glue code for overloaded methods looks
0
+something like the following:
0
+
0
+bool Primitives::float_mul(STATE, VMExecutable* exec,
0
+ Task* task, Message& msg) {
0
+ OBJECT ret;
0
+ try {
0
+ if(Float* arg = try_as<Float>(msg.get_argument(0))) {
0
+ return as<Float>(msg.recv)->mul(state, arg);
0
+ }
0
+ if(Integer* arg = try_as<Integer>(msg.get_argument(0))) {
0
+ return as<Float>(msg.recv)->mul(state, arg);
0
+ }
0
+ else {
0
+ throw new Assertion("unable to resolve primitive float_mul types");
0
+ }
0
+ } catch(PrimitiveFailed& e) {
0
+ abort(); // FIXME
0
+ return true;
0
+ }
0
+ task->primitive_return(ret, msg);
0
+ return false;
0
+}
0
+
0
+
0
+ Tests for Primitives
0
+----------------------
0
+
0
+Since the "primitives" are ordinary C++ methods, tests for them are written
0
+along with the other VM tests. Each builtin_xxx.cpp method has a corresponding
0
+rbx/vm/test/test_xxx.hpp method. See the existing files for more examples.

Comments

    No one has commented yet.