Commit 454bb9d4c2120ff0f7699a35e3ac59bc702012d5

added support for inheritance with tuples. also updated examples/generics to make use of it & updated README.
README
(7 / 3)
  
3333 * Support for debug output via: bin/stackd filename.stackd --debug
3434 -> Outputs the parsed AST
3535
36What's partially implemented:
37 * A generic object system (as in Factor)
38 * Support for:
39 * Generic Words & Methods
40 * Inheritance
41
3642What's still missing (and never might be implemented):
37
43 * Private / read-only slots on objects / classes (and probably more)
3844 * Nice development tools, as Factor has them
3945 * Real debugger or walker
40 * An generic object system (as in Factor)
4146 * Many more features, you'll find in Factor
42
4347
4448Some basic syntax rules:
4549 * All expressions / statements need to end with a semicolon (';')
  
11use: core.math core.misc ;
22in: examples.generics ;
33
4tuple: shape ;
4tuple: shape name ;
55
6tuple: rectangle height width ;
7tuple: circle delimiter ;
6tuple: rectangle < shape height width ;
7tuple: circle < shape delimiter ;
88
99generic: area ; !( shape -- area )
1010
1212 [ height>> ] [ width>> ] bi * ;
1313
1414: <rectangle>
15 rectangle new ;
15 rectangle new "RECTANGLE" >>name ;
1616
1717m: circle area
1818 delimiter>> sq core.math::PI * ;
1919
2020: <circle>
21 circle new ;
21 circle new "CIRCLE" >>name ;
2222
23<rectangle> 10 >>height 10 >>width area print ;
23generic: print-name ; ! ( shape -- )
24! a method only defined on shape
25! will also work on all subclasses (polymorphism) :)
26! actually, since Stackd is dynamic, it will work on any
27! datatype that has a name slot.
28m: shape print-name
29 "Shape: " print- name>> print ;
2430
25<circle> 10 >>delimiter area print ;
31<rectangle>
32 10 >>height
33 10 >>width
34 [ print-name ] keep
35 "-- Area: " print- area print ;
36
37<circle>
38 10 >>delimiter
39 [ print-name ] keep
40 "-- Area: " print- area print ;
  
3333 syntax('tuple:') do |scope, atoms|
3434 tuplename = atoms.first.text_value
3535 slots = atoms.rest.map{|a| a.text_value}
36 superclass = nil
3637 case atoms.first
3738 when Stackd::Identifier
3839 mod = get_current_module(scope)
3940 if mod
40 mod.define_tuple(tuplename, slots)
41 else
42 scope.define_tuple(tuplename, slots)
41 scope = mod
4342 end
43 if slots[0] == "<"
44 superclass = scope[slots[1]]
45 slots = slots[2..-1]
46 end
47 scope.define_tuple(tuplename, slots, superclass)
4448 end
4549 end
4650
  
3434 self[name] = Syntax.new(self, &block)
3535 end
3636
37 def define_tuple(name, slots)
38 tuple = Tuple.new(name, slots)
37 def define_tuple(name, slots, superclass = nil)
38 tuple = Tuple.new(name, slots, superclass)
3939 self.tuples[name] = tuple
4040 define_slot_accessors(slots)
4141 self[name] = tuple
  
11class Tuple
2 attr_reader :slots, :name
3 def initialize(name, slots)
2 attr_reader :slots, :name, :superclass
3 def initialize(name, slots, superclass = nil)
44 @name = name
5 @slots = slots || []
5 if superclass
6 @superclass = superclass
7 @slots = superclass.slots # inherits from superclass
8 else
9 @slots = []
10 end
11 @slots += slots
12 @slots.uniq! # no double slotnames
613 @instances = []
714 end
815
916 def to_s
10 "#<Tuple:#{@name} [#{@slots.join(',')}]>"
17 superclass_str = ""
18 superclass_str = "< #{@superclass.name} " if @superclass
19 "#<Tuple:#{@name} #{superclass_str}[#{@slots.join(',')}]>"
1120 end
1221
1322 def inspect
  
4646 @implementations = {} # Hash with tuples as keys
4747 end
4848
49 def get_method_implementation(tuple)
50 impl = @implementations[tuple]
51 unless impl
52 if tuple.superclass
53 get_method_implementation(tuple.superclass)
54 else
55 nil
56 end
57 else
58 impl
59 end
60 end
61
4962 def call(scope)
5063 obj = DS.peek # last element (top of stack) is our dispatch object
5164 if obj.is_a?(TupleInstance) # only call generic words on tuple instances
52 impl = @implementations[obj.tuple]
65 impl = get_method_implementation(obj.tuple)
5366 if impl
5467 impl.call(scope)
5568 else