Skip to content

Commit b31547d

Browse files
committed
feat: wip
1 parent a16fb24 commit b31547d

File tree

3 files changed

+246
-46
lines changed

3 files changed

+246
-46
lines changed

src/luajit/lua_state.cr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,16 @@ module Luajit
14101410
end
14111411
end
14121412

1413+
# Cleans up *arr* refs for Lua GC
1414+
def clean(arr : Array(LuaAny)) : Nil
1415+
arr.each { |i| remove_ref(i) }
1416+
end
1417+
1418+
# Cleans up *hash* refs for Lua GC
1419+
def clean(hash : Hash(String | Float64, LuaAny)) : Nil
1420+
hash.each { |_, v| remove_ref(v) }
1421+
end
1422+
14131423
private macro push_fn__eq
14141424
push_fn do |%lua_state|
14151425
%state = LuaState.new(%lua_state)

src/wrappers/path.cr

Lines changed: 223 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,255 @@ class Luajit::Wrappers::Path < Luajit::LuaObject
44
global_name "Path"
55
metatable_name "__PATH__"
66

7-
# ---@field new fun(path: string?): self
7+
# ---@field new fun(path: string?): Path
88
def_class_method "new" do |state|
9-
if state.is_none?(1)
10-
_self = new(::Path.new)
11-
elsif state.is_string?(1)
12-
_self = new(::Path.new(state.to_string(1)))
13-
else
14-
state.raise_type_error!(1, "expected string or nil")
15-
end
16-
Luajit.setup_userdata(state, _self, self)
9+
instance =
10+
if state.is_none_or_nil?(1)
11+
new ::Path.new
12+
elsif state.is_string?(1)
13+
new ::Path.new(state.to_string(1))
14+
else
15+
state.raise_type_error!(1, "expected string or nil")
16+
end
17+
Luajit.setup_userdata(state, instance, self)
1718
1
1819
end
1920

20-
# ---@field home fun(): self
21+
# ---@field home fun(): Path
2122
def_class_method "home" do |state|
22-
_self = new(::Path.home)
23-
Luajit.setup_userdata(state, _self, self)
23+
Luajit.setup_userdata(state, new(::Path.home), self)
2424
1
2525
end
2626

2727
# ---@field is_absolute fun(self): boolean
2828
def_instance_method "is_absolute" do |state|
2929
state.assert_userdata!(1)
30-
_self = Luajit.userdata_value(state, self, 1)
31-
state.push _self.path.absolute?
30+
instance = Luajit.userdata_value(state, self, 1)
31+
state.push instance.path.absolute?
3232
1
3333
end
3434

35-
# ---@field anchor fun(self): self?
36-
def_instance_method "anchor" do |state|
35+
# ---@field basename fun(self, suffix: string?): string
36+
def_instance_method "basename" do |state|
3737
state.assert_userdata!(1)
38-
_self = Luajit.userdata_value(state, self, 1)
38+
instance = Luajit.userdata_value(state, self, 1)
3939

40-
new_path = _self.path.anchor
40+
suffix =
41+
if state.is_none_or_nil?(2)
42+
nil
43+
elsif state.is_string?(2)
44+
state.to_string(2)
45+
else
46+
state.raise_type_error!(2, "expected string or nil")
47+
end
4148

42-
unless new_path
43-
state.push(nil)
44-
next 1
49+
state.push instance.path.basename(suffix)
50+
1
51+
end
52+
53+
# ---@field dirname fun(self): string
54+
def_instance_method "dirname" do |state|
55+
state.assert_userdata!(1)
56+
instance = Luajit.userdata_value(state, self, 1)
57+
state.push instance.path.dirname
58+
1
59+
end
60+
61+
# ---@field each_parent fun(self, cb: fun(path: Path))
62+
def_instance_method "each_parent" do |state|
63+
state.assert_userdata!(1)
64+
state.assert_function!(2)
65+
66+
instance = Luajit.userdata_value(state, self, 1)
67+
fn_index = 2
68+
69+
state.get_global("Path")
70+
state.get_field(-1, "new")
71+
state.pcall(0, 1)
72+
temp_path_index = state.size
73+
temp_path = Luajit.userdata_value(state, self, temp_path_index)
74+
75+
instance.path.each_parent do |path|
76+
temp_path.path = path
77+
78+
state.push_value(fn_index)
79+
state.push_value(temp_path_index)
80+
state.pcall(1, 0)
4581
end
82+
0
83+
end
84+
85+
# ---@field each_part fun(self, cb: fun(str: string))
86+
def_instance_method "each_part" do |state|
87+
state.assert_userdata!(1)
88+
state.assert_function!(2)
4689

