Skip to content

Commit 5164ab0

Browse files
committed
add is_instance and is_object to moon library
1 parent 74e1e55 commit 5164ab0

File tree

6 files changed

+173
-26
lines changed

6 files changed

+173
-26
lines changed

docs/standard_lib.md

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,52 @@ copy = (arg) -> {k,v for k,v in pairs self}
108108

109109
### `is_object(value)`
110110

111-
Returns true if `value` is an instance of a MoonScript class, false otherwise.
111+
**Deprecated:** Use `is_instance` or `is_class` instead. `is_object` returns
112+
truthy for instances, classes, and `__base` tables — any table with `__class`
113+
accessible. It cannot distinguish between these cases.
114+
115+
### `is_class(value)`
116+
117+
Returns `true` if `value` is a MoonScript class table, `false` otherwise.
118+
Returns `false` for instances, `__base` tables, plain tables, and non-table
119+
values.
120+
121+
```moon
122+
class MyClass
123+
124+
is_class MyClass -- true
125+
is_class MyClass! -- false
126+
is_class MyClass.__base -- false
127+
```
128+
129+
### `is_instance(value)`
130+
131+
Returns `true` if `value` is an instance of a MoonScript class, `false`
132+
otherwise. Returns `false` for class tables, `__base` tables, plain tables, and
133+
non-table values.
134+
135+
```moon
136+
class MyClass
137+
138+
is_instance MyClass! -- true
139+
is_instance MyClass -- false
140+
is_instance MyClass.__base -- false
141+
```
112142

113143
### `type(value)`
114144

115-
If `value` is an instance of a MoonScript class, then return it's class object.
116-
Otherwise, return the result of calling Lua's type method.
145+
If `value` is an instance of a MoonScript class, then return its class object.
146+
If `value` is a class table, return the class itself. Returns the result of
147+
calling Lua's built-in `type` for all other values, including `__base` tables
148+
and plain tables.
117149

118150
```moon
119151
class MyClass
120-
nil
121152
122153
x = MyClass!
123154
assert type(x) == MyClass
155+
assert type(MyClass) == MyClass
156+
assert type(MyClass.__base) == "table"
124157
```
125158

126159
### `bind_methods(obj)`

