forked from Lukc/alsace.netlib.re
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass.moon
102 lines (78 loc) · 2.18 KB
/
class.moon
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
---
-- @module Class
--
-- Differences with moonscript’s builtin class:
--
-- - __init instead of new
-- - `getmetatable(instance)` instead of `instance.__class`
-- - class constructor can be externally defined through __constructor.
-- - Instances can be called if `__call` is defined in its class.
-- - inheritance works with `__index`, and `__index` can be set to anything,
-- allowing dynamic inheritance or other forms of obtaining data. See Lua
-- metamethods for informations about __index.
-- - class variables are defined through the __class array, and not through
-- `@variable:` definitions.
-- - Constructor arguments are *always* tables.
--
-- @todo Some intense renaming MIGHT be necessary.
-- @todo This part will definitely require moar documentation. =|
--
-- @usage
-- MyClass = Class
-- __init: (arg) =>
-- self.value = arg.value or 42
--
-- myInstance = MyClass value: 3.14
--
-- print myInstance.value
-- -- 3.14
---
ClassData = (_class, data) ->
data or= {}
setmetatable data,
__tostring: =>
"<ClassData: #{_class}>"
data
Class = setmetatable {},
__tostring: => "<Class>"
__call: (name, def) =>
-- FIXME: Using debug may prove more useful.
if type(name) == "table"
def = name
elseif type(name) == "string"
def.__name or= name
unless def.__tostring
def.__tostring = =>
"<#{def.__name or "(anonymous)"}>"
unless def.__index
def.__index = (key) =>
value = rawget self, key
if value
return value
value = def[key]
if value
return value
__class = ClassData def, def.__class
__class.__call or= def.__construct or (arg) =>
if type(arg) == "nil"
arg = {}
elseif type(arg) != "table"
error "Class received a non-table argument"
instance = setmetatable {}, def
if def.__init
def.__init instance, arg
instance
__class.__index or= (key) =>
value = rawget self, key
if value
return value
__class = rawget self, "__class"
if __class
value = rawget __class, key
if value
return value
-- erroring __new_index ?
__class.__tostring or= =>
"<Class: #{def.__name or "(anonymous)"}>"
setmetatable def, __class
Class