v1
authorChristian Thaeter <ct@pipapo.org>
Sun, 6 Jul 2014 07:10:44 +0000 (09:10 +0200)
committerChristian Thaeter <ct@pipapo.org>
Sun, 6 Jul 2014 07:10:44 +0000 (09:10 +0200)
proto.lua [new file with mode: 0644]

diff --git a/proto.lua b/proto.lua
new file mode 100644 (file)
index 0000000..36fe0f1
--- /dev/null
+++ b/proto.lua
@@ -0,0 +1,116 @@
+--proto Prototype based Objectsysten
+--proto ----------------------------
+--proto Objects are `cloned` from existing objects ,`Object` is the mother of all objects.
+--proto One can introduce additional inheritance paths with 'inherit'. Lookup order is
+--proto first the prototype chain from `clone` and then all parent chains in the order
+--proto they where added.
+--proto
+--proto Differential inheritance
+--proto ~~~~~~~~~~~~~~~~~~~~~~~~
+--proto Dynamic changes in prototypes and parent objects are reflected in childs unless a
+--proto child overidden a slot. Just doing `child.slot = child.slot` will copy the looked up
+--proto slot into the child, this speeds up further lookup and protects the slot from changes
+--proto in the parent.
+--proto
+--proto
+--proto
+
+-- override the buildin type() function
+--local buildin_type = type
+--function type (x)
+--    local m = getmetatable(x)
+--    return buildin_type(x) == "table" and x.__type or buildin_type(m) == "table" and m.__type or buildin_type(x)
+--end
+
+
+-- Object is the root object for all objects to be created
+local Object = {}
+
+Object.__index = Object
+
+function Object:__clone(t)
+    assert(not t or type(t) == 'table')
+    local newobject = t or {}
+    setmetatable(newobject, self)
+    newobject.__index = self
+    newobject.__proto = self
+    return newobject
+end
+
+
+function Object:__inherit (...)
+    if self.__parents then
+        local parents = self.__parents
+        local args = {...}
+        for i=1,#args do
+            assert((pcall(function () return args[i].indexable end)), "object not indexable")
+            parents[#parents + 1] = args[i]
+        end
+    else
+        self.__parents = {self.__index, ...}
+        self.__index = function(self, key)
+                           local parents = self.__parents
+                           for i=1,#parents do
+                               local value = parents[i][key]
+                               if value then
+                                   return value
+                               end
+                           end
+                       end
+    end
+    return self
+end
+
+
+function Object:__pairs()
+    local state = {self=self, keys_done = {}, parents = self.__parents or {self.__index} or {}, ppos = 1}
+    local function itr (state)
+        local value
+        while state.self do
+            state.pos, value  = next(state.self, state.pos)
+            if state.pos then
+                state.keys_done[state.pos] = true
+                return state.pos, value
+            else
+                state.self = nil
+            end
+        end
+
+        while state.parents[state.ppos] do
+            state.pos, value  = next(state.parents[state.ppos], state.pos)
+            if state.pos then
+                if not state.keys_done[state.pos] then
+                    state.keys_done[state.pos] = true
+                    return state.pos, value
+                end
+            else
+                state.ppos = state.ppos + 1
+            end
+        end
+    end
+
+    return itr, state
+end
+
+
+if arg[1] == "test" then
+    Object.foo = "foo"
+
+    O2 = Object:__clone { bar = "bar"}
+
+
+    O3 = Object:__clone {baz = "baz" }
+    O3:__inherit(O2)
+
+    for k,v in pairs(O3) do
+        print(k,v)
+    end
+else
+    return Object
+end
+
+-- Local Variables:
+-- mode: lua
+-- lua-indent-level: 4
+-- indent-tabs-mode: nil
+-- End: