<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -200,8 +200,13 @@ class Compiler
       @e.comment(arg.position.inspect) if pos != @lastpos
       @lastpos = pos
     end
-    args = get_arg(scope,arg)
-    return @e.load(args[0],args[1])
+    atype, aparam = get_arg(scope,arg)
+    if atype == :ivar
+      ret = compile_eval_arg(scope, :self)
+      @e.load_instance_var(ret, aparam)
+      return @e.result_value
+    end
+    return @e.load(atype,aparam)
   end
 
 
@@ -220,6 +225,12 @@ class Compiler
       atype, aparam = get_arg(scope, left)
     end
 
+    if atype == :ivar
+      ret = compile_eval_arg(scope,:self)
+      @e.save_to_instance_var(source, ret, aparam)
+      return [:subexpr]
+    end
+
     if !(@e.save(atype,source,aparam))
       err_msg = &quot;Expected an argument on left hand side of assignment - got #{atype.to_s}, (left: #{left.inspect}, right: #{right.inspect})&quot;
       error(err_msg, scope, [:assign, left, right]) # pass current expression as well
@@ -357,6 +368,7 @@ class Compiler
     @classes[name] = cscope
     @global_scope.globals &lt;&lt; name
     compile_exp(scope, [:assign, name.to_sym, [:call, :__new_class_object, [cscope.klass_size]]])
+    compile_exp(cscope, [:assign, :@instance_size, cscope.instance_size])
     @global_constants &lt;&lt; name
     exps.each do |e|
       addr = compile_do(cscope, *e)</diff>
      <filename>compiler.rb</filename>
    </modified>
    <modified>
      <diff>@@ -156,8 +156,8 @@ class Emitter
       return load_arg(aparam)
     when :lvar
       return load_local_var(aparam)
-    when :ivar
-      return load_instance_var(aparam)
+#    when :ivar
+#      return load_instance_var(aparam)
     when :cvar
       return load_class_var(aparam)
     when :global
@@ -193,8 +193,9 @@ class Emitter
     return :eax
   end
 