moon/init.lua

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,31 @@ do
77
local _obj_0 = require("moonscript.util")
88
getfenv, setfenv, dump = _obj_0.getfenv, _obj_0.setfenv, _obj_0.dump
99
end
10-
local p, is_object, type, debug, run_with_scope, bind_methods, defaultbl, extend, copy, mixin, mixin_object, mixin_table, fold
10+
local p, is_object, is_class, is_instance, type, debug, run_with_scope, bind_methods, defaultbl, extend, copy, mixin, mixin_object, mixin_table, fold
1111
p = function(o, ...)
1212
print(dump(o))
1313
if select("#", ...) > 0 then
1414
return p(...)
1515
end
1616
end
17-
is_object = function(value)
17+
is_object = function(value) -- deprecated: use is_instance or is_class instead
1818
return lua.type(value) == "table" and value.__class
1919
end
20+
is_class = function(value)
21+
return lua.type(value) == "table" and rawget(value, "__base") ~= nil
22+
end
23+
is_instance = function(value)
24+
if lua.type(value) == "table" then
25+
local mt = getmetatable(value)
26+
return mt and rawget(mt, "__class") ~= nil
27+
end
28+
return false
29+
end
2030
type = function(value)
2131
local base_type = lua.type(value)
2232
if base_type == "table" then
2333
local cls = value.__class
24-
if cls then
34+
if cls and rawget(value, "__class") == nil then
2535
return cls
2636
end
2737
end
@@ -164,6 +174,8 @@ return {
164174
dump = dump,
165175
p = p,
166176
is_object = is_object,
177+
is_class = is_class,
178+
is_instance = is_instance,
167179
type = type,
168180
debug = debug,
169181
run_with_scope = run_with_scope,

moon/init.moon

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,24 @@ p = (o, ...) ->
99
if select("#", ...) > 0
1010
p ...
1111

12-
is_object = (value) -> -- is a moonscript object
12+
is_object = (value) -> -- deprecated: use is_instance or is_class instead
1313
lua.type(value) == "table" and value.__class
1414

15+
is_class = (value) ->
16+
lua.type(value) == "table" and rawget(value, "__base") != nil
17+
18+
is_instance = (value) ->
19+
if lua.type(value) == "table"
20+
mt = getmetatable value
21+
return mt and rawget(mt, "__class") != nil
22+
false
23+
1524
type = (value) -> -- class aware type
1625
base_type = lua.type value
1726
if base_type == "table"
1827
cls = value.__class
19-
return cls if cls
28+
if cls and rawget(value, "__class") == nil
29+
return cls
2030
base_type
2131

2232
debug = setmetatable {
@@ -130,6 +140,6 @@ fold = (items, fn)->
130140
items[1]
131141

132142
{
133-
:dump, :p, :is_object, :type, :debug, :run_with_scope, :bind_methods,
143+
:dump, :p, :is_object, :is_class, :is_instance, :type, :debug, :run_with_scope, :bind_methods,
134144
:defaultbl, :extend, :copy, :mixin, :mixin_object, :mixin_table, :fold
135145
}

moonscript/util.lua

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ concat = table.concat
33
local unpack = unpack or table.unpack
44
local type = type
55
local moon = {
6-
is_object = function(value)
7-
return type(value) == "table" and value.__class
6+
is_class = function(value)
7+
return type(value) == "table" and rawget(value, "__base") ~= nil
8+
end,
9+
is_instance = function(value)
10+
if type(value) == "table" then
11+
local mt = getmetatable(value)
12+
return mt and rawget(mt, "__class") ~= nil
13+
end
14+
return false
815
end,
916
is_a = function(thing, t)
1017
if not (type(thing) == "table") then
@@ -23,7 +30,7 @@ local moon = {
2330
local base_type = type(value)
2431
if base_type == "table" then
2532
local cls = value.__class
26-
if cls then
33+
if cls and rawget(value, "__class") == nil then
2734
return cls
2835
end
2936
end

moonscript/util.moon

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ import concat from table
44
unpack = unpack or table.unpack
55
type = type
66

7-
moon =
8-
is_object: (value) -> -- is a moonscript object
9-
type(value) == "table" and value.__class
7+
moon = {
8+
is_class: (value) ->
9+
type(value) == "table" and rawget(value, "__base") != nil
10+
11+
is_instance: (value) ->
12+
if type(value) == "table"
13+
mt = getmetatable value
14+
return mt and rawget(mt, "__class") != nil
15+
false
1016

1117
is_a: (thing, t) ->
1218
return false unless type(thing) == "table"
@@ -22,8 +28,10 @@ moon =
2228
base_type = type value
2329
if base_type == "table"
2430
cls = value.__class
25-
return cls if cls
31+
if cls and rawget(value, "__class") == nil
32+
return cls
2633
base_type
34+
}
2735

2836
-- convet position in text to line number
2937
pos_to_line = (str, pos) ->

spec/moon_spec.moon

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,37 @@ describe "moon", ->
88
with_dev ->
99
moon = require "moon"
1010

11-
it "should determine correct type", ->
12-
class Test
13-
14-
things = {
15-
Test, Test!, 1, true, nil, "hello"
16-
}
17-
18-
types = [moon.type t for t in *things]
19-
assert.same types, { Test, Test, "number", "boolean", "nil", "string" }
11+
describe "type", ->
12+
it "returns the class for a class", ->
13+
class Test
14+
assert.equal Test, moon.type Test
15+
16+
it "returns the class for an instance", ->
17+
class Test
18+
assert.equal Test, moon.type Test!
19+
20+
it "returns 'table' for __base", ->
21+
class Test
22+
assert.equal "table", moon.type Test.__base
23+
24+
it "returns primitive type for non-tables", ->
25+
assert.equal "number", moon.type 1
26+
assert.equal "boolean", moon.type true
27+
assert.equal "nil", moon.type nil
28+
assert.equal "string", moon.type "hello"
29+
assert.equal "function", moon.type ->
30+
31+
it "returns 'table' for plain tables", ->
32+
assert.equal "table", moon.type {}
33+
assert.equal "table", moon.type {hello: "world"}
34+
35+
it "works with inheritance", ->
36+
class Parent
37+
class Child extends Parent
38+
assert.equal Child, moon.type Child!
39+
assert.equal Parent, moon.type Parent!
40+
assert.equal "table", moon.type Child.__base
41+
assert.equal "table", moon.type Parent.__base
2042

2143
it "should get upvalue", ->
2244
fn = do
@@ -114,6 +136,61 @@ describe "moon", ->
114136

115137
assert.same a, { hello: "world", cat: "mouse", foo: "bar"}
116138

139+
describe "is_class", ->
140+
it "returns true for a class", ->
141+
class Hello
142+
assert.truthy moon.is_class Hello
143+
144+
it "returns false for an instance", ->
145+
class Hello
146+
assert.falsy moon.is_class Hello!
147+
148+
it "returns false for __base", ->
149+
class Hello
150+
assert.falsy moon.is_class Hello.__base
151+
152+
it "returns false for plain tables and non-tables", ->
153+
assert.falsy moon.is_class {}
154+
assert.falsy moon.is_class 123
155+
assert.falsy moon.is_class "hello"
156+
assert.falsy moon.is_class nil
157+
assert.falsy moon.is_class true
158+
159+
it "works with inheritance", ->
160+
class Parent
161+
class Child extends Parent
162+
assert.truthy moon.is_class Parent
163+
assert.truthy moon.is_class Child
164+
assert.falsy moon.is_class Child!
165+
166+
describe "is_instance", ->
167+
it "returns true for an instance", ->
168+
class Hello
169+
assert.truthy moon.is_instance Hello!
170+
171+
it "returns false for a class", ->
172+
class Hello
173+
assert.falsy moon.is_instance Hello
174+
175+
it "returns false for __base", ->
176+
class Hello
177+
assert.falsy moon.is_instance Hello.__base
178+
179+
it "returns false for plain tables and non-tables", ->
180+
assert.falsy moon.is_instance {}
181+
assert.falsy moon.is_instance 123
182+
assert.falsy moon.is_instance "hello"
183+
assert.falsy moon.is_instance nil
184+
assert.falsy moon.is_instance true
185+
186+
it "works with inheritance", ->
187+
class Parent
188+
class Child extends Parent
189+
assert.truthy moon.is_instance Parent!
190+
assert.truthy moon.is_instance Child!
191+
assert.falsy moon.is_instance Parent
192+
assert.falsy moon.is_instance Child
193+
117194
it "should fold", ->
118195
numbers = {4,3,5,6,7,2,3}
119196
sum = moon.fold numbers, (a,b) -> a + b

0 commit comments

Comments
 (0)