delegate a;
delegate b;
method c;
function d;

a == b // if (a.method == b.method) && (a.instance == b.instance)
a == c // if (a.method == c.method)
 


// create a global variable x and assign a function to it
global function x(a)
end
// same as above
global x = function (a)
end

// create a global object (namespace) and assign a function to property x 
global n = {
  x : function (a)
  end
}
// assign function to property x of object (namespace) n (global not required because n already exists)
function n.x(a)
end
// same as above
n.x = function (a)
end

// assign 1 to index 0
n[0] = "index"
n.length == 1

// assign 1 to key "key"
n["key"] = "value"
// print all keys assign to n
iterator = n.items()
loop
  if (pair = iterator()) == nil then
    break
  end
  print(pair)
end
// same as above
for pair in n.items() do
  print(pair)
end

// assign 1 to symbol property
n.property = 1 // or n[symbol("property")] = 1
//
for pair in n.properties() do
  print(pair)
end

// create an object
global o = {
  a : "hello",
  "b" : "world",
  0 : "!"
}
global o = {}
o.a = "hello"
o["b"] = "world"
o[0] = "!"


// create a class object
class Example()
  // member class = Class
  // member inherit = Object
  member classVariable = "hello"
  // a method is a function with an implicite self local variable
  method classMethod(a)
    // local self = self
    // local inherited = self.classMethod
    local localVariable = classVariable + " world"
    print(localVariable)
  end
end
// override Example.classMethod
method Example.classMethod(a)
  // local self = Example
  // local inherited = self.classMethod
  local localVariable = localVariable + " world"
  print(localVariable)
end
// a function somewhat similar to the above
function Example.classFunction(a)
  local self = Example
  local inherited = self.classFunction
end

//
constructor Example()
  // member class = Example
  // member inherit = class.inherit()
  // instance = self
  member instanceVariable = 42
  // method create a local variable that is the value of x thus making it possible to call inherited methods
  method instanceMethod()
    // local self = self
    // local inherited = self.instanceMethod
    inherited()
    print("World")
  end
end

// create a class object
class SpecialExample(Example)
  // member class = Class
  // member inherit = Example
  // overriding a class variabel is not a good idea, since it affects the inherited class globally
  classVariable = "bonjour"
  // is this the same as the above
  member classVariable = "bonjour"
  // overriding a class method is not a good idea, since it affects the inherited class globally
  method classMethod(a)
    // local self = self
    // local inherited = self.classMethod
    local localVariable = classVariable + " a tous"
    print(localVariable)
  end
end
//
constructor SpecialExample()
  // member class = SpecialExample
  // member inherit = class.inherit()
  // instance = self
  member instanceVariable = 42
  // method create a local variable that is the value of x thus making it possible to call inherited methods
  method instanceMethod()
    // local self = self
    // local inherited = self.instanceMethod
    inherited()
    print("World")
  end
end






class Object
end

constructor Object()
  member instance = self
end




// Class.inherit = Undefined
// Class.class = Undefined

// Object.inherit = Undefined
Object.class = Class

Error.inherit = Object
Error.class = Class

SpecialError.inherit = Error
SpecialError.class = Class

// objectInstance.inherit = Undefined
objectInstance.class = Object
objectInstance.instance = specialErrorInstance

errorInstance.inherit = objectInstance
errorInstance.class = Error

specialErrorInstance.inherit = errorInstance
specialErrorInstance.class = SpecialError

// This is an error. The assignment = operator can not be used in an expression.
local a = b = c

// Test if a.class == Error or a.class inherits from Error.
if a is Error then
end

class Object
end


// inherit is a write once variable (after the first write a write has no effect)
class Error
  // member inherit = Object
  // member class = Class
  constructor ()
    member class = Error
    member inherit = class.inherit(); instance = self
    member a = 10
    // method create a local variable that is the value of x thus making it possible to call inherited methods
    method x ()
      print("Hello")
    end
  end
end

class SpecialError(Error)
  // member inherit = Error
  // member class = SpecialError
end

constructor SpecialError()
  member class = SpecialError
  member inherit = class.inherit(); instance = self
  member b = 20
  // method create a local variable that is the value of x thus making it possible to call inherited methods
  local inherited = x
  method x ()
    inherited()
    print("World")
  end
end

special = SpecialError()
special.inherit.inherit.instance == special
special.inherit.inherit.class == Object

special.inherit.class = Error
special.inherit.inherit == errorInstance
special.inherit.x == method()
special.inherit.a == 10

special.b == 20

special.x()

"Hello"


--      setmetatable(c, {__index = function (t, k)
--        local v = search(k, arg)
--        t[k] = v       -- cache
--        shadows.add(k)
--       return v
--      end})


function class(inherits)
  local instance = {}
  setmetatable(instance, inherits)
  return instance
end

ObjectClass = class()
do
  local selfClass = ObjectClass
  local siblings = {}

  function selfClass.siblings()
    return siblings
  end

  function selfClass.get(name)
    -- return variable with no caching
  end

  function selfClass.set(name)
    -- modify variable (do not create shadow)
  end
  
  function selfClass.super()
    return getmetatable(self)
  end

  function self.new()
    return self.initialize({})
  end

  function self.initialize(instance)
    local self = instance

    function self.hello()
      print "hello"
    end

    return self
  end
end
Object = ObjectClass.new

SpecialObjectClass = class(Object)
do
  local self = SpecialObjectClass
  
  function self.new(a, b, c)
    return self.initialize({})
  end

  function self.initialize(instance, a, b, c)
    local self = self.inherits().initialize(instance)
    
    local inherited = self.hello
    function self.hello()
      inherited()
      print "world"
    end
 
    return self
  end    
end
SpecialObject = SpecialObjectClass.new


instance = Object()
instance = ObjectClass.new()


Class = {}
do
  local self = Class
  local siblings = {}
  local shadows = {}
  function self.class()
    return self
  end
  function self.siblings()
    return siblings
  end
  function self.get(name)
    -- return variable with no caching
  end
  function self.set(name)
    -- modify variable (do not create shadow)
  end
  
        ...
      setmetatable(c, {__index = function (t, k)
        local v = search(k, arg)
        t[k] = v       -- cache
        shadows.add(k)
        return v
      end})
      ...

end

Object = {}
do
  Local self = Object
  Local inherited
  Inherited = self.methodx
  Function self.methodx()
    Inherited()
    ...
  End
  Inherited = self.methody
  Function self.methoy()
    Inherited()
  End



function delegate(instance, method)
  local self = instance
  return function (...)
    self:method(args)
  end
end

function class(inherits)
  local class = {}

  if inherits == nil then
    inherits = {}
    function inherits.__call(class, ...) 
      local instance = {}
      setmetatable(instance, class)
      instance:initialize(unpack(arg))
    end
  end

  setmetatable(class, inherits)

  return class
end

Object = class()
do
  local privateA = ""

  Object.publicA = ""
 
  function Object:inherits()
    getmetatable(self)
  end

  function Object:initialize(a)
    privateA = "private " .. a
    self.publicA = "public " .. a
  end
  
  function Object:print()
    print(privateA)
    print(publicA)
  end
end

Special = class()
do
  local privateB = ""

  Special.publicB = ""
  
  function Special:initialize(a, b) 
    self:inherits().initialize(a)
    privateB = "private " .. b
    self.publicB = "public " .. b
  end

  function Special:print()
    self:inherits().print()
    print(privateB)
    print(publicB)
  end
end

x = Object("Hello")
y = Special("Hello", "World")