47-
state.get_global("__PATH__")
90+
instance = Luajit.userdata_value(state, self, 1)
91+
fn_index = 2
92+
93+
instance.path.each_part do |component|
94+
state.push_value(fn_index)
95+
state.push(component)
96+
state.pcall(1, 0)
97+
end
98+
0
99+
end
100+
101+
# ---@field ends_with_separator fun(self): boolean
102+
def_instance_method "ends_with_separator" do |state|
103+
state.assert_userdata!(1)
104+
instance = Luajit.userdata_value(state, self, 1)
105+
state.push instance.path.ends_with_separator?
106+
1
107+
end
108+
109+
# ---@class PathExpandOptions
110+
# ---@field base Path|string?
111+
# ---@field home Path|string|boolean?
112+
# ---@field expand_base boolean?
113+
#
114+
# ---@field expand fun(self, options: PathExpandOptions?): Path
115+
def_instance_method "expand" do |state|
116+
state.assert_userdata!(1)
117+
118+
instance = Luajit.userdata_value(state, self, 1)
119+
120+
state.get_global("Path")
48121
state.get_field(-1, "new")
49122
state.pcall(0, 1)
50-
__self = Luajit.userdata_value(state, self, -1)
51-
__self.path = new_path
123+
new_path = Luajit.userdata_value(state, self, -1)
124+
new_path_index = state.size
125+
126+
if state.is_none_or_nil?(2)
127+
new_path.path = instance.path.expand
128+
next 1
129+
end
130+
131+
unless state.is_table?(2)
132+
state.raise_type_error!(2, "expected table or nil")
133+
end
134+
135+
state.get_field(2, "base")
136+
base_index = state.size
137+
138+
state.get_field(2, "home")
139+
home_index = state.size
140+
141+
state.get_field(2, "expand_base")
142+
expand_base_index = state.size
143+
144+
base =
145+
if state.is_string?(base_index)
146+
state.to_string(base_index)
147+
elsif state.is_userdata?(base_index)
148+
Luajit.userdata_value(state, self, base_index).path
149+
else
150+
Dir.current
151+
end
152+
153+
home =
154+
if state.is_string?(home_index)
155+
state.to_string(home_index)
156+
elsif state.is_userdata?(home_index)
157+
Luajit.userdata_value(state, self, home_index).path
158+
elsif state.is_bool?(home_index)
159+
state.to_boolean(home_index)
160+
else
161+
false
162+
end
163+
164+
expand_base =
165+
if state.is_bool?(expand_base_index)
166+
state.to_boolean(expand_base_index)
167+
else
168+
true
169+
end
170+
171+
new_path.path = instance.path.expand(base: base, home: home, expand_base: expand_base)
172+
state.push_value(new_path_index)
52173
1
53174
end
54175