-  def load_instance_var(aparam)
-    STDERR.puts(&quot;Emitter#load_instance_var not implemented yet - #{aparam.inspect}&quot;)
+  def load_instance_var(ob,aparam)
+    movl(&quot;#{aparam.to_i*PTR_SIZE}(#{to_operand_value(ob)})&quot;,result_value)
+    return result_value
   end
 
   def load_class_var(aparam)
@@ -205,10 +206,8 @@ class Emitter
     movl(arg,local_var(aparam))
   end
 
-  def save_to_instance_var(arg, aparam)
-    # needs to be implemented
-    STDERR.puts(&quot;Emitter#save_to_instance_var needs to be implemented&quot;)
-    STDERR.puts(&quot;Emitter#save_to_instance_var: arg: #{arg.inspect}, aparam: #{aparam.inspect}&quot;)
+  def save_to_instance_var(arg, ob,aparam)
+    movl(arg,&quot;#{aparam.to_i*PTR_SIZE}(#{to_operand_value(ob)})&quot;)
   end
 
   def save_to_class_var(arg, aparam)</diff>
      <filename>emitter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,11 +3,12 @@ class Foo
 
   def bar
     puts(&quot;test&quot;)
+    @foo = &quot;Some text&quot;
     self.hello
   end
 
   def hello
-    puts(&quot;Hello World!&quot;)
+    printf(&quot;Hello World! - %s\n&quot;,@foo)
   end
 end
 </diff>
      <filename>examples/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,9 @@ end
 
 class Class
   def new
-    ob = malloc(4)
+    # @instance_size is generated by the compiler. YES, it is meant to be
+    # an instance var, not a class var
+    ob = malloc(@instance_size*4) 
     %s(assign (index ob 0) self)
     ob
   end</diff>
      <filename>lib/core/class.rb</filename>
    </modified>
    <modified>
      <diff>@@ -64,9 +64,10 @@ VTableEntry = Struct.new(:name, :realname, :offset, :function)
 # we can't usually statically determine what class
 # an object belongs to.
 class VTableOffsets
-  def initialize
+  def initialize 
     @vtable = {}
-    @vtable_max = 1 # Start at 1 since offset 0 is reserved for the vtable pointer for the Class object
+    # Start at CLASS_IVAR_NUM to allow convenient allocation of ivar space for the Class object
+    @vtable_max = ClassScope::CLASS_IVAR_NUM
     # Then we insert the &quot;new&quot; method.
     alloc_offset(:new)
     # __send__ is our fallback if no vtable
@@ -107,12 +108,20 @@ class ClassScope
   # and class variables
   attr_reader :name, :vtable, :instance_vars, :class_vars
 
+  # This is the number of instance variables allowed for the class
+  # Class, and is used for bootstrapping. Note that it could be
+  # determined by the compiler checking the actual class implementation,
+  # so this is a bit of a copout.
+  # 
+  # slot 0 is reserved for the vtable pointer
+  CLASS_IVAR_NUM = 2
+
   def initialize(next_scope, name, offsets)
     @next = next_scope
     @name = name
     @vtable = {}
     @vtableoffsets = offsets
-    @instance_vars = {}
+    @instance_vars = [:@__class__] # FIXME: Do this properly
     @class_vars = {}
   end
 
@@ -120,7 +129,20 @@ class ClassScope
     false
   end
 
+  def add_ivar(a)
+    @instance_vars &lt;&lt; a.to_sym
+  end
+
+  def instance_size
+    @instance_vars.size
+  end
+
   def get_arg(a)
+    # Handle self
+    if a.to_sym == :self
+      return [:global,@name]
+    end
+
     # class variables.
     # if it starts with &quot;@@&quot; it's a classvariable.
     if a.to_s[0..1] == &quot;@@&quot; or @class_vars.include?(a)
@@ -132,9 +154,10 @@ class ClassScope
     # instance variables.
     # if it starts with a single &quot;@&quot;, it's a instance variable.
     if a.to_s[0] == ?@ or @instance_vars.include?(a)
-      @instance_vars[a] ||= a.to_s.rest.to_sym # save without &quot;@&quot;
-      instance_var = @instance_vars[a]
-      return [:ivar, &quot;__instancevar__#{@name}__#{instance_var}&quot;.to_sym] # -&gt; e.g.__instancevar__Foo__varname
+      offset = @instance_vars.index(a)
+      add_ivar(a) if !offset
+      offset = @instance_vars.index(a)
+      return [:ivar, offset]
     end
 
 
@@ -142,6 +165,12 @@ class ClassScope
     return [:addr, a]
   end
 
+  # Returns the size of a class object.
+  # This is a multiple of @vtableoffsets.max, but this
+  # is deceiving as the offsets starts at a value that
+  # is based on the amount of data needed at the start of
+  # the class object as instance variables for the class
+  # object.
   def klass_size
     @vtableoffsets.max * Emitter::PTR_SIZE
   end</diff>
      <filename>scope.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>607e0355034041f3f4a9ca26c057cc37ed81c820</id>
    </parent>
  </parents>
  <author>
    <name>Vidar Hokstad</name>
    <email>vidar@hokstad.com</email>
  </author>
  <url>http://github.com/vidarh/writing-a-compiler-in-ruby/commit/f74fb4f7e375217e2061949fa2c7cf02f869fc75</url>
  <id>f74fb4f7e375217e2061949fa2c7cf02f869fc75</id>
  <committed-date>2009-04-25T06:51:07-07:00</committed-date>
  <authored-date>2009-04-25T06:51:07-07:00</authored-date>
  <message>Instance variable support, and an example</message>
  <tree>d4047fdaf5ff96182860ae05ebc74b2131609e83</tree>
  <committer>
    <name>Vidar Hokstad</name>
    <email>vidar@hokstad.com</email>
  </committer>
</commit>