55-
# ---@operator tostring(self): string
176+
# ---@field extension fun(self): string
177+
def_instance_method "extension" do |state|
178+
state.assert_userdata!(1)
179+
instance = Luajit.userdata_value(state, self, 1)
180+
state.push instance.path.extension
181+
1
182+
end
183+
184+
# ---@field join fun(self, parts: string[]|string): Path
185+
def_instance_method "join" do |state|
186+
state.assert_userdata!(1)
187+
state.assert_any!(2)
188+
instance = Luajit.userdata_value(state, self, 1)
189+
190+
if state.is_string?(2)
191+
state.get_global("Path")
192+
state.get_field(-1, "new")
193+
state.pcall(0, 1)
194+
new_path = Luajit.userdata_value(state, self, -1)
195+
new_path.path = instance.path.join(state.to_string(2))
196+
1
197+
elsif state.is_table?(2)
198+
state.get_global("Path")
199+
state.get_field(-1, "new")
200+
state.pcall(0, 1)
201+
new_path = Luajit.userdata_value(state, self, -1)
202+
new_path_index = state.size
203+
204+
parts = [] of ::String
205+
206+
any_parts = state.to_a(2)
207+
any_parts.each do |i|
208+
if value = i.as_s?
209+
parts << value
210+
else
211+
break
212+
end
213+
end
214+
state.clean(any_parts)
215+
216+
new_path.path = instance.path.join(*parts)
217+
state.push_value(new_path_index)
218+
1
219+
else
220+
state.raise_type_error!(2, "expected table or string")
221+
end
222+
end
223+
224+
# ---@field __tostring fun(self): string
56225
def_instance_method "__tostring" do |state|
57226
state.assert_userdata!(1)
58-
_self = Luajit.userdata_value(state, self, 1)
59-
state.push _self.path.to_s
227+
instance = Luajit.userdata_value(state, self, 1)
228+
state.push instance.path.to_s
229+
1
230+
end
231+
232+
# ---@operator concat(): Path
233+
# op1 = Path, op2 = Path
234+
# op1 = Path, op2 = string
235+
def_instance_method "__concat" do |state|
236+
state.assert_userdata!(1)
237+
state.assert_any!(2)
238+
239+
instance = Luajit.userdata_value(state, self, 1)
240+
241+
if state.is_string?(2)
242+
op2 = state.to_string(2)
243+
op2_path = instance.path.join(op2)
244+
elsif state.is_userdata?(2)
245+
op2 = Luajit.userdata_value(state, self, 2)
246+
op2_path = instance.path.join(op2.path)
247+
else
248+
state.raise_type_error!(2, "expected Path or string")
249+
end
250+
251+
state.get_global("Path")
252+
state.get_field(-1, "new")
253+
state.pcall(0, 1)
254+
new_path = Luajit.userdata_value(state, self, -1)
255+
new_path.path = op2_path
60256
1
61257
end
62258

src/wrappers/path.lua

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
11
---@meta _
22

3-
---@class PathDriveAndRoot
4-
---@field drive string|NIL
5-
---@field root string|NIL
6-
73
---@class PathExpandOptions
84
---@field base Path|string?
95
---@field home Path|string|boolean?
106
---@field expand_base boolean?
117

128
---@class (exact) Path
13-
---@field new fun(path: string?): self
14-
---@field home fun(): self
9+
---@field new fun(path: string?): Path
10+
---@field home fun(): Path
1511
---@field is_absolute fun(self): boolean
16-
---@field anchor fun(self): self?
1712
---@field basename fun(self, suffix: string?): string
1813
---@field dirname fun(self): string
19-
---@field drive fun(self): self?
20-
---@field drive_and_root fun(self): PathDriveAndRoot
2114
---@field each_parent fun(self, cb: fun(path: Path))
2215
---@field each_part fun(self, cb: fun(str: string))
2316
---@field ends_with_separator fun(self): boolean
24-
---@field expand fun(self, options: PathExpandOptions?)
17+
---@field expand fun(self, options: PathExpandOptions?): Path
2518
---@field extension fun(self): string
26-
---@field join fun(self, parts: string[]|string): self
27-
---@field normalize fun(self, remove_final_separator: boolean?)
28-
---@field parent fun(self): self
29-
---@field parents fun(self): self[]
19+
---@field join fun(self, parts: string[]|string): Path
20+
---@field normalize fun(self, remove_final_separator: boolean?): Path
21+
---@field parent fun(self): Path
22+
---@field parents fun(self): Path[]
3023
---@field parts fun(self): string[]
31-
---@field relative_to fun(self, base: self|string): self
32-
---@field is_relative_to fun(self, base: self|string): self?
33-
---@field root fun(self): self?
34-
---@field sibling fun(self, name: self|string): self
24+
---@field relative_to fun(self, base: Path|string): Path
25+
---@field is_relative_to fun(self, base: Path|string): Path?
26+
---@field root fun(self): Path?
27+
---@field sibling fun(self, name: Path|string): Path
3528
---@field stem fun(self): string
36-
---@operator concat(): string
29+
---@field __tostring fun(self): string
30+
---@operator concat(): Path
3731
Path = {}

0 commit comments

Comments
 (0)