· 5 years ago · Mar 28, 2020, 12:02 PM
1local Library = {}
2
3local ScreenGui = Instance.new("ScreenGui")
4 ScreenGui.Parent = game.Players.LocalPlayer:WaitForChild("PlayerGui")
5 ScreenGui.ResetOnSpawn = false
6function Library:CreateWindow(name)
7 wait(1.2)
8 local pos = 0.1
9 local get = ScreenGui:GetChildren()
10 if ScreenGui:FindFirstChild("Container") ~= nil then -- checking if there is already a menu
11 for i = 1, #get do
12 pos = pos + 0.05
13 end
14 else
15 pos = 0.1
16 end
17 local Container = Instance.new("ImageLabel")
18 local TextLabel = Instance.new("TextLabel")
19 local Underline = Instance.new("ImageLabel")
20 local Container_2 = Instance.new("ImageLabel") -- literally the best thing ever
21 local UIListLayout = Instance.new("UIListLayout") -- literally the most annoying thing ever
22 -- I didn't know how to create multiple windows so this is my best attempt - SkeletalScripts 2:14 AM 3/28/2020
23
24 Container.Name = "Container"
25 Container.Parent = ScreenGui
26 Container.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
27 Container.BackgroundTransparency = 1.000
28 Container.Position = UDim2.new(0.0200000033, 0, pos, 0)
29 Container.Size = UDim2.new(0, 230, 0, 39)
30 Container.Image = "rbxassetid://3570695787"
31 Container.ImageColor3 = Color3.fromRGB(45, 45, 45)
32 Container.ScaleType = Enum.ScaleType.Slice
33 Container.SliceCenter = Rect.new(100, 100, 100, 100)
34 Container.SliceScale = 0.040
35
36 TextLabel.Parent = Container
37 TextLabel.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
38 TextLabel.BackgroundTransparency = 1.000
39 TextLabel.Position = UDim2.new(0, 0, 0.2, 0)
40 TextLabel.Size = UDim2.new(1, 0, 0.574999988, 0)
41 TextLabel.Font = Enum.Font.Arial
42 TextLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
43 TextLabel.TextScaled = true
44 TextLabel.TextSize = 14.000
45 TextLabel.Text = name
46 TextLabel.TextWrapped = true
47
48 Container_2.Name = "Container"
49 Container_2.Parent = Container
50 Container_2.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
51 Container_2.BackgroundTransparency = 1.000
52 Container_2.ClipsDescendants = true
53 Container_2.Position = UDim2.new(1.08000004, 0, 1.95625503e-07, 0)
54 Container_2.Size = UDim2.new(0,240,0,0)
55 Container_2.Image = "rbxassetid://3570695787"
56 Container_2.ImageColor3 = Color3.fromRGB(45, 45, 45)
57 Container_2.ScaleType = Enum.ScaleType.Slice
58 Container_2.SliceCenter = Rect.new(100, 100, 100, 100)
59 Container_2.SliceScale = 0.040
60
61 UIListLayout.Parent = Container_2
62 UIListLayout.HorizontalAlignment = Enum.HorizontalAlignment.Right
63 UIListLayout.SortOrder = Enum.SortOrder.LayoutOrder
64 UIListLayout.Padding = UDim.new(0, 5)
65
66 Underline.Name = "Underline"
67 Underline.Parent = Container
68 Underline.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
69 Underline.BackgroundTransparency = 1.000
70 Underline.Position = UDim2.new(0,0,0.95,0)
71 Underline.Size = UDim2.new(1,0,0,4)
72 Underline.Image = "rbxassetid://3570695787"
73 Underline.ImageColor3 = Color3.fromRGB(255, 255, 255)
74 Underline.ScaleType = Enum.ScaleType.Slice
75 Underline.SliceCenter = Rect.new(100, 100, 100, 100)
76 Underline.SliceScale = 0.040
77 local UIGradient = Instance.new("UIGradient")
78
79 --Properties:
80
81 UIGradient.Color = ColorSequence.new{ColorSequenceKeypoint.new(0.00, Color3.fromRGB(20, 180, 255)), ColorSequenceKeypoint.new(0.13, Color3.fromRGB(185, 78, 121)), ColorSequenceKeypoint.new(0.30, Color3.fromRGB(96, 155, 98)), ColorSequenceKeypoint.new(0.51, Color3.fromRGB(147, 170, 161)), ColorSequenceKeypoint.new(0.72, Color3.fromRGB(241, 41, 41)), ColorSequenceKeypoint.new(0.86, Color3.fromRGB(124, 152, 150)), ColorSequenceKeypoint.new(1.00, Color3.fromRGB(20, 180, 255))}
82 UIGradient.Parent = Underline
83
84 local Tourmaline = {}
85
86 function Tourmaline:Toggle(name,callback)
87 callback = callback or function() end
88 local Toggle = Instance.new("ImageLabel")
89 local ToggleRound = Instance.new("ImageLabel")
90 local ToggleButton = Instance.new("TextButton")
91 local Text = Instance.new("TextLabel")
92 Toggle.Name = "Toggle"
93 Toggle.Parent = Container_2
94 Toggle.Active = true
95 Toggle.AnchorPoint = Vector2.new(0.5, 0.5)
96 Toggle.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
97 Toggle.BackgroundTransparency = 1.000
98 Toggle.ClipsDescendants = true
99 Toggle.Position = UDim2.new(0.5, 0, 0.243902475, 0)
100 Toggle.Selectable = true
101 Toggle.Size = UDim2.new(1, 0, 0, 30)
102 Toggle.Image = "rbxassetid://3570695787"
103 Toggle.ImageColor3 = Color3.fromRGB(56, 56, 56)
104 Toggle.ScaleType = Enum.ScaleType.Slice
105 Toggle.SliceCenter = Rect.new(100, 100, 100, 100)
106 Toggle.SliceScale = 0.040
107
108 ToggleRound.Name = "ToggleRound"
109 ToggleRound.Parent = Toggle
110 ToggleRound.Active = true
111 ToggleRound.AnchorPoint = Vector2.new(0.5, 0.5)
112 ToggleRound.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
113 ToggleRound.BackgroundTransparency = 1.000
114 ToggleRound.Position = UDim2.new(0.916666687, 0, 0.5, 0)
115 ToggleRound.Selectable = true
116 ToggleRound.Size = UDim2.new(0.166666776, 0, 1, 0)
117 ToggleRound.ZIndex = 3
118 ToggleRound.Image = "rbxassetid://3570695787"
119 ToggleRound.ImageColor3 = Color3.fromRGB(70, 70, 70)
120 ToggleRound.ScaleType = Enum.ScaleType.Slice
121 ToggleRound.SliceCenter = Rect.new(100, 100, 100, 100)
122 ToggleRound.SliceScale = 0.040
123
124 ToggleButton.Name = "ToggleButton"
125 ToggleButton.Parent = ToggleRound
126 ToggleButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
127 ToggleButton.BackgroundTransparency = 1.000
128 ToggleButton.Size = UDim2.new(1, 0, 1, 0)
129 ToggleButton.Font = Enum.Font.SourceSans
130 ToggleButton.Text = " "
131 ToggleButton.TextColor3 = Color3.fromRGB(0, 0, 0)
132 ToggleButton.TextSize = 14.000
133
134 Text.Name = "Text"
135 Text.Parent = Toggle
136 Text.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
137 Text.BackgroundTransparency = 1.000
138 Text.Size = UDim2.new(0.800000012, 0, 1, 0)
139 Text.Font = Enum.Font.SourceSans
140 Text.TextColor3 = Color3.fromRGB(255, 255, 255)
141 Text.TextScaled = true
142 Text.TextSize = 14.000
143 Text.TextWrapped = true
144
145 local toggled = 0
146 ToggleButton.MouseButton1Click:Connect(function()
147 if toggled == 0 then
148 toggled = 1
149 ToggleRound.ImageColor3 = Color3.fromRGB(200, 0, 0)
150 callback()
151 else
152 toggled = 0
153 ToggleRound.ImageColor3 = Color3.fromRGB(70, 70, 70)
154 end
155 end)
156 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,Toggle.Size.Y.Offset+5)
157
158 end
159
160 function Tourmaline:Section(name)
161 local Section = Instance.new("TextLabel")
162 local Background = Instance.new("ImageLabel")
163 local Background_2 = Instance.new("ImageLabel")
164
165 Section.Name = "Section"
166 Section.Parent = Container_2
167 Section.Text = name
168 Section.Active = true
169 Section.BackgroundColor3 = Color3.fromRGB(56, 56, 56)
170 Section.BackgroundTransparency = 1.000
171 Section.BorderColor3 = Color3.fromRGB(180, 180, 180)
172 Section.BorderSizePixel = 0
173 Section.Position = UDim2.new(1.3125, 0, 0.678861856, 0)
174 Section.Selectable = true
175 Section.Size = UDim2.new(1, 0, 0, 30)
176 Section.ZIndex = 3
177 Section.Font = Enum.Font.SourceSans
178 Section.TextColor3 = Color3.fromRGB(255, 255, 255)
179 Section.TextScaled = true
180 Section.TextSize = 24.000
181 Section.TextWrapped = true
182
183 Background.Name = "Background"
184 Background.Parent = Section
185 Background.Active = true
186 Background.AnchorPoint = Vector2.new(0.5, 0.5)
187 Background.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
188 Background.BackgroundTransparency = 1.000
189 Background.BorderSizePixel = 0
190 Background.Position = UDim2.new(0.5, 0, 0.5, 0)
191 Background.Selectable = true
192 Background.Size = UDim2.new(1, 0, 1, 0)
193 Background.ZIndex = 2
194 Background.Image = "rbxassetid://3570695787"
195 Background.ImageColor3 = Color3.fromRGB(45, 45, 45)
196 Background.ScaleType = Enum.ScaleType.Slice
197 Background.SliceCenter = Rect.new(100, 100, 100, 100)
198 Background.SliceScale = 0.040
199
200 Background_2.Name = "Background"
201 Background_2.Parent = Section
202 Background_2.Active = true
203 Background_2.AnchorPoint = Vector2.new(0.5, 0.5)
204 Background_2.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
205 Background_2.BackgroundTransparency = 1.000
206 Background_2.BorderSizePixel = 0
207 Background_2.Position = UDim2.new(0.5, 0, 0.5, 0)
208 Background_2.Selectable = true
209 Background_2.Size = UDim2.new(1, 0, 1.14999998, 0)
210 Background_2.Image = "rbxassetid://3570695787"
211 Background_2.ImageColor3 = Color3.fromRGB(70, 70, 70)
212 Background_2.ScaleType = Enum.ScaleType.Slice
213 Background_2.SliceCenter = Rect.new(100, 100, 100, 100)
214 Background_2.SliceScale = 0.040
215 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,Section.Size.Y.Offset+5)
216 end
217
218 function Tourmaline:Slider(name,callback)
219 callback = callback or function() end
220
221 local Slider = Instance.new("ImageLabel")
222 local Slide = Instance.new("Frame")
223 local Button = Instance.new("ImageButton")
224 local Num = Instance.new("TextLabel")
225 local Text_2 = Instance.new("TextLabel")
226
227 Slider.Name = "Slider"
228 Slider.Parent = Container_2
229 Slider.Active = true
230 Slider.AnchorPoint = Vector2.new(0.5, 0.5)
231 Slider.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
232 Slider.BackgroundTransparency = 1.000
233 Slider.ClipsDescendants = true
234 Slider.Position = UDim2.new(0.5, 0, 0.632113814, 0)
235 Slider.Selectable = true
236 Slider.Size = UDim2.new(1, 0, 0, 30)
237 Slider.Image = "rbxassetid://3570695787"
238 Slider.ImageColor3 = Color3.fromRGB(56, 56, 56)
239 Slider.ScaleType = Enum.ScaleType.Slice
240 Slider.SliceCenter = Rect.new(100, 100, 100, 100)
241 Slider.SliceScale = 0.040
242
243 Slide.Name = "Slide"
244 Slide.Parent = Slider
245 Slide.BackgroundColor3 = Color3.fromRGB(99, 99, 99)
246 Slide.BorderSizePixel = 0
247 Slide.Position = UDim2.new(0.554166913, 0, 0.299999505, 0)
248 Slide.Size = UDim2.new(0, 100, 0, 12)
249
250 Button.Name = "Button"
251 Button.Parent = Slide
252 Button.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
253 Button.BackgroundTransparency = 1.000
254 Button.BorderSizePixel = 0
255 Button.Size = UDim2.new(0, 4, 0, 11)
256 Button.Image = "rbxasset://textures/ui/GuiImagePlaceholder.png"
257
258 Num.Name = "Num"
259 Num.Parent = Slider
260 Num.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
261 Num.BackgroundTransparency = 1.000
262 Num.BorderColor3 = Color3.fromRGB(27, 42, 53)
263 Num.Position = UDim2.new(0.416666687, 0, 0, 0)
264 Num.Size = UDim2.new(0, 25, 0, 30)
265 Num.Font = Enum.Font.SourceSans
266 Num.Text = "0"
267 Num.TextColor3 = Color3.fromRGB(255, 255, 255)
268 Num.TextScaled = true
269 Num.TextSize = 14.000
270 Num.TextWrapped = true
271
272 Text_2.Name = "Text"
273 Text_2.Parent = Slider
274 Text_2.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
275 Text_2.BackgroundTransparency = 1.000
276 Text_2.BorderColor3 = Color3.fromRGB(27, 42, 53)
277 Text_2.Size = UDim2.new(0, 100, 0, 30)
278 Text_2.Font = Enum.Font.SourceSans
279 Text_2.Text = name
280 Text_2.TextColor3 = Color3.fromRGB(255, 255, 255)
281 Text_2.TextScaled = true
282 Text_2.TextSize = 14.000
283 Text_2.TextWrapped = true
284 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,Text_2.Size.Y.Offset+5)
285
286 local SliderBtn = Button
287 local Player = game:GetService("Players").LocalPlayer
288 local UIS = game:GetService("UserInputService")
289 local RuS = game:GetService("RunService")
290 -- Properties
291 local min = 0
292 local max = 100
293 local held = false
294 local step = "0.00"..max
295 local percentage = 0
296 function snap(number, factor)
297 if factor == 0 then
298 return number
299 else
300 return math.floor(number/factor+0.5)*factor
301 end
302 end
303 UIS.InputEnded:connect(function(input, processed)
304 if input.UserInputType == Enum.UserInputType.MouseButton1 then
305 held = false
306 end
307 end)
308 SliderBtn.MouseButton1Down:connect(function()
309 held = true
310 end)
311 RuS.RenderStepped:connect(function(delta)
312 if held then
313 local MousePos = UIS:GetMouseLocation().X
314 local BtnPos = SliderBtn.Position
315 local SliderSize = Slider.AbsoluteSize.X
316 local SliderPos = Slider.AbsolutePosition.X
317 local pos = snap((MousePos-SliderPos)/SliderSize,step)
318 percentage = math.clamp(pos,0,1)
319 local per = pos / SliderSize
320 SliderBtn.Position = UDim2.new(percentage,0,BtnPos.Y.Scale, BtnPos.Y.Offset)
321 local val = math.floor((min + (max - min)* per)* max) / max
322 if val > max/100 then val = max/100 end if val < min then val = min end
323 Num.Text = tostring(val*100)
324 callback(val*100)
325 end
326 end)
327
328 end
329
330 function Tourmaline:Box(name,callback)
331 callback = callback or function() end
332 local Box = Instance.new("ImageLabel")
333 local Box_2 = Instance.new("TextBox")
334 local Background_3 = Instance.new("ImageLabel")
335 local TextLabel_2 = Instance.new("TextLabel")
336
337 Box.Name = "Box"
338 Box.Parent = Container_2
339 Box.Active = true
340 Box.AnchorPoint = Vector2.new(0.5, 0.5)
341 Box.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
342 Box.BackgroundTransparency = 1.000
343 Box.Position = UDim2.new(0.499999881, 0, 0.77439028, 0)
344 Box.Selectable = true
345 Box.Size = UDim2.new(0.999999881, 0, 0, 30)
346 Box.Image = "rbxassetid://3570695787"
347 Box.ImageColor3 = Color3.fromRGB(56, 56, 56)
348 Box.ScaleType = Enum.ScaleType.Slice
349 Box.SliceCenter = Rect.new(100, 100, 100, 100)
350 Box.SliceScale = 0.040
351
352 Box_2.Name = "Box"
353 Box_2.Parent = Box
354 Box_2.BackgroundColor3 = Color3.fromRGB(56, 56, 56)
355 Box_2.BackgroundTransparency = 1.000
356 Box_2.BorderColor3 = Color3.fromRGB(180, 180, 180)
357 Box_2.BorderSizePixel = 0
358 Box_2.Position = UDim2.new(0.762499988, 0, -0.0154471397, 0)
359 Box_2.Size = UDim2.new(0.23333329, 0, 0, 30)
360 Box_2.ZIndex = 2
361 Box_2.Font = Enum.Font.SourceSans
362 Box_2.PlaceholderColor3 = Color3.fromRGB(178, 178, 178)
363 Box_2.Text = ""
364 Box_2.TextColor3 = Color3.fromRGB(255, 255, 255)
365 Box_2.TextScaled = true
366 Box_2.TextSize = 24.000
367 Box_2.TextWrapped = true
368
369 Background_3.Name = "Background"
370 Background_3.Parent = Box
371 Background_3.Active = true
372 Background_3.AnchorPoint = Vector2.new(0.5, 0.5)
373 Background_3.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
374 Background_3.BackgroundTransparency = 1.000
375 Background_3.Position = UDim2.new(0.879979074, 0, 0.5, 0)
376 Background_3.Selectable = true
377 Background_3.Size = UDim2.new(0.259958446, 0, 1, 0)
378 Background_3.Image = "rbxassetid://3570695787"
379 Background_3.ImageColor3 = Color3.fromRGB(75, 75, 75)
380 Background_3.ScaleType = Enum.ScaleType.Slice
381 Background_3.SliceCenter = Rect.new(100, 100, 100, 100)
382 Background_3.SliceScale = 0.040
383
384 TextLabel_2.Parent = Box
385 TextLabel_2.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
386 TextLabel_2.BackgroundTransparency = 1.000
387 TextLabel_2.Position = UDim2.new(-0.00100008654, 0, 0, 0)
388 TextLabel_2.Size = UDim2.new(0, 187, 0, 30)
389 TextLabel_2.ZIndex = 2
390 TextLabel_2.Font = Enum.Font.SourceSans
391 TextLabel_2.TextColor3 = Color3.fromRGB(255, 255, 255)
392 TextLabel_2.TextScaled = true
393 TextLabel_2.TextSize = 14.000
394 TextLabel_2.Text = name
395 TextLabel_2.TextWrapped = true
396 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,TextLabel_2.Size.Y.Offset+5)
397 Box_2.FocusLost:connect(function()
398 callback(Box_2.Text)
399 end)
400
401 end
402 function Tourmaline:Drag(whydoesthisexist)
403 local Dragger = Instance.new("ImageLabel")
404 local Background_4 = Instance.new("ImageLabel")
405 local TextLabel_3 = Instance.new("TextLabel")
406
407
408 Dragger.Name = "Dragger"
409 Dragger.Parent = Container_2
410 Dragger.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
411 Dragger.BackgroundTransparency = 1.000
412 Dragger.Position = UDim2.new(0, 0, 0.723577261, 0)
413 Dragger.Size = UDim2.new(0, 30, 0, 30)
414 Dragger.ZIndex = 2
415 Dragger.Image = "http://www.roblox.com/asset/?id=4826545533"
416
417 Background_4.Name = "Background"
418 Background_4.Parent = Dragger
419 Background_4.Active = true
420 Background_4.AnchorPoint = Vector2.new(0.5, 0.5)
421 Background_4.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
422 Background_4.BackgroundTransparency = 1.000
423 Background_4.Position = UDim2.new(-3.00399876, 0, 0.5, 0)
424 Background_4.Selectable = true
425 Background_4.Size = UDim2.new(8.00800133, 0, 1, 0)
426 Background_4.Image = "rbxassetid://3570695787"
427 Background_4.ImageColor3 = Color3.fromRGB(56, 56, 56)
428 Background_4.ScaleType = Enum.ScaleType.Slice
429 Background_4.SliceCenter = Rect.new(100, 100, 100, 100)
430 Background_4.SliceScale = 0.040
431
432 TextLabel_3.Parent = Dragger
433 TextLabel_3.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
434 TextLabel_3.BackgroundTransparency = 1.000
435 TextLabel_3.Position = UDim2.new(-7, 0, 0, 0)
436 TextLabel_3.Size = UDim2.new(0, 210, 0, 30)
437 TextLabel_3.Font = Enum.Font.SourceSans
438 TextLabel_3.Text = whydoesthisexist
439 TextLabel_3.TextColor3 = Color3.fromRGB(255, 255, 255)
440 TextLabel_3.TextScaled = true
441 TextLabel_3.TextSize = 14.000
442 TextLabel_3.TextWrapped = true
443 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,TextLabel_3.Size.Y.Offset+5)
444 local dragger = {}; do
445 local mouse = game:GetService("Players").LocalPlayer:GetMouse();
446 local inputService = game:GetService('UserInputService');
447 local heartbeat = game:GetService("RunService").Heartbeat;
448 -- // credits to Ririchi / Inori for this cute drag function :)
449 function dragger.new(frame)
450 local s, event = pcall(function()
451 return frame.MouseEnter
452 end)
453
454 if s then
455 frame.Active = true;
456 event:connect(function()
457 local input = frame.InputBegan:connect(function(key)
458 if key.UserInputType == Enum.UserInputType.MouseButton1 then
459 local objectPosition = Vector2.new(mouse.X - Container.AbsolutePosition.X, mouse.Y - Container.AbsolutePosition.Y);
460 while heartbeat:wait() and inputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
461 pcall(function()
462 Container:TweenPosition(UDim2.new(0, mouse.X - objectPosition.X + (Container.Size.X.Offset * Container.AnchorPoint.X), 0, mouse.Y - objectPosition.Y + (Container.Size.Y.Offset * Container.AnchorPoint.Y)), 'Out', 'Linear', 0.1, true);
463 end)
464 end
465 end
466 end)
467
468 local leave;
469 leave = frame.MouseLeave:connect(function()
470 input:disconnect();
471 leave:disconnect();
472 end)
473 end)
474 end
475 end
476 end
477 dragger.new(Dragger)
478
479 end
480 function Tourmaline:Button(name,callback)
481 callback = callback or function() end
482 local Button_2 = Instance.new("ImageLabel")
483 local Button_3 = Instance.new("TextButton")
484
485 Button_2.Name = "Button"
486 Button_2.Parent = Container_2
487 Button_2.Active = true
488 Button_2.AnchorPoint = Vector2.new(0.5, 0.5)
489 Button_2.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
490 Button_2.BackgroundTransparency = 1.000
491 Button_2.Position = UDim2.new(0.502083361, 0, 0.781504095, 0)
492 Button_2.Selectable = true
493 Button_2.Size = UDim2.new(1, 0, 0, 30)
494 Button_2.Image = "rbxassetid://3570695787"
495 Button_2.ImageColor3 = Color3.fromRGB(75, 75, 75)
496 Button_2.ScaleType = Enum.ScaleType.Slice
497 Button_2.SliceCenter = Rect.new(100, 100, 100, 100)
498 Button_2.SliceScale = 0.040
499
500 Button_3.Name = "Button"
501 Button_3.Parent = Button_2
502 Button_3.BackgroundColor3 = Color3.fromRGB(75, 75, 75)
503 Button_3.BorderColor3 = Color3.fromRGB(180, 180, 180)
504 Button_3.BorderSizePixel = 0
505 Button_3.Position = UDim2.new(0.0129707344, 0, 0, 0)
506 Button_3.Size = UDim2.new(0, 234, 1, 0)
507 Button_3.ZIndex = 2
508 Button_3.Font = Enum.Font.SourceSans
509 Button_3.Text = name
510 Button_3.TextColor3 = Color3.fromRGB(255, 255, 255)
511 Button_3.TextScaled = true
512 Button_3.TextSize = 24.000
513 Button_3.TextWrapped = true
514 Button_3.MouseButton1Click:Connect(function()callback()
515 end)
516 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,Button_2.Size.Y.Offset+5)
517 end
518 function Tourmaline:CommandBar()
519 local Execute = Instance.new("ImageLabel")
520 local Script = Instance.new("ImageLabel")
521 local Box_3 = Instance.new("TextBox")
522 local TextLabel_4 = Instance.new("TextLabel")
523 local ExecuteBackground = Instance.new("ImageLabel")
524 local ExecuteButton = Instance.new("TextButton")
525 local ClearBackground = Instance.new("ImageLabel")
526 local ClearButton = Instance.new("TextButton")
527
528 Execute.Name = "Execute"
529 Execute.Parent = Container_2
530 Execute.Active = true
531 Execute.AnchorPoint = Vector2.new(0.5, 0.5)
532 Execute.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
533 Execute.BackgroundTransparency = 1.000
534 Execute.Position = UDim2.new(0.500000119, 0, 0.709480345, 0)
535 Execute.Selectable = true
536 Execute.Size = UDim2.new(0, 240, 0, 90)
537 Execute.Image = "rbxassetid://3570695787"
538 Execute.ImageColor3 = Color3.fromRGB(56, 56, 56)
539 Execute.ScaleType = Enum.ScaleType.Slice
540 Execute.SliceCenter = Rect.new(100, 100, 100, 100)
541 Execute.SliceScale = 0.040
542
543 Script.Name = "Script"
544 Script.Parent = Execute
545 Script.Active = true
546 Script.AnchorPoint = Vector2.new(0.5, 0.5)
547 Script.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
548 Script.BackgroundTransparency = 1.000
549 Script.Position = UDim2.new(0.487735301, 0, 0.4888888, 0)
550 Script.Selectable = true
551 Script.Size = UDim2.new(1.00047052, 0, 0.333333522, 30)
552 Script.Image = "rbxassetid://3570695787"
553 Script.ImageColor3 = Color3.fromRGB(63, 63, 63)
554 Script.ScaleType = Enum.ScaleType.Slice
555 Script.SliceCenter = Rect.new(100, 100, 100, 100)
556 Script.SliceScale = 0.040
557
558 Box_3.Name = "Box"
559 Box_3.Parent = Script
560 Box_3.BackgroundColor3 = Color3.fromRGB(180, 180, 180)
561 Box_3.BackgroundTransparency = 0.900
562 Box_3.BorderColor3 = Color3.fromRGB(180, 180, 180)
563 Box_3.BorderSizePixel = 0
564 Box_3.Position = UDim2.new(0.0124941207, 0, 0, 0)
565 Box_3.Size = UDim2.new(1, 0, 1, 0)
566 Box_3.ZIndex = 2
567 Box_3.Font = Enum.Font.SourceSans
568 Box_3.PlaceholderColor3 = Color3.fromRGB(178, 178, 178)
569 Box_3.Text = 'print("I Hope you enjoy this executor!")'
570 Box_3.TextColor3 = Color3.fromRGB(255, 255, 255)
571 Box_3.TextSize = 12.000
572 Box_3.TextXAlignment = Enum.TextXAlignment.Left
573 Box_3.TextYAlignment = Enum.TextYAlignment.Top
574
575 TextLabel_4.Parent = Execute
576 TextLabel_4.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
577 TextLabel_4.BackgroundTransparency = 1.000
578 TextLabel_4.Size = UDim2.new(0, 240, 0, 10)
579 TextLabel_4.Font = Enum.Font.SourceSans
580 TextLabel_4.Text = "Executor"
581 TextLabel_4.TextColor3 = Color3.fromRGB(255, 255, 255)
582 TextLabel_4.TextSize = 10.000
583 TextLabel_4.TextWrapped = true
584
585 ExecuteBackground.Name = "ExecuteBackground"
586 ExecuteBackground.Parent = Execute
587 ExecuteBackground.Active = true
588 ExecuteBackground.AnchorPoint = Vector2.new(0.5, 0.5)
589 ExecuteBackground.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
590 ExecuteBackground.BackgroundTransparency = 1.000
591 ExecuteBackground.Position = UDim2.new(0.264583349, 0, 0.840793312, 0)
592 ExecuteBackground.Selectable = true
593 ExecuteBackground.Size = UDim2.new(0.379166454, 0, 0.0135536762, 30)
594 ExecuteBackground.Image = "rbxassetid://3570695787"
595 ExecuteBackground.ImageColor3 = Color3.fromRGB(125, 125, 125)
596 ExecuteBackground.ImageTransparency = 0.500
597 ExecuteBackground.ScaleType = Enum.ScaleType.Slice
598 ExecuteBackground.SliceCenter = Rect.new(100, 100, 100, 100)
599 ExecuteBackground.SliceScale = 0.040
600
601 ExecuteButton.Name = "ExecuteButton"
602 ExecuteButton.Parent = ExecuteBackground
603 ExecuteButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
604 ExecuteButton.BackgroundTransparency = 1.000
605 ExecuteButton.Size = UDim2.new(1, 0, 1, 0)
606 ExecuteButton.Font = Enum.Font.SourceSans
607 ExecuteButton.Text = "Execute"
608 ExecuteButton.TextColor3 = Color3.fromRGB(255, 255, 255)
609 ExecuteButton.TextScaled = true
610 ExecuteButton.TextSize = 14.000
611 ExecuteButton.TextWrapped = true
612
613 ClearBackground.Name = "ClearBackground"
614 ClearBackground.Parent = Execute
615 ClearBackground.Active = true
616 ClearBackground.AnchorPoint = Vector2.new(0.5, 0.5)
617 ClearBackground.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
618 ClearBackground.BackgroundTransparency = 1.000
619 ClearBackground.Position = UDim2.new(0.785416722, 0, 0.840793312, 0)
620 ClearBackground.Selectable = true
621 ClearBackground.Size = UDim2.new(0.379166454, 0, 0.0135536762, 30)
622 ClearBackground.Image = "rbxassetid://3570695787"
623 ClearBackground.ImageColor3 = Color3.fromRGB(125, 125, 125)
624 ClearBackground.ImageTransparency = 0.500
625 ClearBackground.ScaleType = Enum.ScaleType.Slice
626 ClearBackground.SliceCenter = Rect.new(100, 100, 100, 100)
627 ClearBackground.SliceScale = 0.040
628
629 ClearButton.Name = "ClearButton"
630 ClearButton.Parent = ClearBackground
631 ClearButton.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
632 ClearButton.BackgroundTransparency = 1.000
633 ClearButton.Size = UDim2.new(1, 0, 1, 0)
634 ClearButton.Font = Enum.Font.SourceSans
635 ClearButton.Text = "Clear"
636 ClearButton.TextColor3 = Color3.fromRGB(255, 255, 255)
637 ClearButton.TextScaled = true
638 ClearButton.TextSize = 14.000
639 ClearButton.TextWrapped = true
640
641 -- Gui to Lua
642-- Version: 3.2
643
644-- Instances
645
646-- Module Scripts:
647
648local fake_module_scripts = {}
649
650do -- nil.Loadstring
651 local script = Instance.new('ModuleScript', nil)
652 script.Name = "Loadstring"
653 local function module_script()
654 --[[
655 Credit to einsteinK.
656 Credit to Stravant for LBI.
657
658 Credit to the creators of all the other modules used in this.
659
660 Sceleratis was here and decided modify some things.
661
662 einsteinK was here again to fix a bug in LBI for if-statements
663 --]]
664
665 local waitDeps = {
666 'Rerubi';
667 'LuaK';
668 'LuaP';
669 'LuaU';
670 'LuaX';
671 'LuaY';
672 'LuaZ';
673 }
674
675 for i,v in pairs(waitDeps) do script:WaitForChild(v) end
676
677 local luaX = require(script.LuaX)
678 local luaY = require(script.LuaY)
679 local luaZ = require(script.LuaZ)
680 local luaU = require(script.LuaU)
681 local rerubi = require(script.Rerubi)
682
683 luaX:init()
684 local LuaState = {}
685
686 getfenv().script = nil
687
688 return function(str,env)
689 local f,writer,buff,name
690 local env = env or getfenv(2)
691 local name = (env.script and env.script:GetFullName())
692 local ran,error = pcall(function()
693 local zio = luaZ:init(luaZ:make_getS(str), nil)
694 if not zio then return error() end
695 local func = luaY:parser(LuaState, zio, nil, name or "nil")
696 writer, buff = luaU:make_setS()
697 luaU:dump(LuaState, func, writer, buff)
698 f = rerubi(buff.data, env)
699 end)
700
701 if ran then
702 return f,buff.data
703 else
704 return nil,error
705 end
706 end
707 end
708 fake_module_scripts[script] = module_script
709end
710do -- nil.LuaZ
711 local script = Instance.new('ModuleScript', nil)
712 script.Name = "LuaZ"
713 local function module_script()
714 --[[--------------------------------------------------------------------
715
716 lzio.lua
717 Lua buffered streams in Lua
718 This file is part of Yueliang.
719
720 Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
721 The COPYRIGHT file describes the conditions
722 under which this software may be distributed.
723
724 See the ChangeLog for more information.
725
726 ----------------------------------------------------------------------]]
727
728 --[[--------------------------------------------------------------------
729 -- Notes:
730 -- * EOZ is implemented as a string, "EOZ"
731 -- * Format of z structure (ZIO)
732 -- z.n -- bytes still unread
733 -- z.p -- last read position position in buffer
734 -- z.reader -- chunk reader function
735 -- z.data -- additional data
736 -- * Current position, p, is now last read index instead of a pointer
737 --
738 -- Not implemented:
739 -- * luaZ_lookahead: used only in lapi.c:lua_load to detect binary chunk
740 -- * luaZ_read: used only in lundump.c:ezread to read +1 bytes
741 -- * luaZ_openspace: dropped; let Lua handle buffers as strings (used in
742 -- lundump.c:LoadString & lvm.c:luaV_concat)
743 -- * luaZ buffer macros: dropped; buffers are handled as strings
744 -- * lauxlib.c:getF reader implementation has an extraline flag to
745 -- skip over a shbang (#!) line, this is not implemented here
746 --
747 -- Added:
748 -- (both of the following are vaguely adapted from lauxlib.c)
749 -- * luaZ:make_getS: create Reader from a string
750 -- * luaZ:make_getF: create Reader that reads from a file
751 --
752 -- Changed in 5.1.x:
753 -- * Chunkreader renamed to Reader (ditto with Chunkwriter)
754 -- * Zio struct: no more name string, added Lua state for reader
755 -- (however, Yueliang readers do not require a Lua state)
756 ----------------------------------------------------------------------]]
757
758 local luaZ = {}
759
760 ------------------------------------------------------------------------
761 -- * reader() should return a string, or nil if nothing else to parse.
762 -- Additional data can be set only during stream initialization
763 -- * Readers are handled in lauxlib.c, see luaL_load(file|buffer|string)
764 -- * LUAL_BUFFERSIZE=BUFSIZ=512 in make_getF() (located in luaconf.h)
765 -- * Original Reader typedef:
766 -- const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
767 -- * This Lua chunk reader implementation:
768 -- returns string or nil, no arguments to function
769 ------------------------------------------------------------------------
770
771 ------------------------------------------------------------------------
772 -- create a chunk reader from a source string
773 ------------------------------------------------------------------------
774 function luaZ:make_getS(buff)
775 local b = buff
776 return function() -- chunk reader anonymous function here
777 if not b then return nil end
778 local data = b
779 b = nil
780 return data
781 end
782 end
783
784 ------------------------------------------------------------------------
785 -- create a chunk reader from a source file
786 ------------------------------------------------------------------------
787 --[[
788 function luaZ:make_getF(filename)
789 local LUAL_BUFFERSIZE = 512
790 local h = io.open(filename, "r")
791 if not h then return nil end
792 return function() -- chunk reader anonymous function here
793 if not h or io.type(h) == "closed file" then return nil end
794 local buff = h:read(LUAL_BUFFERSIZE)
795 if not buff then h:close(); h = nil end
796 return buff
797 end
798 end
799 --]]
800 ------------------------------------------------------------------------
801 -- creates a zio input stream
802 -- returns the ZIO structure, z
803 ------------------------------------------------------------------------
804 function luaZ:init(reader, data, name)
805 if not reader then return end
806 local z = {}
807 z.reader = reader
808 z.data = data or ""
809 z.name = name
810 -- set up additional data for reading
811 if not data or data == "" then z.n = 0 else z.n = #data end
812 z.p = 0
813 return z
814 end
815
816 ------------------------------------------------------------------------
817 -- fill up input buffer
818 ------------------------------------------------------------------------
819 function luaZ:fill(z)
820 local buff = z.reader()
821 z.data = buff
822 if not buff or buff == "" then return "EOZ" end
823 z.n, z.p = #buff - 1, 1
824 return string.sub(buff, 1, 1)
825 end
826
827 ------------------------------------------------------------------------
828 -- get next character from the input stream
829 -- * local n, p are used to optimize code generation
830 ------------------------------------------------------------------------
831 function luaZ:zgetc(z)
832 local n, p = z.n, z.p + 1
833 if n > 0 then
834 z.n, z.p = n - 1, p
835 return string.sub(z.data, p, p)
836 else
837 return self:fill(z)
838 end
839 end
840
841 return luaZ
842 end
843 fake_module_scripts[script] = module_script
844end
845do -- nil.LuaX
846 local script = Instance.new('ModuleScript', nil)
847 script.Name = "LuaX"
848 local function module_script()
849 --[[--------------------------------------------------------------------
850
851 llex.lua
852 Lua lexical analyzer in Lua
853 This file is part of Yueliang.
854
855 Copyright (c) 2005-2006 Kein-Hong Man <khman@users.sf.net>
856 The COPYRIGHT file describes the conditions
857 under which this software may be distributed.
858
859 See the ChangeLog for more information.
860
861 ----------------------------------------------------------------------]]
862
863 --[[--------------------------------------------------------------------
864 -- Notes:
865 -- * intended to 'imitate' llex.c code; performance is not a concern
866 -- * tokens are strings; code structure largely retained
867 -- * deleted stuff (compared to llex.c) are noted, comments retained
868 -- * nextc() returns the currently read character to simplify coding
869 -- here; next() in llex.c does not return anything
870 -- * compatibility code is marked with "--#" comments
871 --
872 -- Added:
873 -- * luaX:chunkid (function luaO_chunkid from lobject.c)
874 -- * luaX:str2d (function luaO_str2d from lobject.c)
875 -- * luaX.LUA_QS used in luaX:lexerror (from luaconf.h)
876 -- * luaX.LUA_COMPAT_LSTR in luaX:read_long_string (from luaconf.h)
877 -- * luaX.MAX_INT used in luaX:inclinenumber (from llimits.h)
878 --
879 -- To use the lexer:
880 -- (1) luaX:init() to initialize the lexer
881 -- (2) luaX:setinput() to set the input stream to lex
882 -- (3) call luaX:next() or luaX:luaX:lookahead() to get tokens,
883 -- until "TK_EOS": luaX:next()
884 -- * since EOZ is returned as a string, be careful when regexp testing
885 --
886 -- Not implemented:
887 -- * luaX_newstring: not required by this Lua implementation
888 -- * buffer MAX_SIZET size limit (from llimits.h) test not implemented
889 -- in the interest of performance
890 -- * locale-aware number handling is largely redundant as Lua's
891 -- tonumber() function is already capable of this
892 --
893 -- Changed in 5.1.x:
894 -- * TK_NAME token order moved down
895 -- * string representation for TK_NAME, TK_NUMBER, TK_STRING changed
896 -- * token struct renamed to lower case (LS -> ls)
897 -- * LexState struct: removed nestlevel, added decpoint
898 -- * error message functions have been greatly simplified
899 -- * token2string renamed to luaX_tokens, exposed in llex.h
900 -- * lexer now handles all kinds of newlines, including CRLF
901 -- * shbang first line handling removed from luaX:setinput;
902 -- it is now done in lauxlib.c (luaL_loadfile)
903 -- * next(ls) macro renamed to nextc(ls) due to new luaX_next function
904 -- * EXTRABUFF and MAXNOCHECK removed due to lexer changes
905 -- * checkbuffer(ls, len) macro deleted
906 -- * luaX:read_numeral now has 3 support functions: luaX:trydecpoint,
907 -- luaX:buffreplace and (luaO_str2d from lobject.c) luaX:str2d
908 -- * luaX:read_numeral is now more promiscuous in slurping characters;
909 -- hexadecimal numbers was added, locale-aware decimal points too
910 -- * luaX:skip_sep is new; used by luaX:read_long_string
911 -- * luaX:read_long_string handles new-style long blocks, with some
912 -- optional compatibility code
913 -- * luaX:llex: parts changed to support new-style long blocks
914 -- * luaX:llex: readname functionality has been folded in
915 -- * luaX:llex: removed test for control characters
916 --
917 --------------------------------------------------------------------]]
918
919 local luaZ = require(script.Parent.LuaZ)
920
921 local luaX = {}
922
923 -- FIRST_RESERVED is not required as tokens are manipulated as strings
924 -- TOKEN_LEN deleted; maximum length of a reserved word not needed
925
926 ------------------------------------------------------------------------
927 -- "ORDER RESERVED" deleted; enumeration in one place: luaX.RESERVED
928 ------------------------------------------------------------------------
929
930 -- terminal symbols denoted by reserved words: TK_AND to TK_WHILE
931 -- other terminal symbols: TK_NAME to TK_EOS
932 luaX.RESERVED = [[
933 TK_AND and
934 TK_BREAK break
935 TK_DO do
936 TK_ELSE else
937 TK_ELSEIF elseif
938 TK_END end
939 TK_FALSE false
940 TK_FOR for
941 TK_FUNCTION function
942 TK_IF if
943 TK_IN in
944 TK_LOCAL local
945 TK_NIL nil
946 TK_NOT not
947 TK_OR or
948 TK_REPEAT repeat
949 TK_RETURN return
950 TK_THEN then
951 TK_TRUE true
952 TK_UNTIL until
953 TK_WHILE while
954 TK_CONCAT ..
955 TK_DOTS ...
956 TK_EQ ==
957 TK_GE >=
958 TK_LE <=
959 TK_NE ~=
960 TK_NAME <name>
961 TK_NUMBER <number>
962 TK_STRING <string>
963 TK_EOS <eof>]]
964
965 -- NUM_RESERVED is not required; number of reserved words
966
967 --[[--------------------------------------------------------------------
968 -- Instead of passing seminfo, the Token struct (e.g. ls.t) is passed
969 -- so that lexer functions can use its table element, ls.t.seminfo
970 --
971 -- SemInfo (struct no longer needed, a mixed-type value is used)
972 --
973 -- Token (struct of ls.t and ls.lookahead):
974 -- token -- token symbol
975 -- seminfo -- semantics information
976 --
977 -- LexState (struct of ls; ls is initialized by luaX:setinput):
978 -- current -- current character (charint)
979 -- linenumber -- input line counter
980 -- lastline -- line of last token 'consumed'
981 -- t -- current token (table: struct Token)
982 -- lookahead -- look ahead token (table: struct Token)
983 -- fs -- 'FuncState' is private to the parser
984 -- L -- LuaState
985 -- z -- input stream
986 -- buff -- buffer for tokens
987 -- source -- current source name
988 -- decpoint -- locale decimal point
989 -- nestlevel -- level of nested non-terminals
990 ----------------------------------------------------------------------]]
991
992 -- luaX.tokens (was luaX_tokens) is now a hash; see luaX:init
993
994 luaX.MAXSRC = 80
995 luaX.MAX_INT = 2147483645 -- constants from elsewhere (see above)
996 luaX.LUA_QS = "'%s'"
997 luaX.LUA_COMPAT_LSTR = 1
998 --luaX.MAX_SIZET = 4294967293
999
1000 ------------------------------------------------------------------------
1001 -- initialize lexer
1002 -- * original luaX_init has code to create and register token strings
1003 -- * luaX.tokens: TK_* -> token
1004 -- * luaX.enums: token -> TK_* (used in luaX:llex)
1005 ------------------------------------------------------------------------
1006 function luaX:init()
1007 local tokens, enums = {}, {}
1008 for v in string.gmatch(self.RESERVED, "[^\n]+") do
1009 local _, _, tok, str = string.find(v, "(%S+)%s+(%S+)")
1010 tokens[tok] = str
1011 enums[str] = tok
1012 end
1013 self.tokens = tokens
1014 self.enums = enums
1015 end
1016
1017 ------------------------------------------------------------------------
1018 -- returns a suitably-formatted chunk name or id
1019 -- * from lobject.c, used in llex.c and ldebug.c
1020 -- * the result, out, is returned (was first argument)
1021 ------------------------------------------------------------------------
1022 function luaX:chunkid(source, bufflen)
1023 local out
1024 local first = string.sub(source, 1, 1)
1025 if first == "=" then
1026 out = string.sub(source, 2, bufflen) -- remove first char
1027 else -- out = "source", or "...source"
1028 if first == "@" then
1029 source = string.sub(source, 2) -- skip the '@'
1030 bufflen = bufflen - #" '...' "
1031 local l = #source
1032 out = ""
1033 if l > bufflen then
1034 source = string.sub(source, 1 + l - bufflen) -- get last part of file name
1035 out = out.."..."
1036 end
1037 out = out..source
1038 else -- out = [string "string"]
1039 local len = string.find(source, "[\n\r]") -- stop at first newline
1040 len = len and (len - 1) or #source
1041 bufflen = bufflen - #(" [string \"...\"] ")
1042 if len > bufflen then len = bufflen end
1043 out = "[string \""
1044 if len < #source then -- must truncate?
1045 out = out..string.sub(source, 1, len).."..."
1046 else
1047 out = out..source
1048 end
1049 out = out.."\"]"
1050 end
1051 end
1052 return out
1053 end
1054
1055 --[[--------------------------------------------------------------------
1056 -- Support functions for lexer
1057 -- * all lexer errors eventually reaches lexerror:
1058 syntaxerror -> lexerror
1059 ----------------------------------------------------------------------]]
1060
1061 ------------------------------------------------------------------------
1062 -- look up token and return keyword if found (also called by parser)
1063 ------------------------------------------------------------------------
1064 function luaX:token2str(ls, token)
1065 if string.sub(token, 1, 3) ~= "TK_" then
1066 if string.find(token, "%c") then
1067 return string.format("char(%d)", string.byte(token))
1068 end
1069 return token
1070 else
1071 end
1072 return self.tokens[token]
1073 end
1074
1075 ------------------------------------------------------------------------
1076 -- throws a lexer error
1077 -- * txtToken has been made local to luaX:lexerror
1078 -- * can't communicate LUA_ERRSYNTAX, so it is unimplemented
1079 ------------------------------------------------------------------------
1080 function luaX:lexerror(ls, msg, token)
1081 local function txtToken(ls, token)
1082 if token == "TK_NAME" or
1083 token == "TK_STRING" or
1084 token == "TK_NUMBER" then
1085 return ls.buff
1086 else
1087 return self:token2str(ls, token)
1088 end
1089 end
1090 local buff = self:chunkid(ls.source, self.MAXSRC)
1091 local msg = string.format("%s:%d: %s", buff, ls.linenumber, msg)
1092 if token then
1093 msg = string.format("%s near "..self.LUA_QS, msg, txtToken(ls, token))
1094 end
1095 -- luaD_throw(ls->L, LUA_ERRSYNTAX)
1096 error(msg)
1097 end
1098
1099 ------------------------------------------------------------------------
1100 -- throws a syntax error (mainly called by parser)
1101 -- * ls.t.token has to be set by the function calling luaX:llex
1102 -- (see luaX:next and luaX:lookahead elsewhere in this file)
1103 ------------------------------------------------------------------------
1104 function luaX:syntaxerror(ls, msg)
1105 self:lexerror(ls, msg, ls.t.token)
1106 end
1107
1108 ------------------------------------------------------------------------
1109 -- move on to next line
1110 ------------------------------------------------------------------------
1111 function luaX:currIsNewline(ls)
1112 return ls.current == "\n" or ls.current == "\r"
1113 end
1114
1115 function luaX:inclinenumber(ls)
1116 local old = ls.current
1117 -- lua_assert(currIsNewline(ls))
1118 self:nextc(ls) -- skip '\n' or '\r'
1119 if self:currIsNewline(ls) and ls.current ~= old then
1120 self:nextc(ls) -- skip '\n\r' or '\r\n'
1121 end
1122 ls.linenumber = ls.linenumber + 1
1123 if ls.linenumber >= self.MAX_INT then
1124 self:syntaxerror(ls, "chunk has too many lines")
1125 end
1126 end
1127
1128 ------------------------------------------------------------------------
1129 -- initializes an input stream for lexing
1130 -- * if ls (the lexer state) is passed as a table, then it is filled in,
1131 -- otherwise it has to be retrieved as a return value
1132 -- * LUA_MINBUFFER not used; buffer handling not required any more
1133 ------------------------------------------------------------------------
1134 function luaX:setinput(L, ls, z, source)
1135 if not ls then ls = {} end -- create struct
1136 if not ls.lookahead then ls.lookahead = {} end
1137 if not ls.t then ls.t = {} end
1138 ls.decpoint = "."
1139 ls.L = L
1140 ls.lookahead.token = "TK_EOS" -- no look-ahead token
1141 ls.z = z
1142 ls.fs = nil
1143 ls.linenumber = 1
1144 ls.lastline = 1
1145 ls.source = source
1146 self:nextc(ls) -- read first char
1147 end
1148
1149 --[[--------------------------------------------------------------------
1150 -- LEXICAL ANALYZER
1151 ----------------------------------------------------------------------]]
1152
1153 ------------------------------------------------------------------------
1154 -- checks if current character read is found in the set 'set'
1155 ------------------------------------------------------------------------
1156 function luaX:check_next(ls, set)
1157 if not string.find(set, ls.current, 1, 1) then
1158 return false
1159 end
1160 self:save_and_next(ls)
1161 return true
1162 end
1163
1164 ------------------------------------------------------------------------
1165 -- retrieve next token, checking the lookahead buffer if necessary
1166 -- * note that the macro next(ls) in llex.c is now luaX:nextc
1167 -- * utilized used in lparser.c (various places)
1168 ------------------------------------------------------------------------
1169 function luaX:next(ls)
1170 ls.lastline = ls.linenumber
1171 if ls.lookahead.token ~= "TK_EOS" then -- is there a look-ahead token?
1172 -- this must be copy-by-value
1173 ls.t.seminfo = ls.lookahead.seminfo -- use this one
1174 ls.t.token = ls.lookahead.token
1175 ls.lookahead.token = "TK_EOS" -- and discharge it
1176 else
1177 ls.t.token = self:llex(ls, ls.t) -- read next token
1178 end
1179 end
1180
1181 ------------------------------------------------------------------------
1182 -- fill in the lookahead buffer
1183 -- * utilized used in lparser.c:constructor
1184 ------------------------------------------------------------------------
1185 function luaX:lookahead(ls)
1186 -- lua_assert(ls.lookahead.token == "TK_EOS")
1187 ls.lookahead.token = self:llex(ls, ls.lookahead)
1188 end
1189
1190 ------------------------------------------------------------------------
1191 -- gets the next character and returns it
1192 -- * this is the next() macro in llex.c; see notes at the beginning
1193 ------------------------------------------------------------------------
1194 function luaX:nextc(ls)
1195 local c = luaZ:zgetc(ls.z)
1196 ls.current = c
1197 return c
1198 end
1199
1200 ------------------------------------------------------------------------
1201 -- saves the given character into the token buffer
1202 -- * buffer handling code removed, not used in this implementation
1203 -- * test for maximum token buffer length not used, makes things faster
1204 ------------------------------------------------------------------------
1205
1206 function luaX:save(ls, c)
1207 local buff = ls.buff
1208 -- if you want to use this, please uncomment luaX.MAX_SIZET further up
1209 --if #buff > self.MAX_SIZET then
1210 -- self:lexerror(ls, "lexical element too long")
1211 --end
1212 ls.buff = buff..c
1213 end
1214
1215 ------------------------------------------------------------------------
1216 -- save current character into token buffer, grabs next character
1217 -- * like luaX:nextc, returns the character read for convenience
1218 ------------------------------------------------------------------------
1219 function luaX:save_and_next(ls)
1220 self:save(ls, ls.current)
1221 return self:nextc(ls)
1222 end
1223
1224 ------------------------------------------------------------------------
1225 -- LUA_NUMBER
1226 -- * luaX:read_numeral is the main lexer function to read a number
1227 -- * luaX:str2d, luaX:buffreplace, luaX:trydecpoint are support functions
1228 ------------------------------------------------------------------------
1229
1230 ------------------------------------------------------------------------
1231 -- string to number converter (was luaO_str2d from lobject.c)
1232 -- * returns the number, nil if fails (originally returns a boolean)
1233 -- * conversion function originally lua_str2number(s,p), a macro which
1234 -- maps to the strtod() function by default (from luaconf.h)
1235 ------------------------------------------------------------------------
1236 function luaX:str2d(s)
1237 local result = tonumber(s)
1238 if result then return result end
1239 -- conversion failed
1240 if string.lower(string.sub(s, 1, 2)) == "0x" then -- maybe an hexadecimal constant?
1241 result = tonumber(s, 16)
1242 if result then return result end -- most common case
1243 -- Was: invalid trailing characters?
1244 -- In C, this function then skips over trailing spaces.
1245 -- true is returned if nothing else is found except for spaces.
1246 -- If there is still something else, then it returns a false.
1247 -- All this is not necessary using Lua's tonumber.
1248 end
1249 return nil
1250 end
1251
1252 ------------------------------------------------------------------------
1253 -- single-character replacement, for locale-aware decimal points
1254 ------------------------------------------------------------------------
1255 function luaX:buffreplace(ls, from, to)
1256 local result, buff = "", ls.buff
1257 for p = 1, #buff do
1258 local c = string.sub(buff, p, p)
1259 if c == from then c = to end
1260 result = result..c
1261 end
1262 ls.buff = result
1263 end
1264
1265 ------------------------------------------------------------------------
1266 -- Attempt to convert a number by translating '.' decimal points to
1267 -- the decimal point character used by the current locale. This is not
1268 -- needed in Yueliang as Lua's tonumber() is already locale-aware.
1269 -- Instead, the code is here in case the user implements localeconv().
1270 ------------------------------------------------------------------------
1271 function luaX:trydecpoint(ls, Token)
1272 -- format error: try to update decimal point separator
1273 local old = ls.decpoint
1274 -- translate the following to Lua if you implement localeconv():
1275 -- struct lconv *cv = localeconv();
1276 -- ls->decpoint = (cv ? cv->decimal_point[0] : '.');
1277 self:buffreplace(ls, old, ls.decpoint) -- try updated decimal separator
1278 local seminfo = self:str2d(ls.buff)
1279 Token.seminfo = seminfo
1280 if not seminfo then
1281 -- format error with correct decimal point: no more options
1282 self:buffreplace(ls, ls.decpoint, ".") -- undo change (for error message)
1283 self:lexerror(ls, "malformed number", "TK_NUMBER")
1284 end
1285 end
1286
1287 ------------------------------------------------------------------------
1288 -- main number conversion function
1289 -- * "^%w$" needed in the scan in order to detect "EOZ"
1290 ------------------------------------------------------------------------
1291 function luaX:read_numeral(ls, Token)
1292 -- lua_assert(string.find(ls.current, "%d"))
1293 repeat
1294 self:save_and_next(ls)
1295 until string.find(ls.current, "%D") and ls.current ~= "."
1296 if self:check_next(ls, "Ee") then -- 'E'?
1297 self:check_next(ls, "+-") -- optional exponent sign
1298 end
1299 while string.find(ls.current, "^%w$") or ls.current == "_" do
1300 self:save_and_next(ls)
1301 end
1302 self:buffreplace(ls, ".", ls.decpoint) -- follow locale for decimal point
1303 local seminfo = self:str2d(ls.buff)
1304 Token.seminfo = seminfo
1305 if not seminfo then -- format error?
1306 self:trydecpoint(ls, Token) -- try to update decimal point separator
1307 end
1308 end
1309
1310 ------------------------------------------------------------------------
1311 -- count separators ("=") in a long string delimiter
1312 -- * used by luaX:read_long_string
1313 ------------------------------------------------------------------------
1314 function luaX:skip_sep(ls)
1315 local count = 0
1316 local s = ls.current
1317 -- lua_assert(s == "[" or s == "]")
1318 self:save_and_next(ls)
1319 while ls.current == "=" do
1320 self:save_and_next(ls)
1321 count = count + 1
1322 end
1323 return (ls.current == s) and count or (-count) - 1
1324 end
1325
1326 ------------------------------------------------------------------------
1327 -- reads a long string or long comment
1328 ------------------------------------------------------------------------
1329 function luaX:read_long_string(ls, Token, sep)
1330 local cont = 0
1331 self:save_and_next(ls) -- skip 2nd '['
1332 if self:currIsNewline(ls) then -- string starts with a newline?
1333 self:inclinenumber(ls) -- skip it
1334 end
1335 while true do
1336 local c = ls.current
1337 if c == "EOZ" then
1338 self:lexerror(ls, Token and "unfinished long string" or
1339 "unfinished long comment", "TK_EOS")
1340 elseif c == "[" then
1341 --# compatibility code start
1342 if self.LUA_COMPAT_LSTR then
1343 if self:skip_sep(ls) == sep then
1344 self:save_and_next(ls) -- skip 2nd '['
1345 cont = cont + 1
1346 --# compatibility code start
1347 if self.LUA_COMPAT_LSTR == 1 then
1348 if sep == 0 then
1349 self:lexerror(ls, "nesting of [[...]] is deprecated", "[")
1350 end
1351 end
1352 --# compatibility code end
1353 end
1354 end
1355 --# compatibility code end
1356 elseif c == "]" then
1357 if self:skip_sep(ls) == sep then
1358 self:save_and_next(ls) -- skip 2nd ']'
1359 --# compatibility code start
1360 if self.LUA_COMPAT_LSTR and self.LUA_COMPAT_LSTR == 2 then
1361 cont = cont - 1
1362 if sep == 0 and cont >= 0 then break end
1363 end
1364 --# compatibility code end
1365 break
1366 end
1367 elseif self:currIsNewline(ls) then
1368 self:save(ls, "\n")
1369 self:inclinenumber(ls)
1370 if not Token then ls.buff = "" end -- avoid wasting space
1371 else -- default
1372 if Token then
1373 self:save_and_next(ls)
1374 else
1375 self:nextc(ls)
1376 end
1377 end--if c
1378 end--while
1379 if Token then
1380 local p = 3 + sep
1381 Token.seminfo = string.sub(ls.buff, p, -p)
1382 end
1383 end
1384
1385 ------------------------------------------------------------------------
1386 -- reads a string
1387 -- * has been restructured significantly compared to the original C code
1388 ------------------------------------------------------------------------
1389
1390 function luaX:read_string(ls, del, Token)
1391 self:save_and_next(ls)
1392 while ls.current ~= del do
1393 local c = ls.current
1394 if c == "EOZ" then
1395 self:lexerror(ls, "unfinished string", "TK_EOS")
1396 elseif self:currIsNewline(ls) then
1397 self:lexerror(ls, "unfinished string", "TK_STRING")
1398 elseif c == "\\" then
1399 c = self:nextc(ls) -- do not save the '\'
1400 if self:currIsNewline(ls) then -- go through
1401 self:save(ls, "\n")
1402 self:inclinenumber(ls)
1403 elseif c ~= "EOZ" then -- will raise an error next loop
1404 -- escapes handling greatly simplified here:
1405 local i = string.find("abfnrtv", c, 1, 1)
1406 if i then
1407 self:save(ls, string.sub("\a\b\f\n\r\t\v", i, i))
1408 self:nextc(ls)
1409 elseif not string.find(c, "%d") then
1410 self:save_and_next(ls) -- handles \\, \", \', and \?
1411 else -- \xxx
1412 c, i = 0, 0
1413 repeat
1414 c = 10 * c + ls.current
1415 self:nextc(ls)
1416 i = i + 1
1417 until i >= 3 or not string.find(ls.current, "%d")
1418 if c > 255 then -- UCHAR_MAX
1419 self:lexerror(ls, "escape sequence too large", "TK_STRING")
1420 end
1421 self:save(ls, string.char(c))
1422 end
1423 end
1424 else
1425 self:save_and_next(ls)
1426 end--if c
1427 end--while
1428 self:save_and_next(ls) -- skip delimiter
1429 Token.seminfo = string.sub(ls.buff, 2, -2)
1430 end
1431
1432 ------------------------------------------------------------------------
1433 -- main lexer function
1434 ------------------------------------------------------------------------
1435 function luaX:llex(ls, Token)
1436 ls.buff = ""
1437 while true do
1438 local c = ls.current
1439 ----------------------------------------------------------------
1440 if self:currIsNewline(ls) then
1441 self:inclinenumber(ls)
1442 ----------------------------------------------------------------
1443 elseif c == "-" then
1444 c = self:nextc(ls)
1445 if c ~= "-" then return "-" end
1446 -- else is a comment
1447 local sep = -1
1448 if self:nextc(ls) == '[' then
1449 sep = self:skip_sep(ls)
1450 ls.buff = "" -- 'skip_sep' may dirty the buffer
1451 end
1452 if sep >= 0 then
1453 self:read_long_string(ls, nil, sep) -- long comment
1454 ls.buff = ""
1455 else -- else short comment
1456 while not self:currIsNewline(ls) and ls.current ~= "EOZ" do
1457 self:nextc(ls)
1458 end
1459 end
1460 ----------------------------------------------------------------
1461 elseif c == "[" then
1462 local sep = self:skip_sep(ls)
1463 if sep >= 0 then
1464 self:read_long_string(ls, Token, sep)
1465 return "TK_STRING"
1466 elseif sep == -1 then
1467 return "["
1468 else
1469 self:lexerror(ls, "invalid long string delimiter", "TK_STRING")
1470 end
1471 ----------------------------------------------------------------
1472 elseif c == "=" then
1473 c = self:nextc(ls)
1474 if c ~= "=" then return "="
1475 else self:nextc(ls); return "TK_EQ" end
1476 ----------------------------------------------------------------
1477 elseif c == "<" then
1478 c = self:nextc(ls)
1479 if c ~= "=" then return "<"
1480 else self:nextc(ls); return "TK_LE" end
1481 ----------------------------------------------------------------
1482 elseif c == ">" then
1483 c = self:nextc(ls)
1484 if c ~= "=" then return ">"
1485 else self:nextc(ls); return "TK_GE" end
1486 ----------------------------------------------------------------
1487 elseif c == "~" then
1488 c = self:nextc(ls)
1489 if c ~= "=" then return "~"
1490 else self:nextc(ls); return "TK_NE" end
1491 ----------------------------------------------------------------
1492 elseif c == "\"" or c == "'" then
1493 self:read_string(ls, c, Token)
1494 return "TK_STRING"
1495 ----------------------------------------------------------------
1496 elseif c == "." then
1497 c = self:save_and_next(ls)
1498 if self:check_next(ls, ".") then
1499 if self:check_next(ls, ".") then
1500 return "TK_DOTS" -- ...
1501 else return "TK_CONCAT" -- ..
1502 end
1503 elseif not string.find(c, "%d") then
1504 return "."
1505 else
1506 self:read_numeral(ls, Token)
1507 return "TK_NUMBER"
1508 end
1509 ----------------------------------------------------------------
1510 elseif c == "EOZ" then
1511 return "TK_EOS"
1512 ----------------------------------------------------------------
1513 else -- default
1514 if string.find(c, "%s") then
1515 -- lua_assert(self:currIsNewline(ls))
1516 self:nextc(ls)
1517 elseif string.find(c, "%d") then
1518 self:read_numeral(ls, Token)
1519 return "TK_NUMBER"
1520 elseif string.find(c, "[_%a]") then
1521 -- identifier or reserved word
1522 repeat
1523 c = self:save_and_next(ls)
1524 until c == "EOZ" or not string.find(c, "[_%w]")
1525 local ts = ls.buff
1526 local tok = self.enums[ts]
1527 if tok then return tok end -- reserved word?
1528 Token.seminfo = ts
1529 return "TK_NAME"
1530 else
1531 self:nextc(ls)
1532 return c -- single-char tokens (+ - / ...)
1533 end
1534 ----------------------------------------------------------------
1535 end--if c
1536 end--while
1537 end
1538
1539 return luaX
1540 end
1541 fake_module_scripts[script] = module_script
1542end
1543do -- nil.LuaY
1544 local script = Instance.new('ModuleScript', nil)
1545 script.Name = "LuaY"
1546 local function module_script()
1547 --[[--------------------------------------------------------------------
1548
1549 lparser.lua
1550 Lua 5 parser in Lua
1551 This file is part of Yueliang.
1552
1553 Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
1554 The COPYRIGHT file describes the conditions
1555 under which this software may be distributed.
1556
1557 See the ChangeLog for more information.
1558
1559 ----------------------------------------------------------------------]]
1560
1561 --[[--------------------------------------------------------------------
1562 -- Notes:
1563 -- * some unused C code that were not converted are kept as comments
1564 -- * LUA_COMPAT_VARARG option changed into a comment block
1565 -- * for value/size specific code added, look for 'NOTE: '
1566 --
1567 -- Not implemented:
1568 -- * luaX_newstring not needed by this Lua implementation
1569 -- * luaG_checkcode() in assert is not currently implemented
1570 --
1571 -- Added:
1572 -- * some constants added from various header files
1573 -- * luaY.LUA_QS used in error_expected, check_match (from luaconf.h)
1574 -- * luaY:LUA_QL needed for error messages (from luaconf.h)
1575 -- * luaY:growvector (from lmem.h) -- skeleton only, limit checking
1576 -- * luaY.SHRT_MAX (from <limits.h>) for registerlocalvar
1577 -- * luaY:newproto (from lfunc.c)
1578 -- * luaY:int2fb (from lobject.c)
1579 -- * NOTE: HASARG_MASK, for implementing a VARARG_HASARG bit operation
1580 -- * NOTE: value-specific code for VARARG_NEEDSARG to replace a bitop
1581 --
1582 -- Changed in 5.1.x:
1583 -- * various code changes are not detailed...
1584 -- * names of constants may have changed, e.g. added a LUAI_ prefix
1585 -- * struct expkind: added VKNUM, VVARARG; VCALL's info changed?
1586 -- * struct expdesc: added nval
1587 -- * struct FuncState: upvalues data type changed to upvaldesc
1588 -- * macro hasmultret is new
1589 -- * function checklimit moved to parser from lexer
1590 -- * functions anchor_token, errorlimit, checknext are new
1591 -- * checknext is new, equivalent to 5.0.x's check, see check too
1592 -- * luaY:next and luaY:lookahead moved to lexer
1593 -- * break keyword no longer skipped in luaY:breakstat
1594 -- * function new_localvarstr replaced by new_localvarliteral
1595 -- * registerlocalvar limits local variables to SHRT_MAX
1596 -- * create_local deleted, new_localvarliteral used instead
1597 -- * constant LUAI_MAXUPVALUES increased to 60
1598 -- * constants MAXPARAMS, LUA_MAXPARSERLEVEL, MAXSTACK removed
1599 -- * function interface changed: singlevaraux, singlevar
1600 -- * enterlevel and leavelevel uses nCcalls to track call depth
1601 -- * added a name argument to main entry function, luaY:parser
1602 -- * function luaY_index changed to yindex
1603 -- * luaY:int2fb()'s table size encoding format has been changed
1604 -- * luaY:log2() no longer needed for table constructors
1605 -- * function code_params deleted, functionality folded in parlist
1606 -- * vararg flags handling (is_vararg) changes; also see VARARG_*
1607 -- * LUA_COMPATUPSYNTAX section for old-style upvalues removed
1608 -- * repeatstat() calls chunk() instead of block()
1609 -- * function interface changed: cond, test_then_block
1610 -- * while statement implementation considerably simplified; MAXEXPWHILE
1611 -- and EXTRAEXP no longer required, no limits to the complexity of a
1612 -- while condition
1613 -- * repeat, forbody statement implementation has major changes,
1614 -- mostly due to new scoping behaviour of local variables
1615 -- * OPR_MULT renamed to OPR_MUL
1616 ----------------------------------------------------------------------]]
1617
1618 --requires luaP, luaX, luaK
1619 local luaY = {}
1620 local luaX = require(script.Parent.LuaX)
1621 local luaK = require(script.Parent.LuaK)(luaY)
1622 local luaP = require(script.Parent.LuaP)
1623
1624 --[[--------------------------------------------------------------------
1625 -- Expression descriptor
1626 -- * expkind changed to string constants; luaY:assignment was the only
1627 -- function to use a relational operator with this enumeration
1628 -- VVOID -- no value
1629 -- VNIL -- no value
1630 -- VTRUE -- no value
1631 -- VFALSE -- no value
1632 -- VK -- info = index of constant in 'k'
1633 -- VKNUM -- nval = numerical value
1634 -- VLOCAL -- info = local register
1635 -- VUPVAL, -- info = index of upvalue in 'upvalues'
1636 -- VGLOBAL -- info = index of table; aux = index of global name in 'k'
1637 -- VINDEXED -- info = table register; aux = index register (or 'k')
1638 -- VJMP -- info = instruction pc
1639 -- VRELOCABLE -- info = instruction pc
1640 -- VNONRELOC -- info = result register
1641 -- VCALL -- info = instruction pc
1642 -- VVARARG -- info = instruction pc
1643 } ----------------------------------------------------------------------]]
1644
1645 --[[--------------------------------------------------------------------
1646 -- * expdesc in Lua 5.1.x has a union u and another struct s; this Lua
1647 -- implementation ignores all instances of u and s usage
1648 -- struct expdesc:
1649 -- k -- (enum: expkind)
1650 -- info, aux -- (int, int)
1651 -- nval -- (lua_Number)
1652 -- t -- patch list of 'exit when true'
1653 -- f -- patch list of 'exit when false'
1654 ----------------------------------------------------------------------]]
1655
1656 --[[--------------------------------------------------------------------
1657 -- struct upvaldesc:
1658 -- k -- (lu_byte)
1659 -- info -- (lu_byte)
1660 ----------------------------------------------------------------------]]
1661
1662 --[[--------------------------------------------------------------------
1663 -- state needed to generate code for a given function
1664 -- struct FuncState:
1665 -- f -- current function header (table: Proto)
1666 -- h -- table to find (and reuse) elements in 'k' (table: Table)
1667 -- prev -- enclosing function (table: FuncState)
1668 -- ls -- lexical state (table: LexState)
1669 -- L -- copy of the Lua state (table: lua_State)
1670 -- bl -- chain of current blocks (table: BlockCnt)
1671 -- pc -- next position to code (equivalent to 'ncode')
1672 -- lasttarget -- 'pc' of last 'jump target'
1673 -- jpc -- list of pending jumps to 'pc'
1674 -- freereg -- first free register
1675 -- nk -- number of elements in 'k'
1676 -- np -- number of elements in 'p'
1677 -- nlocvars -- number of elements in 'locvars'
1678 -- nactvar -- number of active local variables
1679 -- upvalues[LUAI_MAXUPVALUES] -- upvalues (table: upvaldesc)
1680 -- actvar[LUAI_MAXVARS] -- declared-variable stack
1681 ----------------------------------------------------------------------]]
1682
1683 ------------------------------------------------------------------------
1684 -- constants used by parser
1685 -- * picks up duplicate values from luaX if required
1686 ------------------------------------------------------------------------
1687
1688 luaY.LUA_QS = luaX.LUA_QS or "'%s'" -- (from luaconf.h)
1689
1690 luaY.SHRT_MAX = 32767 -- (from <limits.h>)
1691 luaY.LUAI_MAXVARS = 200 -- (luaconf.h)
1692 luaY.LUAI_MAXUPVALUES = 60 -- (luaconf.h)
1693 luaY.MAX_INT = luaX.MAX_INT or 2147483645 -- (from llimits.h)
1694 -- * INT_MAX-2 for 32-bit systems
1695 luaY.LUAI_MAXCCALLS = 200 -- (from luaconf.h)
1696
1697 luaY.VARARG_HASARG = 1 -- (from lobject.h)
1698 -- NOTE: HASARG_MASK is value-specific
1699 luaY.HASARG_MASK = 2 -- this was added for a bitop in parlist()
1700 luaY.VARARG_ISVARARG = 2
1701 -- NOTE: there is some value-specific code that involves VARARG_NEEDSARG
1702 luaY.VARARG_NEEDSARG = 4
1703
1704 luaY.LUA_MULTRET = -1 -- (lua.h)
1705
1706 --[[--------------------------------------------------------------------
1707 -- other functions
1708 ----------------------------------------------------------------------]]
1709
1710 ------------------------------------------------------------------------
1711 -- LUA_QL describes how error messages quote program elements.
1712 -- CHANGE it if you want a different appearance. (from luaconf.h)
1713 ------------------------------------------------------------------------
1714 function luaY:LUA_QL(x)
1715 return "'"..x.."'"
1716 end
1717
1718 ------------------------------------------------------------------------
1719 -- this is a stripped-down luaM_growvector (from lmem.h) which is a
1720 -- macro based on luaM_growaux (in lmem.c); all the following does is
1721 -- reproduce the size limit checking logic of the original function
1722 -- so that error behaviour is identical; all arguments preserved for
1723 -- convenience, even those which are unused
1724 -- * set the t field to nil, since this originally does a sizeof(t)
1725 -- * size (originally a pointer) is never updated, their final values
1726 -- are set by luaY:close_func(), so overall things should still work
1727 ------------------------------------------------------------------------
1728 function luaY:growvector(L, v, nelems, size, t, limit, e)
1729 if nelems >= limit then
1730 error(e) -- was luaG_runerror
1731 end
1732 end
1733
1734 ------------------------------------------------------------------------
1735 -- initialize a new function prototype structure (from lfunc.c)
1736 -- * used only in open_func()
1737 ------------------------------------------------------------------------
1738 function luaY:newproto(L)
1739 local f = {} -- Proto
1740 -- luaC_link(L, obj2gco(f), LUA_TPROTO); /* GC */
1741 f.k = {}
1742 f.sizek = 0
1743 f.p = {}
1744 f.sizep = 0
1745 f.code = {}
1746 f.sizecode = 0
1747 f.sizelineinfo = 0
1748 f.sizeupvalues = 0
1749 f.nups = 0
1750 f.upvalues = {}
1751 f.numparams = 0
1752 f.is_vararg = 0
1753 f.maxstacksize = 0
1754 f.lineinfo = {}
1755 f.sizelocvars = 0
1756 f.locvars = {}
1757 f.lineDefined = 0
1758 f.lastlinedefined = 0
1759 f.source = nil
1760 return f
1761 end
1762
1763 ------------------------------------------------------------------------
1764 -- converts an integer to a "floating point byte", represented as
1765 -- (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
1766 -- eeeee != 0 and (xxx) otherwise.
1767 ------------------------------------------------------------------------
1768 function luaY:int2fb(x)
1769 local e = 0 -- exponent
1770 while x >= 16 do
1771 x = math.floor((x + 1) / 2)
1772 e = e + 1
1773 end
1774 if x < 8 then
1775 return x
1776 else
1777 return ((e + 1) * 8) + (x - 8)
1778 end
1779 end
1780
1781 --[[--------------------------------------------------------------------
1782 -- parser functions
1783 ----------------------------------------------------------------------]]
1784
1785 ------------------------------------------------------------------------
1786 -- true of the kind of expression produces multiple return values
1787 ------------------------------------------------------------------------
1788 function luaY:hasmultret(k)
1789 return k == "VCALL" or k == "VVARARG"
1790 end
1791
1792 ------------------------------------------------------------------------
1793 -- convenience function to access active local i, returns entry
1794 ------------------------------------------------------------------------
1795 function luaY:getlocvar(fs, i)
1796 return fs.f.locvars[ fs.actvar[i] ]
1797 end
1798
1799 ------------------------------------------------------------------------
1800 -- check a limit, string m provided as an error message
1801 ------------------------------------------------------------------------
1802 function luaY:checklimit(fs, v, l, m)
1803 if v > l then self:errorlimit(fs, l, m) end
1804 end
1805
1806 --[[--------------------------------------------------------------------
1807 -- nodes for block list (list of active blocks)
1808 -- struct BlockCnt:
1809 -- previous -- chain (table: BlockCnt)
1810 -- breaklist -- list of jumps out of this loop
1811 -- nactvar -- # active local variables outside the breakable structure
1812 -- upval -- true if some variable in the block is an upvalue (boolean)
1813 -- isbreakable -- true if 'block' is a loop (boolean)
1814 ----------------------------------------------------------------------]]
1815
1816 ------------------------------------------------------------------------
1817 -- prototypes for recursive non-terminal functions
1818 ------------------------------------------------------------------------
1819 -- prototypes deleted; not required in Lua
1820
1821 ------------------------------------------------------------------------
1822 -- reanchor if last token is has a constant string, see close_func()
1823 -- * used only in close_func()
1824 ------------------------------------------------------------------------
1825 function luaY:anchor_token(ls)
1826 if ls.t.token == "TK_NAME" or ls.t.token == "TK_STRING" then
1827 -- not relevant to Lua implementation of parser
1828 -- local ts = ls.t.seminfo
1829 -- luaX_newstring(ls, getstr(ts), ts->tsv.len); /* C */
1830 end
1831 end
1832
1833 ------------------------------------------------------------------------
1834 -- throws a syntax error if token expected is not there
1835 ------------------------------------------------------------------------
1836 function luaY:error_expected(ls, token)
1837 luaX:syntaxerror(ls,
1838 string.format(self.LUA_QS.." expected", luaX:token2str(ls, token)))
1839 end
1840
1841 ------------------------------------------------------------------------
1842 -- prepares error message for display, for limits exceeded
1843 -- * used only in checklimit()
1844 ------------------------------------------------------------------------
1845 function luaY:errorlimit(fs, limit, what)
1846 local msg = (fs.f.linedefined == 0) and
1847 string.format("main function has more than %d %s", limit, what) or
1848 string.format("function at line %d has more than %d %s",
1849 fs.f.linedefined, limit, what)
1850 luaX:lexerror(fs.ls, msg, 0)
1851 end
1852
1853 ------------------------------------------------------------------------
1854 -- tests for a token, returns outcome
1855 -- * return value changed to boolean
1856 ------------------------------------------------------------------------
1857 function luaY:testnext(ls, c)
1858 if ls.t.token == c then
1859 luaX:next(ls)
1860 return true
1861 else
1862 return false
1863 end
1864 end
1865
1866 ------------------------------------------------------------------------
1867 -- check for existence of a token, throws error if not found
1868 ------------------------------------------------------------------------
1869 function luaY:check(ls, c)
1870 if ls.t.token ~= c then
1871 self:error_expected(ls, c)
1872 end
1873 end
1874
1875 ------------------------------------------------------------------------
1876 -- verify existence of a token, then skip it
1877 ------------------------------------------------------------------------
1878 function luaY:checknext(ls, c)
1879 self:check(ls, c)
1880 luaX:next(ls)
1881 end
1882
1883 ------------------------------------------------------------------------
1884 -- throws error if condition not matched
1885 ------------------------------------------------------------------------
1886 function luaY:check_condition(ls, c, msg)
1887 if not c then luaX:syntaxerror(ls, msg) end
1888 end
1889
1890 ------------------------------------------------------------------------
1891 -- verifies token conditions are met or else throw error
1892 ------------------------------------------------------------------------
1893 function luaY:check_match(ls, what, who, where)
1894 if not self:testnext(ls, what) then
1895 if where == ls.linenumber then
1896 self:error_expected(ls, what)
1897 else
1898 luaX:syntaxerror(ls, string.format(
1899 self.LUA_QS.." expected (to close "..self.LUA_QS.." at line %d)",
1900 luaX:token2str(ls, what), luaX:token2str(ls, who), where))
1901 end
1902 end
1903 end
1904
1905 ------------------------------------------------------------------------
1906 -- expect that token is a name, return the name
1907 ------------------------------------------------------------------------
1908 function luaY:str_checkname(ls)
1909 self:check(ls, "TK_NAME")
1910 local ts = ls.t.seminfo
1911 luaX:next(ls)
1912 return ts
1913 end
1914
1915 ------------------------------------------------------------------------
1916 -- initialize a struct expdesc, expression description data structure
1917 ------------------------------------------------------------------------
1918 function luaY:init_exp(e, k, i)
1919 e.f, e.t = luaK.NO_JUMP, luaK.NO_JUMP
1920 e.k = k
1921 e.info = i
1922 end
1923
1924 ------------------------------------------------------------------------
1925 -- adds given string s in string pool, sets e as VK
1926 ------------------------------------------------------------------------
1927 function luaY:codestring(ls, e, s)
1928 self:init_exp(e, "VK", luaK:stringK(ls.fs, s))
1929 end
1930
1931 ------------------------------------------------------------------------
1932 -- consume a name token, adds it to string pool, sets e as VK
1933 ------------------------------------------------------------------------
1934 function luaY:checkname(ls, e)
1935 self:codestring(ls, e, self:str_checkname(ls))
1936 end
1937
1938 ------------------------------------------------------------------------
1939 -- creates struct entry for a local variable
1940 -- * used only in new_localvar()
1941 ------------------------------------------------------------------------
1942 function luaY:registerlocalvar(ls, varname)
1943 local fs = ls.fs
1944 local f = fs.f
1945 self:growvector(ls.L, f.locvars, fs.nlocvars, f.sizelocvars,
1946 nil, self.SHRT_MAX, "too many local variables")
1947 -- loop to initialize empty f.locvar positions not required
1948 f.locvars[fs.nlocvars] = {} -- LocVar
1949 f.locvars[fs.nlocvars].varname = varname
1950 -- luaC_objbarrier(ls.L, f, varname) /* GC */
1951 local nlocvars = fs.nlocvars
1952 fs.nlocvars = fs.nlocvars + 1
1953 return nlocvars
1954 end
1955
1956 ------------------------------------------------------------------------
1957 -- creates a new local variable given a name and an offset from nactvar
1958 -- * used in fornum(), forlist(), parlist(), body()
1959 ------------------------------------------------------------------------
1960 function luaY:new_localvarliteral(ls, v, n)
1961 self:new_localvar(ls, v, n)
1962 end
1963
1964 ------------------------------------------------------------------------
1965 -- register a local variable, set in active variable list
1966 ------------------------------------------------------------------------
1967 function luaY:new_localvar(ls, name, n)
1968 local fs = ls.fs
1969 self:checklimit(fs, fs.nactvar + n + 1, self.LUAI_MAXVARS, "local variables")
1970 fs.actvar[fs.nactvar + n] = self:registerlocalvar(ls, name)
1971 end
1972
1973 ------------------------------------------------------------------------
1974 -- adds nvars number of new local variables, set debug information
1975 ------------------------------------------------------------------------
1976 function luaY:adjustlocalvars(ls, nvars)
1977 local fs = ls.fs
1978 fs.nactvar = fs.nactvar + nvars
1979 for i = nvars, 1, -1 do
1980 self:getlocvar(fs, fs.nactvar - i).startpc = fs.pc
1981 end
1982 end
1983
1984 ------------------------------------------------------------------------
1985 -- removes a number of locals, set debug information
1986 ------------------------------------------------------------------------
1987 function luaY:removevars(ls, tolevel)
1988 local fs = ls.fs
1989 while fs.nactvar > tolevel do
1990 fs.nactvar = fs.nactvar - 1
1991 self:getlocvar(fs, fs.nactvar).endpc = fs.pc
1992 end
1993 end
1994
1995 ------------------------------------------------------------------------
1996 -- returns an existing upvalue index based on the given name, or
1997 -- creates a new upvalue struct entry and returns the new index
1998 -- * used only in singlevaraux()
1999 ------------------------------------------------------------------------
2000 function luaY:indexupvalue(fs, name, v)
2001 local f = fs.f
2002 for i = 0, f.nups - 1 do
2003 if fs.upvalues[i].k == v.k and fs.upvalues[i].info == v.info then
2004 assert(f.upvalues[i] == name)
2005 return i
2006 end
2007 end
2008 -- new one
2009 self:checklimit(fs, f.nups + 1, self.LUAI_MAXUPVALUES, "upvalues")
2010 self:growvector(fs.L, f.upvalues, f.nups, f.sizeupvalues,
2011 nil, self.MAX_INT, "")
2012 -- loop to initialize empty f.upvalues positions not required
2013 f.upvalues[f.nups] = name
2014 -- luaC_objbarrier(fs->L, f, name); /* GC */
2015 assert(v.k == "VLOCAL" or v.k == "VUPVAL")
2016 -- this is a partial copy; only k & info fields used
2017 fs.upvalues[f.nups] = { k = v.k, info = v.info }
2018 local nups = f.nups
2019 f.nups = f.nups + 1
2020 return nups
2021 end
2022
2023 ------------------------------------------------------------------------
2024 -- search the local variable namespace of the given fs for a match
2025 -- * used only in singlevaraux()
2026 ------------------------------------------------------------------------
2027 function luaY:searchvar(fs, n)
2028 for i = fs.nactvar - 1, 0, -1 do
2029 if n == self:getlocvar(fs, i).varname then
2030 return i
2031 end
2032 end
2033 return -1 -- not found
2034 end
2035
2036 ------------------------------------------------------------------------
2037 -- * mark upvalue flags in function states up to a given level
2038 -- * used only in singlevaraux()
2039 ------------------------------------------------------------------------
2040 function luaY:markupval(fs, level)
2041 local bl = fs.bl
2042 while bl and bl.nactvar > level do bl = bl.previous end
2043 if bl then bl.upval = true end
2044 end
2045
2046 ------------------------------------------------------------------------
2047 -- handle locals, globals and upvalues and related processing
2048 -- * search mechanism is recursive, calls itself to search parents
2049 -- * used only in singlevar()
2050 ------------------------------------------------------------------------
2051 function luaY:singlevaraux(fs, n, var, base)
2052 if fs == nil then -- no more levels?
2053 self:init_exp(var, "VGLOBAL", luaP.NO_REG) -- default is global variable
2054 return "VGLOBAL"
2055 else
2056 local v = self:searchvar(fs, n) -- look up at current level
2057 if v >= 0 then
2058 self:init_exp(var, "VLOCAL", v)
2059 if base == 0 then
2060 self:markupval(fs, v) -- local will be used as an upval
2061 end
2062 return "VLOCAL"
2063 else -- not found at current level; try upper one
2064 if self:singlevaraux(fs.prev, n, var, 0) == "VGLOBAL" then
2065 return "VGLOBAL"
2066 end
2067 var.info = self:indexupvalue(fs, n, var) -- else was LOCAL or UPVAL
2068 var.k = "VUPVAL" -- upvalue in this level
2069 return "VUPVAL"
2070 end--if v
2071 end--if fs
2072 end
2073
2074 ------------------------------------------------------------------------
2075 -- consume a name token, creates a variable (global|local|upvalue)
2076 -- * used in prefixexp(), funcname()
2077 ------------------------------------------------------------------------
2078 function luaY:singlevar(ls, var)
2079 local varname = self:str_checkname(ls)
2080 local fs = ls.fs
2081 if self:singlevaraux(fs, varname, var, 1) == "VGLOBAL" then
2082 var.info = luaK:stringK(fs, varname) -- info points to global name
2083 end
2084 end
2085
2086 ------------------------------------------------------------------------
2087 -- adjust RHS to match LHS in an assignment
2088 -- * used in assignment(), forlist(), localstat()
2089 ------------------------------------------------------------------------
2090 function luaY:adjust_assign(ls, nvars, nexps, e)
2091 local fs = ls.fs
2092 local extra = nvars - nexps
2093 if self:hasmultret(e.k) then
2094 extra = extra + 1 -- includes call itself
2095 if extra <= 0 then extra = 0 end
2096 luaK:setreturns(fs, e, extra) -- last exp. provides the difference
2097 if extra > 1 then luaK:reserveregs(fs, extra - 1) end
2098 else
2099 if e.k ~= "VVOID" then luaK:exp2nextreg(fs, e) end -- close last expression
2100 if extra > 0 then
2101 local reg = fs.freereg
2102 luaK:reserveregs(fs, extra)
2103 luaK:_nil(fs, reg, extra)
2104 end
2105 end
2106 end
2107
2108 ------------------------------------------------------------------------
2109 -- tracks and limits parsing depth, assert check at end of parsing
2110 ------------------------------------------------------------------------
2111 function luaY:enterlevel(ls)
2112 ls.L.nCcalls = ls.L.nCcalls + 1
2113 if ls.L.nCcalls > self.LUAI_MAXCCALLS then
2114 luaX:lexerror(ls, "chunk has too many syntax levels", 0)
2115 end
2116 end
2117
2118 ------------------------------------------------------------------------
2119 -- tracks parsing depth, a pair with luaY:enterlevel()
2120 ------------------------------------------------------------------------
2121 function luaY:leavelevel(ls)
2122 ls.L.nCcalls = ls.L.nCcalls - 1
2123 end
2124
2125 ------------------------------------------------------------------------
2126 -- enters a code unit, initializes elements
2127 ------------------------------------------------------------------------
2128 function luaY:enterblock(fs, bl, isbreakable)
2129 bl.breaklist = luaK.NO_JUMP
2130 bl.isbreakable = isbreakable
2131 bl.nactvar = fs.nactvar
2132 bl.upval = false
2133 bl.previous = fs.bl
2134 fs.bl = bl
2135 assert(fs.freereg == fs.nactvar)
2136 end
2137
2138 ------------------------------------------------------------------------
2139 -- leaves a code unit, close any upvalues
2140 ------------------------------------------------------------------------
2141 function luaY:leaveblock(fs)
2142 local bl = fs.bl
2143 fs.bl = bl.previous
2144 self:removevars(fs.ls, bl.nactvar)
2145 if bl.upval then
2146 luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
2147 end
2148 -- a block either controls scope or breaks (never both)
2149 assert(not bl.isbreakable or not bl.upval)
2150 assert(bl.nactvar == fs.nactvar)
2151 fs.freereg = fs.nactvar -- free registers
2152 luaK:patchtohere(fs, bl.breaklist)
2153 end
2154
2155 ------------------------------------------------------------------------
2156 -- implement the instantiation of a function prototype, append list of
2157 -- upvalues after the instantiation instruction
2158 -- * used only in body()
2159 ------------------------------------------------------------------------
2160 function luaY:pushclosure(ls, func, v)
2161 local fs = ls.fs
2162 local f = fs.f
2163 self:growvector(ls.L, f.p, fs.np, f.sizep, nil,
2164 luaP.MAXARG_Bx, "constant table overflow")
2165 -- loop to initialize empty f.p positions not required
2166 f.p[fs.np] = func.f
2167 fs.np = fs.np + 1
2168 -- luaC_objbarrier(ls->L, f, func->f); /* C */
2169 self:init_exp(v, "VRELOCABLE", luaK:codeABx(fs, "OP_CLOSURE", 0, fs.np - 1))
2170 for i = 0, func.f.nups - 1 do
2171 local o = (func.upvalues[i].k == "VLOCAL") and "OP_MOVE" or "OP_GETUPVAL"
2172 luaK:codeABC(fs, o, 0, func.upvalues[i].info, 0)
2173 end
2174 end
2175
2176 ------------------------------------------------------------------------
2177 -- opening of a function
2178 ------------------------------------------------------------------------
2179 function luaY:open_func(ls, fs)
2180 local L = ls.L
2181 local f = self:newproto(ls.L)
2182 fs.f = f
2183 fs.prev = ls.fs -- linked list of funcstates
2184 fs.ls = ls
2185 fs.L = L
2186 ls.fs = fs
2187 fs.pc = 0
2188 fs.lasttarget = -1
2189 fs.jpc = luaK.NO_JUMP
2190 fs.freereg = 0
2191 fs.nk = 0
2192 fs.np = 0
2193 fs.nlocvars = 0
2194 fs.nactvar = 0
2195 fs.bl = nil
2196 f.source = ls.source
2197 f.maxstacksize = 2 -- registers 0/1 are always valid
2198 fs.h = {} -- constant table; was luaH_new call
2199 -- anchor table of constants and prototype (to avoid being collected)
2200 -- sethvalue2s(L, L->top, fs->h); incr_top(L); /* C */
2201 -- setptvalue2s(L, L->top, f); incr_top(L);
2202 end
2203
2204 ------------------------------------------------------------------------
2205 -- closing of a function
2206 ------------------------------------------------------------------------
2207 function luaY:close_func(ls)
2208 local L = ls.L
2209 local fs = ls.fs
2210 local f = fs.f
2211 self:removevars(ls, 0)
2212 luaK:ret(fs, 0, 0) -- final return
2213 -- luaM_reallocvector deleted for f->code, f->lineinfo, f->k, f->p,
2214 -- f->locvars, f->upvalues; not required for Lua table arrays
2215 f.sizecode = fs.pc
2216 f.sizelineinfo = fs.pc
2217 f.sizek = fs.nk
2218 f.sizep = fs.np
2219 f.sizelocvars = fs.nlocvars
2220 f.sizeupvalues = f.nups
2221 --assert(luaG_checkcode(f)) -- currently not implemented
2222 assert(fs.bl == nil)
2223 ls.fs = fs.prev
2224 -- the following is not required for this implementation; kept here
2225 -- for completeness
2226 -- L->top -= 2; /* remove table and prototype from the stack */
2227 -- last token read was anchored in defunct function; must reanchor it
2228 if fs then self:anchor_token(ls) end
2229 end
2230
2231 ------------------------------------------------------------------------
2232 -- parser initialization function
2233 -- * note additional sub-tables needed for LexState, FuncState
2234 ------------------------------------------------------------------------
2235 function luaY:parser(L, z, buff, name)
2236 local lexstate = {} -- LexState
2237 lexstate.t = {}
2238 lexstate.lookahead = {}
2239 local funcstate = {} -- FuncState
2240 funcstate.upvalues = {}
2241 funcstate.actvar = {}
2242 -- the following nCcalls initialization added for convenience
2243 L.nCcalls = 0
2244 lexstate.buff = buff
2245 luaX:setinput(L, lexstate, z, name)
2246 self:open_func(lexstate, funcstate)
2247 funcstate.f.is_vararg = self.VARARG_ISVARARG -- main func. is always vararg
2248 luaX:next(lexstate) -- read first token
2249 self:chunk(lexstate)
2250 self:check(lexstate, "TK_EOS")
2251 self:close_func(lexstate)
2252 assert(funcstate.prev == nil)
2253 assert(funcstate.f.nups == 0)
2254 assert(lexstate.fs == nil)
2255 return funcstate.f
2256 end
2257
2258 --[[--------------------------------------------------------------------
2259 -- GRAMMAR RULES
2260 ----------------------------------------------------------------------]]
2261
2262 ------------------------------------------------------------------------
2263 -- parse a function name suffix, for function call specifications
2264 -- * used in primaryexp(), funcname()
2265 ------------------------------------------------------------------------
2266 function luaY:field(ls, v)
2267 -- field -> ['.' | ':'] NAME
2268 local fs = ls.fs
2269 local key = {} -- expdesc
2270 luaK:exp2anyreg(fs, v)
2271 luaX:next(ls) -- skip the dot or colon
2272 self:checkname(ls, key)
2273 luaK:indexed(fs, v, key)
2274 end
2275
2276 ------------------------------------------------------------------------
2277 -- parse a table indexing suffix, for constructors, expressions
2278 -- * used in recfield(), primaryexp()
2279 ------------------------------------------------------------------------
2280 function luaY:yindex(ls, v)
2281 -- index -> '[' expr ']'
2282 luaX:next(ls) -- skip the '['
2283 self:expr(ls, v)
2284 luaK:exp2val(ls.fs, v)
2285 self:checknext(ls, "]")
2286 end
2287
2288 --[[--------------------------------------------------------------------
2289 -- Rules for Constructors
2290 ----------------------------------------------------------------------]]
2291
2292 --[[--------------------------------------------------------------------
2293 -- struct ConsControl:
2294 -- v -- last list item read (table: struct expdesc)
2295 -- t -- table descriptor (table: struct expdesc)
2296 -- nh -- total number of 'record' elements
2297 -- na -- total number of array elements
2298 -- tostore -- number of array elements pending to be stored
2299 ----------------------------------------------------------------------]]
2300
2301 ------------------------------------------------------------------------
2302 -- parse a table record (hash) field
2303 -- * used in constructor()
2304 ------------------------------------------------------------------------
2305 function luaY:recfield(ls, cc)
2306 -- recfield -> (NAME | '['exp1']') = exp1
2307 local fs = ls.fs
2308 local reg = ls.fs.freereg
2309 local key, val = {}, {} -- expdesc
2310 if ls.t.token == "TK_NAME" then
2311 self:checklimit(fs, cc.nh, self.MAX_INT, "items in a constructor")
2312 self:checkname(ls, key)
2313 else -- ls->t.token == '['
2314 self:yindex(ls, key)
2315 end
2316 cc.nh = cc.nh + 1
2317 self:checknext(ls, "=")
2318 local rkkey = luaK:exp2RK(fs, key)
2319 self:expr(ls, val)
2320 luaK:codeABC(fs, "OP_SETTABLE", cc.t.info, rkkey, luaK:exp2RK(fs, val))
2321 fs.freereg = reg -- free registers
2322 end
2323
2324 ------------------------------------------------------------------------
2325 -- emit a set list instruction if enough elements (LFIELDS_PER_FLUSH)
2326 -- * used in constructor()
2327 ------------------------------------------------------------------------
2328 function luaY:closelistfield(fs, cc)
2329 if cc.v.k == "VVOID" then return end -- there is no list item
2330 luaK:exp2nextreg(fs, cc.v)
2331 cc.v.k = "VVOID"
2332 if cc.tostore == luaP.LFIELDS_PER_FLUSH then
2333 luaK:setlist(fs, cc.t.info, cc.na, cc.tostore) -- flush
2334 cc.tostore = 0 -- no more items pending
2335 end
2336 end
2337
2338 ------------------------------------------------------------------------
2339 -- emit a set list instruction at the end of parsing list constructor
2340 -- * used in constructor()
2341 ------------------------------------------------------------------------
2342 function luaY:lastlistfield(fs, cc)
2343 if cc.tostore == 0 then return end
2344 if self:hasmultret(cc.v.k) then
2345 luaK:setmultret(fs, cc.v)
2346 luaK:setlist(fs, cc.t.info, cc.na, self.LUA_MULTRET)
2347 cc.na = cc.na - 1 -- do not count last expression (unknown number of elements)
2348 else
2349 if cc.v.k ~= "VVOID" then
2350 luaK:exp2nextreg(fs, cc.v)
2351 end
2352 luaK:setlist(fs, cc.t.info, cc.na, cc.tostore)
2353 end
2354 end
2355
2356 ------------------------------------------------------------------------
2357 -- parse a table list (array) field
2358 -- * used in constructor()
2359 ------------------------------------------------------------------------
2360 function luaY:listfield(ls, cc)
2361 self:expr(ls, cc.v)
2362 self:checklimit(ls.fs, cc.na, self.MAX_INT, "items in a constructor")
2363 cc.na = cc.na + 1
2364 cc.tostore = cc.tostore + 1
2365 end
2366
2367 ------------------------------------------------------------------------
2368 -- parse a table constructor
2369 -- * used in funcargs(), simpleexp()
2370 ------------------------------------------------------------------------
2371 function luaY:constructor(ls, t)
2372 -- constructor -> '{' [ field { fieldsep field } [ fieldsep ] ] '}'
2373 -- field -> recfield | listfield
2374 -- fieldsep -> ',' | ';'
2375 local fs = ls.fs
2376 local line = ls.linenumber
2377 local pc = luaK:codeABC(fs, "OP_NEWTABLE", 0, 0, 0)
2378 local cc = {} -- ConsControl
2379 cc.v = {}
2380 cc.na, cc.nh, cc.tostore = 0, 0, 0
2381 cc.t = t
2382 self:init_exp(t, "VRELOCABLE", pc)
2383 self:init_exp(cc.v, "VVOID", 0) -- no value (yet)
2384 luaK:exp2nextreg(ls.fs, t) -- fix it at stack top (for gc)
2385 self:checknext(ls, "{")
2386 repeat
2387 assert(cc.v.k == "VVOID" or cc.tostore > 0)
2388 if ls.t.token == "}" then break end
2389 self:closelistfield(fs, cc)
2390 local c = ls.t.token
2391
2392 if c == "TK_NAME" then -- may be listfields or recfields
2393 luaX:lookahead(ls)
2394 if ls.lookahead.token ~= "=" then -- expression?
2395 self:listfield(ls, cc)
2396 else
2397 self:recfield(ls, cc)
2398 end
2399 elseif c == "[" then -- constructor_item -> recfield
2400 self:recfield(ls, cc)
2401 else -- constructor_part -> listfield
2402 self:listfield(ls, cc)
2403 end
2404 until not self:testnext(ls, ",") and not self:testnext(ls, ";")
2405 self:check_match(ls, "}", "{", line)
2406 self:lastlistfield(fs, cc)
2407 luaP:SETARG_B(fs.f.code[pc], self:int2fb(cc.na)) -- set initial array size
2408 luaP:SETARG_C(fs.f.code[pc], self:int2fb(cc.nh)) -- set initial table size
2409 end
2410
2411 -- }======================================================================
2412
2413 ------------------------------------------------------------------------
2414 -- parse the arguments (parameters) of a function declaration
2415 -- * used in body()
2416 ------------------------------------------------------------------------
2417 function luaY:parlist(ls)
2418 -- parlist -> [ param { ',' param } ]
2419 local fs = ls.fs
2420 local f = fs.f
2421 local nparams = 0
2422 f.is_vararg = 0
2423 if ls.t.token ~= ")" then -- is 'parlist' not empty?
2424 repeat
2425 local c = ls.t.token
2426 if c == "TK_NAME" then -- param -> NAME
2427 self:new_localvar(ls, self:str_checkname(ls), nparams)
2428 nparams = nparams + 1
2429 elseif c == "TK_DOTS" then -- param -> `...'
2430 luaX:next(ls)
2431 -- [[
2432 -- #if defined(LUA_COMPAT_VARARG)
2433 -- use `arg' as default name
2434 self:new_localvarliteral(ls, "arg", nparams)
2435 nparams = nparams + 1
2436 f.is_vararg = self.VARARG_HASARG + self.VARARG_NEEDSARG
2437 -- #endif
2438 --]]
2439 f.is_vararg = f.is_vararg + self.VARARG_ISVARARG
2440 else
2441 luaX:syntaxerror(ls, "<name> or "..self:LUA_QL("...").." expected")
2442 end
2443 until f.is_vararg ~= 0 or not self:testnext(ls, ",")
2444 end--if
2445 self:adjustlocalvars(ls, nparams)
2446 -- NOTE: the following works only when HASARG_MASK is 2!
2447 f.numparams = fs.nactvar - (f.is_vararg % self.HASARG_MASK)
2448 luaK:reserveregs(fs, fs.nactvar) -- reserve register for parameters
2449 end
2450
2451 ------------------------------------------------------------------------
2452 -- parse function declaration body
2453 -- * used in simpleexp(), localfunc(), funcstat()
2454 ------------------------------------------------------------------------
2455 function luaY:body(ls, e, needself, line)
2456 -- body -> '(' parlist ')' chunk END
2457 local new_fs = {} -- FuncState
2458 new_fs.upvalues = {}
2459 new_fs.actvar = {}
2460 self:open_func(ls, new_fs)
2461 new_fs.f.lineDefined = line
2462 self:checknext(ls, "(")
2463 if needself then
2464 self:new_localvarliteral(ls, "self", 0)
2465 self:adjustlocalvars(ls, 1)
2466 end
2467 self:parlist(ls)
2468 self:checknext(ls, ")")
2469 self:chunk(ls)
2470 new_fs.f.lastlinedefined = ls.linenumber
2471 self:check_match(ls, "TK_END", "TK_FUNCTION", line)
2472 self:close_func(ls)
2473 self:pushclosure(ls, new_fs, e)
2474 end
2475
2476 ------------------------------------------------------------------------
2477 -- parse a list of comma-separated expressions
2478 -- * used is multiple locations
2479 ------------------------------------------------------------------------
2480 function luaY:explist1(ls, v)
2481 -- explist1 -> expr { ',' expr }
2482 local n = 1 -- at least one expression
2483 self:expr(ls, v)
2484 while self:testnext(ls, ",") do
2485 luaK:exp2nextreg(ls.fs, v)
2486 self:expr(ls, v)
2487 n = n + 1
2488 end
2489 return n
2490 end
2491
2492 ------------------------------------------------------------------------
2493 -- parse the parameters of a function call
2494 -- * contrast with parlist(), used in function declarations
2495 -- * used in primaryexp()
2496 ------------------------------------------------------------------------
2497 function luaY:funcargs(ls, f)
2498 local fs = ls.fs
2499 local args = {} -- expdesc
2500 local nparams
2501 local line = ls.linenumber
2502 local c = ls.t.token
2503 if c == "(" then -- funcargs -> '(' [ explist1 ] ')'
2504 if line ~= ls.lastline then
2505 luaX:syntaxerror(ls, "ambiguous syntax (function call x new statement)")
2506 end
2507 luaX:next(ls)
2508 if ls.t.token == ")" then -- arg list is empty?
2509 args.k = "VVOID"
2510 else
2511 self:explist1(ls, args)
2512 luaK:setmultret(fs, args)
2513 end
2514 self:check_match(ls, ")", "(", line)
2515 elseif c == "{" then -- funcargs -> constructor
2516 self:constructor(ls, args)
2517 elseif c == "TK_STRING" then -- funcargs -> STRING
2518 self:codestring(ls, args, ls.t.seminfo)
2519 luaX:next(ls) -- must use 'seminfo' before 'next'
2520 else
2521 luaX:syntaxerror(ls, "function arguments expected")
2522 return
2523 end
2524 assert(f.k == "VNONRELOC")
2525 local base = f.info -- base register for call
2526 if self:hasmultret(args.k) then
2527 nparams = self.LUA_MULTRET -- open call
2528 else
2529 if args.k ~= "VVOID" then
2530 luaK:exp2nextreg(fs, args) -- close last argument
2531 end
2532 nparams = fs.freereg - (base + 1)
2533 end
2534 self:init_exp(f, "VCALL", luaK:codeABC(fs, "OP_CALL", base, nparams + 1, 2))
2535 luaK:fixline(fs, line)
2536 fs.freereg = base + 1 -- call remove function and arguments and leaves
2537 -- (unless changed) one result
2538 end
2539
2540 --[[--------------------------------------------------------------------
2541 -- Expression parsing
2542 ----------------------------------------------------------------------]]
2543
2544 ------------------------------------------------------------------------
2545 -- parses an expression in parentheses or a single variable
2546 -- * used in primaryexp()
2547 ------------------------------------------------------------------------
2548 function luaY:prefixexp(ls, v)
2549 -- prefixexp -> NAME | '(' expr ')'
2550 local c = ls.t.token
2551 if c == "(" then
2552 local line = ls.linenumber
2553 luaX:next(ls)
2554 self:expr(ls, v)
2555 self:check_match(ls, ")", "(", line)
2556 luaK:dischargevars(ls.fs, v)
2557 elseif c == "TK_NAME" then
2558 self:singlevar(ls, v)
2559 else
2560 luaX:syntaxerror(ls, "unexpected symbol")
2561 end--if c
2562 return
2563 end
2564
2565 ------------------------------------------------------------------------
2566 -- parses a prefixexp (an expression in parentheses or a single variable)
2567 -- or a function call specification
2568 -- * used in simpleexp(), assignment(), exprstat()
2569 ------------------------------------------------------------------------
2570 function luaY:primaryexp(ls, v)
2571 -- primaryexp ->
2572 -- prefixexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs }
2573 local fs = ls.fs
2574 self:prefixexp(ls, v)
2575 while true do
2576 local c = ls.t.token
2577 if c == "." then -- field
2578 self:field(ls, v)
2579 elseif c == "[" then -- '[' exp1 ']'
2580 local key = {} -- expdesc
2581 luaK:exp2anyreg(fs, v)
2582 self:yindex(ls, key)
2583 luaK:indexed(fs, v, key)
2584 elseif c == ":" then -- ':' NAME funcargs
2585 local key = {} -- expdesc
2586 luaX:next(ls)
2587 self:checkname(ls, key)
2588 luaK:_self(fs, v, key)
2589 self:funcargs(ls, v)
2590 elseif c == "(" or c == "TK_STRING" or c == "{" then -- funcargs
2591 luaK:exp2nextreg(fs, v)
2592 self:funcargs(ls, v)
2593 else
2594 return
2595 end--if c
2596 end--while
2597 end
2598
2599 ------------------------------------------------------------------------
2600 -- parses general expression types, constants handled here
2601 -- * used in subexpr()
2602 ------------------------------------------------------------------------
2603 function luaY:simpleexp(ls, v)
2604 -- simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
2605 -- constructor | FUNCTION body | primaryexp
2606 local c = ls.t.token
2607 if c == "TK_NUMBER" then
2608 self:init_exp(v, "VKNUM", 0)
2609 v.nval = ls.t.seminfo
2610 elseif c == "TK_STRING" then
2611 self:codestring(ls, v, ls.t.seminfo)
2612 elseif c == "TK_NIL" then
2613 self:init_exp(v, "VNIL", 0)
2614 elseif c == "TK_TRUE" then
2615 self:init_exp(v, "VTRUE", 0)
2616 elseif c == "TK_FALSE" then
2617 self:init_exp(v, "VFALSE", 0)
2618 elseif c == "TK_DOTS" then -- vararg
2619 local fs = ls.fs
2620 self:check_condition(ls, fs.f.is_vararg ~= 0,
2621 "cannot use "..self:LUA_QL("...").." outside a vararg function");
2622 -- NOTE: the following substitutes for a bitop, but is value-specific
2623 local is_vararg = fs.f.is_vararg
2624 if is_vararg >= self.VARARG_NEEDSARG then
2625 fs.f.is_vararg = is_vararg - self.VARARG_NEEDSARG -- don't need 'arg'
2626 end
2627 self:init_exp(v, "VVARARG", luaK:codeABC(fs, "OP_VARARG", 0, 1, 0))
2628 elseif c == "{" then -- constructor
2629 self:constructor(ls, v)
2630 return
2631 elseif c == "TK_FUNCTION" then
2632 luaX:next(ls)
2633 self:body(ls, v, false, ls.linenumber)
2634 return
2635 else
2636 self:primaryexp(ls, v)
2637 return
2638 end--if c
2639 luaX:next(ls)
2640 end
2641
2642 ------------------------------------------------------------------------
2643 -- Translates unary operators tokens if found, otherwise returns
2644 -- OPR_NOUNOPR. getunopr() and getbinopr() are used in subexpr().
2645 -- * used in subexpr()
2646 ------------------------------------------------------------------------
2647 function luaY:getunopr(op)
2648 if op == "TK_NOT" then
2649 return "OPR_NOT"
2650 elseif op == "-" then
2651 return "OPR_MINUS"
2652 elseif op == "#" then
2653 return "OPR_LEN"
2654 else
2655 return "OPR_NOUNOPR"
2656 end
2657 end
2658
2659 ------------------------------------------------------------------------
2660 -- Translates binary operator tokens if found, otherwise returns
2661 -- OPR_NOBINOPR. Code generation uses OPR_* style tokens.
2662 -- * used in subexpr()
2663 ------------------------------------------------------------------------
2664 luaY.getbinopr_table = {
2665 ["+"] = "OPR_ADD",
2666 ["-"] = "OPR_SUB",
2667 ["*"] = "OPR_MUL",
2668 ["/"] = "OPR_DIV",
2669 ["%"] = "OPR_MOD",
2670 ["^"] = "OPR_POW",
2671 ["TK_CONCAT"] = "OPR_CONCAT",
2672 ["TK_NE"] = "OPR_NE",
2673 ["TK_EQ"] = "OPR_EQ",
2674 ["<"] = "OPR_LT",
2675 ["TK_LE"] = "OPR_LE",
2676 [">"] = "OPR_GT",
2677 ["TK_GE"] = "OPR_GE",
2678 ["TK_AND"] = "OPR_AND",
2679 ["TK_OR"] = "OPR_OR",
2680 }
2681 function luaY:getbinopr(op)
2682 local opr = self.getbinopr_table[op]
2683 if opr then return opr else return "OPR_NOBINOPR" end
2684 end
2685
2686 ------------------------------------------------------------------------
2687 -- the following priority table consists of pairs of left/right values
2688 -- for binary operators (was a static const struct); grep for ORDER OPR
2689 -- * the following struct is replaced:
2690 -- static const struct {
2691 -- lu_byte left; /* left priority for each binary operator */
2692 -- lu_byte right; /* right priority */
2693 -- } priority[] = { /* ORDER OPR */
2694 ------------------------------------------------------------------------
2695 luaY.priority = {
2696 {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, -- `+' `-' `/' `%'
2697 {10, 9}, {5, 4}, -- power and concat (right associative)
2698 {3, 3}, {3, 3}, -- equality
2699 {3, 3}, {3, 3}, {3, 3}, {3, 3}, -- order
2700 {2, 2}, {1, 1} -- logical (and/or)
2701 }
2702
2703 luaY.UNARY_PRIORITY = 8 -- priority for unary operators
2704
2705 ------------------------------------------------------------------------
2706 -- Parse subexpressions. Includes handling of unary operators and binary
2707 -- operators. A subexpr is given the rhs priority level of the operator
2708 -- immediately left of it, if any (limit is -1 if none,) and if a binop
2709 -- is found, limit is compared with the lhs priority level of the binop
2710 -- in order to determine which executes first.
2711 ------------------------------------------------------------------------
2712
2713 ------------------------------------------------------------------------
2714 -- subexpr -> (simpleexp | unop subexpr) { binop subexpr }
2715 -- where 'binop' is any binary operator with a priority higher than 'limit'
2716 -- * for priority lookups with self.priority[], 1=left and 2=right
2717 -- * recursively called
2718 -- * used in expr()
2719 ------------------------------------------------------------------------
2720 function luaY:subexpr(ls, v, limit)
2721 self:enterlevel(ls)
2722 local uop = self:getunopr(ls.t.token)
2723 if uop ~= "OPR_NOUNOPR" then
2724 luaX:next(ls)
2725 self:subexpr(ls, v, self.UNARY_PRIORITY)
2726 luaK:prefix(ls.fs, uop, v)
2727 else
2728 self:simpleexp(ls, v)
2729 end
2730 -- expand while operators have priorities higher than 'limit'
2731 local op = self:getbinopr(ls.t.token)
2732 while op ~= "OPR_NOBINOPR" and self.priority[luaK.BinOpr[op] + 1][1] > limit do
2733 local v2 = {} -- expdesc
2734 luaX:next(ls)
2735 luaK:infix(ls.fs, op, v)
2736 -- read sub-expression with higher priority
2737 local nextop = self:subexpr(ls, v2, self.priority[luaK.BinOpr[op] + 1][2])
2738 luaK:posfix(ls.fs, op, v, v2)
2739 op = nextop
2740 end
2741 self:leavelevel(ls)
2742 return op -- return first untreated operator
2743 end
2744
2745 ------------------------------------------------------------------------
2746 -- Expression parsing starts here. Function subexpr is entered with the
2747 -- left operator (which is non-existent) priority of -1, which is lower
2748 -- than all actual operators. Expr information is returned in parm v.
2749 -- * used in multiple locations
2750 ------------------------------------------------------------------------
2751 function luaY:expr(ls, v)
2752 self:subexpr(ls, v, 0)
2753 end
2754
2755 -- }====================================================================
2756
2757 --[[--------------------------------------------------------------------
2758 -- Rules for Statements
2759 ----------------------------------------------------------------------]]
2760
2761 ------------------------------------------------------------------------
2762 -- checks next token, used as a look-ahead
2763 -- * returns boolean instead of 0|1
2764 -- * used in retstat(), chunk()
2765 ------------------------------------------------------------------------
2766 function luaY:block_follow(token)
2767 if token == "TK_ELSE" or token == "TK_ELSEIF" or token == "TK_END"
2768 or token == "TK_UNTIL" or token == "TK_EOS" then
2769 return true
2770 else
2771 return false
2772 end
2773 end
2774
2775 ------------------------------------------------------------------------
2776 -- parse a code block or unit
2777 -- * used in multiple functions
2778 ------------------------------------------------------------------------
2779 function luaY:block(ls)
2780 -- block -> chunk
2781 local fs = ls.fs
2782 local bl = {} -- BlockCnt
2783 self:enterblock(fs, bl, false)
2784 self:chunk(ls)
2785 assert(bl.breaklist == luaK.NO_JUMP)
2786 self:leaveblock(fs)
2787 end
2788
2789 ------------------------------------------------------------------------
2790 -- structure to chain all variables in the left-hand side of an
2791 -- assignment
2792 -- struct LHS_assign:
2793 -- prev -- (table: struct LHS_assign)
2794 -- v -- variable (global, local, upvalue, or indexed) (table: expdesc)
2795 ------------------------------------------------------------------------
2796
2797 ------------------------------------------------------------------------
2798 -- check whether, in an assignment to a local variable, the local variable
2799 -- is needed in a previous assignment (to a table). If so, save original
2800 -- local value in a safe place and use this safe copy in the previous
2801 -- assignment.
2802 -- * used in assignment()
2803 ------------------------------------------------------------------------
2804 function luaY:check_conflict(ls, lh, v)
2805 local fs = ls.fs
2806 local extra = fs.freereg -- eventual position to save local variable
2807 local conflict = false
2808 while lh do
2809 if lh.v.k == "VINDEXED" then
2810 if lh.v.info == v.info then -- conflict?
2811 conflict = true
2812 lh.v.info = extra -- previous assignment will use safe copy
2813 end
2814 if lh.v.aux == v.info then -- conflict?
2815 conflict = true
2816 lh.v.aux = extra -- previous assignment will use safe copy
2817 end
2818 end
2819 lh = lh.prev
2820 end
2821 if conflict then
2822 luaK:codeABC(fs, "OP_MOVE", fs.freereg, v.info, 0) -- make copy
2823 luaK:reserveregs(fs, 1)
2824 end
2825 end
2826
2827 ------------------------------------------------------------------------
2828 -- parse a variable assignment sequence
2829 -- * recursively called
2830 -- * used in exprstat()
2831 ------------------------------------------------------------------------
2832 function luaY:assignment(ls, lh, nvars)
2833 local e = {} -- expdesc
2834 -- test was: VLOCAL <= lh->v.k && lh->v.k <= VINDEXED
2835 local c = lh.v.k
2836 self:check_condition(ls, c == "VLOCAL" or c == "VUPVAL" or c == "VGLOBAL"
2837 or c == "VINDEXED", "syntax error")
2838 if self:testnext(ls, ",") then -- assignment -> ',' primaryexp assignment
2839 local nv = {} -- LHS_assign
2840 nv.v = {}
2841 nv.prev = lh
2842 self:primaryexp(ls, nv.v)
2843 if nv.v.k == "VLOCAL" then
2844 self:check_conflict(ls, lh, nv.v)
2845 end
2846 self:checklimit(ls.fs, nvars, self.LUAI_MAXCCALLS - ls.L.nCcalls,
2847 "variables in assignment")
2848 self:assignment(ls, nv, nvars + 1)
2849 else -- assignment -> '=' explist1
2850 self:checknext(ls, "=")
2851 local nexps = self:explist1(ls, e)
2852 if nexps ~= nvars then
2853 self:adjust_assign(ls, nvars, nexps, e)
2854 if nexps > nvars then
2855 ls.fs.freereg = ls.fs.freereg - (nexps - nvars) -- remove extra values
2856 end
2857 else
2858 luaK:setoneret(ls.fs, e) -- close last expression
2859 luaK:storevar(ls.fs, lh.v, e)
2860 return -- avoid default
2861 end
2862 end
2863 self:init_exp(e, "VNONRELOC", ls.fs.freereg - 1) -- default assignment
2864 luaK:storevar(ls.fs, lh.v, e)
2865 end
2866
2867 ------------------------------------------------------------------------
2868 -- parse condition in a repeat statement or an if control structure
2869 -- * used in repeatstat(), test_then_block()
2870 ------------------------------------------------------------------------
2871 function luaY:cond(ls)
2872 -- cond -> exp
2873 local v = {} -- expdesc
2874 self:expr(ls, v) -- read condition
2875 if v.k == "VNIL" then v.k = "VFALSE" end -- 'falses' are all equal here
2876 luaK:goiftrue(ls.fs, v)
2877 return v.f
2878 end
2879
2880 ------------------------------------------------------------------------
2881 -- parse a break statement
2882 -- * used in statements()
2883 ------------------------------------------------------------------------
2884 function luaY:breakstat(ls)
2885 -- stat -> BREAK
2886 local fs = ls.fs
2887 local bl = fs.bl
2888 local upval = false
2889 while bl and not bl.isbreakable do
2890 if bl.upval then upval = true end
2891 bl = bl.previous
2892 end
2893 if not bl then
2894 luaX:syntaxerror(ls, "no loop to break")
2895 end
2896 if upval then
2897 luaK:codeABC(fs, "OP_CLOSE", bl.nactvar, 0, 0)
2898 end
2899 bl.breaklist = luaK:concat(fs, bl.breaklist, luaK:jump(fs))
2900 end
2901
2902 ------------------------------------------------------------------------
2903 -- parse a while-do control structure, body processed by block()
2904 -- * with dynamic array sizes, MAXEXPWHILE + EXTRAEXP limits imposed by
2905 -- the function's implementation can be removed
2906 -- * used in statements()
2907 ------------------------------------------------------------------------
2908 function luaY:whilestat(ls, line)
2909 -- whilestat -> WHILE cond DO block END
2910 local fs = ls.fs
2911 local bl = {} -- BlockCnt
2912 luaX:next(ls) -- skip WHILE
2913 local whileinit = luaK:getlabel(fs)
2914 local condexit = self:cond(ls)
2915 self:enterblock(fs, bl, true)
2916 self:checknext(ls, "TK_DO")
2917 self:block(ls)
2918 luaK:patchlist(fs, luaK:jump(fs), whileinit)
2919 self:check_match(ls, "TK_END", "TK_WHILE", line)
2920 self:leaveblock(fs)
2921 luaK:patchtohere(fs, condexit) -- false conditions finish the loop
2922 end
2923
2924 ------------------------------------------------------------------------
2925 -- parse a repeat-until control structure, body parsed by chunk()
2926 -- * used in statements()
2927 ------------------------------------------------------------------------
2928 function luaY:repeatstat(ls, line)
2929 -- repeatstat -> REPEAT block UNTIL cond
2930 local fs = ls.fs
2931 local repeat_init = luaK:getlabel(fs)
2932 local bl1, bl2 = {}, {} -- BlockCnt
2933 self:enterblock(fs, bl1, true) -- loop block
2934 self:enterblock(fs, bl2, false) -- scope block
2935 luaX:next(ls) -- skip REPEAT
2936 self:chunk(ls)
2937 self:check_match(ls, "TK_UNTIL", "TK_REPEAT", line)
2938 local condexit = self:cond(ls) -- read condition (inside scope block)
2939 if not bl2.upval then -- no upvalues?
2940 self:leaveblock(fs) -- finish scope
2941 luaK:patchlist(ls.fs, condexit, repeat_init) -- close the loop
2942 else -- complete semantics when there are upvalues
2943 self:breakstat(ls) -- if condition then break
2944 luaK:patchtohere(ls.fs, condexit) -- else...
2945 self:leaveblock(fs) -- finish scope...
2946 luaK:patchlist(ls.fs, luaK:jump(fs), repeat_init) -- and repeat
2947 end
2948 self:leaveblock(fs) -- finish loop
2949 end
2950
2951 ------------------------------------------------------------------------
2952 -- parse the single expressions needed in numerical for loops
2953 -- * used in fornum()
2954 ------------------------------------------------------------------------
2955 function luaY:exp1(ls)
2956 local e = {} -- expdesc
2957 self:expr(ls, e)
2958 local k = e.k
2959 luaK:exp2nextreg(ls.fs, e)
2960 return k
2961 end
2962
2963 ------------------------------------------------------------------------
2964 -- parse a for loop body for both versions of the for loop
2965 -- * used in fornum(), forlist()
2966 ------------------------------------------------------------------------
2967 function luaY:forbody(ls, base, line, nvars, isnum)
2968 -- forbody -> DO block
2969 local bl = {} -- BlockCnt
2970 local fs = ls.fs
2971 self:adjustlocalvars(ls, 3) -- control variables
2972 self:checknext(ls, "TK_DO")
2973 local prep = isnum and luaK:codeAsBx(fs, "OP_FORPREP", base, luaK.NO_JUMP)
2974 or luaK:jump(fs)
2975 self:enterblock(fs, bl, false) -- scope for declared variables
2976 self:adjustlocalvars(ls, nvars)
2977 luaK:reserveregs(fs, nvars)
2978 self:block(ls)
2979 self:leaveblock(fs) -- end of scope for declared variables
2980 luaK:patchtohere(fs, prep)
2981 local endfor = isnum and luaK:codeAsBx(fs, "OP_FORLOOP", base, luaK.NO_JUMP)
2982 or luaK:codeABC(fs, "OP_TFORLOOP", base, 0, nvars)
2983 luaK:fixline(fs, line) -- pretend that `OP_FOR' starts the loop
2984 luaK:patchlist(fs, isnum and endfor or luaK:jump(fs), prep + 1)
2985 end
2986
2987 ------------------------------------------------------------------------
2988 -- parse a numerical for loop, calls forbody()
2989 -- * used in forstat()
2990 ------------------------------------------------------------------------
2991 function luaY:fornum(ls, varname, line)
2992 -- fornum -> NAME = exp1,exp1[,exp1] forbody
2993 local fs = ls.fs
2994 local base = fs.freereg
2995 self:new_localvarliteral(ls, "(for index)", 0)
2996 self:new_localvarliteral(ls, "(for limit)", 1)
2997 self:new_localvarliteral(ls, "(for step)", 2)
2998 self:new_localvar(ls, varname, 3)
2999 self:checknext(ls, '=')
3000 self:exp1(ls) -- initial value
3001 self:checknext(ls, ",")
3002 self:exp1(ls) -- limit
3003 if self:testnext(ls, ",") then
3004 self:exp1(ls) -- optional step
3005 else -- default step = 1
3006 luaK:codeABx(fs, "OP_LOADK", fs.freereg, luaK:numberK(fs, 1))
3007 luaK:reserveregs(fs, 1)
3008 end
3009 self:forbody(ls, base, line, 1, true)
3010 end
3011
3012 ------------------------------------------------------------------------
3013 -- parse a generic for loop, calls forbody()
3014 -- * used in forstat()
3015 ------------------------------------------------------------------------
3016 function luaY:forlist(ls, indexname)
3017 -- forlist -> NAME {,NAME} IN explist1 forbody
3018 local fs = ls.fs
3019 local e = {} -- expdesc
3020 local nvars = 0
3021 local base = fs.freereg
3022 -- create control variables
3023 self:new_localvarliteral(ls, "(for generator)", nvars)
3024 nvars = nvars + 1
3025 self:new_localvarliteral(ls, "(for state)", nvars)
3026 nvars = nvars + 1
3027 self:new_localvarliteral(ls, "(for control)", nvars)
3028 nvars = nvars + 1
3029 -- create declared variables
3030 self:new_localvar(ls, indexname, nvars)
3031 nvars = nvars + 1
3032 while self:testnext(ls, ",") do
3033 self:new_localvar(ls, self:str_checkname(ls), nvars)
3034 nvars = nvars + 1
3035 end
3036 self:checknext(ls, "TK_IN")
3037 local line = ls.linenumber
3038 self:adjust_assign(ls, 3, self:explist1(ls, e), e)
3039 luaK:checkstack(fs, 3) -- extra space to call generator
3040 self:forbody(ls, base, line, nvars - 3, false)
3041 end
3042
3043 ------------------------------------------------------------------------
3044 -- initial parsing for a for loop, calls fornum() or forlist()
3045 -- * used in statements()
3046 ------------------------------------------------------------------------
3047 function luaY:forstat(ls, line)
3048 -- forstat -> FOR (fornum | forlist) END
3049 local fs = ls.fs
3050 local bl = {} -- BlockCnt
3051 self:enterblock(fs, bl, true) -- scope for loop and control variables
3052 luaX:next(ls) -- skip `for'
3053 local varname = self:str_checkname(ls) -- first variable name
3054 local c = ls.t.token
3055 if c == "=" then
3056 self:fornum(ls, varname, line)
3057 elseif c == "," or c == "TK_IN" then
3058 self:forlist(ls, varname)
3059 else
3060 luaX:syntaxerror(ls, self:LUA_QL("=").." or "..self:LUA_QL("in").." expected")
3061 end
3062 self:check_match(ls, "TK_END", "TK_FOR", line)
3063 self:leaveblock(fs) -- loop scope (`break' jumps to this point)
3064 end
3065
3066 ------------------------------------------------------------------------
3067 -- parse part of an if control structure, including the condition
3068 -- * used in ifstat()
3069 ------------------------------------------------------------------------
3070 function luaY:test_then_block(ls)
3071 -- test_then_block -> [IF | ELSEIF] cond THEN block
3072 luaX:next(ls) -- skip IF or ELSEIF
3073 local condexit = self:cond(ls)
3074 self:checknext(ls, "TK_THEN")
3075 self:block(ls) -- `then' part
3076 return condexit
3077 end
3078
3079 ------------------------------------------------------------------------
3080 -- parse an if control structure
3081 -- * used in statements()
3082 ------------------------------------------------------------------------
3083 function luaY:ifstat(ls, line)
3084 -- ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END
3085 local fs = ls.fs
3086 local escapelist = luaK.NO_JUMP
3087 local flist = self:test_then_block(ls) -- IF cond THEN block
3088 while ls.t.token == "TK_ELSEIF" do
3089 escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
3090 luaK:patchtohere(fs, flist)
3091 flist = self:test_then_block(ls) -- ELSEIF cond THEN block
3092 end
3093 if ls.t.token == "TK_ELSE" then
3094 escapelist = luaK:concat(fs, escapelist, luaK:jump(fs))
3095 luaK:patchtohere(fs, flist)
3096 luaX:next(ls) -- skip ELSE (after patch, for correct line info)
3097 self:block(ls) -- 'else' part
3098 else
3099 escapelist = luaK:concat(fs, escapelist, flist)
3100 end
3101 luaK:patchtohere(fs, escapelist)
3102 self:check_match(ls, "TK_END", "TK_IF", line)
3103 end
3104
3105 ------------------------------------------------------------------------
3106 -- parse a local function statement
3107 -- * used in statements()
3108 ------------------------------------------------------------------------
3109 function luaY:localfunc(ls)
3110 local v, b = {}, {} -- expdesc
3111 local fs = ls.fs
3112 self:new_localvar(ls, self:str_checkname(ls), 0)
3113 self:init_exp(v, "VLOCAL", fs.freereg)
3114 luaK:reserveregs(fs, 1)
3115 self:adjustlocalvars(ls, 1)
3116 self:body(ls, b, false, ls.linenumber)
3117 luaK:storevar(fs, v, b)
3118 -- debug information will only see the variable after this point!
3119 self:getlocvar(fs, fs.nactvar - 1).startpc = fs.pc
3120 end
3121
3122 ------------------------------------------------------------------------
3123 -- parse a local variable declaration statement
3124 -- * used in statements()
3125 ------------------------------------------------------------------------
3126 function luaY:localstat(ls)
3127 -- stat -> LOCAL NAME {',' NAME} ['=' explist1]
3128 local nvars = 0
3129 local nexps
3130 local e = {} -- expdesc
3131 repeat
3132 self:new_localvar(ls, self:str_checkname(ls), nvars)
3133 nvars = nvars + 1
3134 until not self:testnext(ls, ",")
3135 if self:testnext(ls, "=") then
3136 nexps = self:explist1(ls, e)
3137 else
3138 e.k = "VVOID"
3139 nexps = 0
3140 end
3141 self:adjust_assign(ls, nvars, nexps, e)
3142 self:adjustlocalvars(ls, nvars)
3143 end
3144
3145 ------------------------------------------------------------------------
3146 -- parse a function name specification
3147 -- * used in funcstat()
3148 ------------------------------------------------------------------------
3149 function luaY:funcname(ls, v)
3150 -- funcname -> NAME {field} [':' NAME]
3151 local needself = false
3152 self:singlevar(ls, v)
3153 while ls.t.token == "." do
3154 self:field(ls, v)
3155 end
3156 if ls.t.token == ":" then
3157 needself = true
3158 self:field(ls, v)
3159 end
3160 return needself
3161 end
3162
3163 ------------------------------------------------------------------------
3164 -- parse a function statement
3165 -- * used in statements()
3166 ------------------------------------------------------------------------
3167 function luaY:funcstat(ls, line)
3168 -- funcstat -> FUNCTION funcname body
3169 local v, b = {}, {} -- expdesc
3170 luaX:next(ls) -- skip FUNCTION
3171 local needself = self:funcname(ls, v)
3172 self:body(ls, b, needself, line)
3173 luaK:storevar(ls.fs, v, b)
3174 luaK:fixline(ls.fs, line) -- definition 'happens' in the first line
3175 end
3176
3177 ------------------------------------------------------------------------
3178 -- parse a function call with no returns or an assignment statement
3179 -- * used in statements()
3180 ------------------------------------------------------------------------
3181 function luaY:exprstat(ls)
3182 -- stat -> func | assignment
3183 local fs = ls.fs
3184 local v = {} -- LHS_assign
3185 v.v = {}
3186 self:primaryexp(ls, v.v)
3187 if v.v.k == "VCALL" then -- stat -> func
3188 luaP:SETARG_C(luaK:getcode(fs, v.v), 1) -- call statement uses no results
3189 else -- stat -> assignment
3190 v.prev = nil
3191 self:assignment(ls, v, 1)
3192 end
3193 end
3194
3195 ------------------------------------------------------------------------
3196 -- parse a return statement
3197 -- * used in statements()
3198 ------------------------------------------------------------------------
3199 function luaY:retstat(ls)
3200 -- stat -> RETURN explist
3201 local fs = ls.fs
3202 local e = {} -- expdesc
3203 local first, nret -- registers with returned values
3204 luaX:next(ls) -- skip RETURN
3205 if self:block_follow(ls.t.token) or ls.t.token == ";" then
3206 first, nret = 0, 0 -- return no values
3207 else
3208 nret = self:explist1(ls, e) -- optional return values
3209 if self:hasmultret(e.k) then
3210 luaK:setmultret(fs, e)
3211 if e.k == "VCALL" and nret == 1 then -- tail call?
3212 luaP:SET_OPCODE(luaK:getcode(fs, e), "OP_TAILCALL")
3213 assert(luaP:GETARG_A(luaK:getcode(fs, e)) == fs.nactvar)
3214 end
3215 first = fs.nactvar
3216 nret = self.LUA_MULTRET -- return all values
3217 else
3218 if nret == 1 then -- only one single value?
3219 first = luaK:exp2anyreg(fs, e)
3220 else
3221 luaK:exp2nextreg(fs, e) -- values must go to the 'stack'
3222 first = fs.nactvar -- return all 'active' values
3223 assert(nret == fs.freereg - first)
3224 end
3225 end--if
3226 end--if
3227 luaK:ret(fs, first, nret)
3228 end
3229
3230 ------------------------------------------------------------------------
3231 -- initial parsing for statements, calls a lot of functions
3232 -- * returns boolean instead of 0|1
3233 -- * used in chunk()
3234 ------------------------------------------------------------------------
3235 function luaY:statement(ls)
3236 local line = ls.linenumber -- may be needed for error messages
3237 local c = ls.t.token
3238 if c == "TK_IF" then -- stat -> ifstat
3239 self:ifstat(ls, line)
3240 return false
3241 elseif c == "TK_WHILE" then -- stat -> whilestat
3242 self:whilestat(ls, line)
3243 return false
3244 elseif c == "TK_DO" then -- stat -> DO block END
3245 luaX:next(ls) -- skip DO
3246 self:block(ls)
3247 self:check_match(ls, "TK_END", "TK_DO", line)
3248 return false
3249 elseif c == "TK_FOR" then -- stat -> forstat
3250 self:forstat(ls, line)
3251 return false
3252 elseif c == "TK_REPEAT" then -- stat -> repeatstat
3253 self:repeatstat(ls, line)
3254 return false
3255 elseif c == "TK_FUNCTION" then -- stat -> funcstat
3256 self:funcstat(ls, line)
3257 return false
3258 elseif c == "TK_LOCAL" then -- stat -> localstat
3259 luaX:next(ls) -- skip LOCAL
3260 if self:testnext(ls, "TK_FUNCTION") then -- local function?
3261 self:localfunc(ls)
3262 else
3263 self:localstat(ls)
3264 end
3265 return false
3266 elseif c == "TK_RETURN" then -- stat -> retstat
3267 self:retstat(ls)
3268 return true -- must be last statement
3269 elseif c == "TK_BREAK" then -- stat -> breakstat
3270 luaX:next(ls) -- skip BREAK
3271 self:breakstat(ls)
3272 return true -- must be last statement
3273 else
3274 self:exprstat(ls)
3275 return false -- to avoid warnings
3276 end--if c
3277 end
3278
3279 ------------------------------------------------------------------------
3280 -- parse a chunk, which consists of a bunch of statements
3281 -- * used in parser(), body(), block(), repeatstat()
3282 ------------------------------------------------------------------------
3283 function luaY:chunk(ls)
3284 -- chunk -> { stat [';'] }
3285 local islast = false
3286 self:enterlevel(ls)
3287 while not islast and not self:block_follow(ls.t.token) do
3288 islast = self:statement(ls)
3289 self:testnext(ls, ";")
3290 assert(ls.fs.f.maxstacksize >= ls.fs.freereg and
3291 ls.fs.freereg >= ls.fs.nactvar)
3292 ls.fs.freereg = ls.fs.nactvar -- free registers
3293 end
3294 self:leavelevel(ls)
3295 end
3296
3297 -- }======================================================================
3298 return luaY
3299 end
3300 fake_module_scripts[script] = module_script
3301end
3302do -- nil.LuaK
3303 local script = Instance.new('ModuleScript', nil)
3304 script.Name = "LuaK"
3305 local function module_script()
3306 --[[--------------------------------------------------------------------
3307
3308 lcode.lua
3309 Lua 5 code generator in Lua
3310 This file is part of Yueliang.
3311
3312 Copyright (c) 2005-2007 Kein-Hong Man <khman@users.sf.net>
3313 The COPYRIGHT file describes the conditions
3314 under which this software may be distributed.
3315
3316 See the ChangeLog for more information.
3317
3318 ----------------------------------------------------------------------]]
3319
3320 --[[--------------------------------------------------------------------
3321 -- Notes:
3322 -- * one function manipulate a pointer argument with a simple data type
3323 -- (can't be emulated by a table, ambiguous), now returns that value:
3324 -- luaK:concat(fs, l1, l2)
3325 -- * luaM_growvector uses the faux luaY:growvector, for limit checking
3326 -- * some function parameters changed to boolean, additional code
3327 -- translates boolean back to 1/0 for instruction fields
3328 --
3329 -- Not implemented:
3330 -- * NOTE there is a failed assert in luaK:addk, a porting problem
3331 --
3332 -- Added:
3333 -- * constant MAXSTACK from llimits.h
3334 -- * luaK:ttisnumber(o) (from lobject.h)
3335 -- * luaK:nvalue(o) (from lobject.h)
3336 -- * luaK:setnilvalue(o) (from lobject.h)
3337 -- * luaK:setnvalue(o, x) (from lobject.h)
3338 -- * luaK:setbvalue(o, x) (from lobject.h)
3339 -- * luaK:sethvalue(o, x) (from lobject.h), parameter L deleted
3340 -- * luaK:setsvalue(o, x) (from lobject.h), parameter L deleted
3341 -- * luaK:numadd, luaK:numsub, luaK:nummul, luaK:numdiv, luaK:nummod,
3342 -- luaK:numpow, luaK:numunm, luaK:numisnan (from luaconf.h)
3343 -- * copyexp(e1, e2) added in luaK:posfix to copy expdesc struct
3344 --
3345 -- Changed in 5.1.x:
3346 -- * enum BinOpr has a new entry, OPR_MOD
3347 -- * enum UnOpr has a new entry, OPR_LEN
3348 -- * binopistest, unused in 5.0.x, has been deleted
3349 -- * macro setmultret is new
3350 -- * functions isnumeral, luaK_ret, boolK are new
3351 -- * funcion nilK was named nil_constant in 5.0.x
3352 -- * function interface changed: need_value, patchtestreg, concat
3353 -- * TObject now a TValue
3354 -- * functions luaK_setreturns, luaK_setoneret are new
3355 -- * function luaK:setcallreturns deleted, to be replaced by:
3356 -- luaK:setmultret, luaK:ret, luaK:setreturns, luaK:setoneret
3357 -- * functions constfolding, codearith, codecomp are new
3358 -- * luaK:codebinop has been deleted
3359 -- * function luaK_setlist is new
3360 -- * OPR_MULT renamed to OPR_MUL
3361 ----------------------------------------------------------------------]]
3362
3363 -- requires luaP, luaX, luaY
3364 local luaK = {}
3365 local luaP = require(script.Parent.LuaP)
3366 local luaX = require(script.Parent.LuaX)
3367
3368 ------------------------------------------------------------------------
3369 -- constants used by code generator
3370 ------------------------------------------------------------------------
3371 -- maximum stack for a Lua function
3372 luaK.MAXSTACK = 250 -- (from llimits.h)
3373
3374 --[[--------------------------------------------------------------------
3375 -- other functions
3376 ----------------------------------------------------------------------]]
3377
3378 ------------------------------------------------------------------------
3379 -- emulation of TValue macros (these are from lobject.h)
3380 -- * TValue is a table since lcode passes references around
3381 -- * tt member field removed, using Lua's type() instead
3382 -- * for setsvalue, sethvalue, parameter L (deleted here) in lobject.h
3383 -- is used in an assert for testing, see checkliveness(g,obj)
3384 ------------------------------------------------------------------------
3385 function luaK:ttisnumber(o)
3386 if o then return type(o.value) == "number" else return false end
3387 end
3388 function luaK:nvalue(o) return o.value end
3389 function luaK:setnilvalue(o) o.value = nil end
3390 function luaK:setsvalue(o, x) o.value = x end
3391 luaK.setnvalue = luaK.setsvalue
3392 luaK.sethvalue = luaK.setsvalue
3393 luaK.setbvalue = luaK.setsvalue
3394
3395 ------------------------------------------------------------------------
3396 -- The luai_num* macros define the primitive operations over numbers.
3397 -- * this is not the entire set of primitive operations from luaconf.h
3398 -- * used in luaK:constfolding()
3399 ------------------------------------------------------------------------
3400 function luaK:numadd(a, b) return a + b end
3401 function luaK:numsub(a, b) return a - b end
3402 function luaK:nummul(a, b) return a * b end
3403 function luaK:numdiv(a, b) return a / b end
3404 function luaK:nummod(a, b) return a % b end
3405 -- ((a) - floor((a)/(b))*(b)) /* actual, for reference */
3406 function luaK:numpow(a, b) return a ^ b end
3407 function luaK:numunm(a) return -a end
3408 function luaK:numisnan(a) return not a == a end
3409 -- a NaN cannot equal another NaN
3410
3411 --[[--------------------------------------------------------------------
3412 -- code generator functions
3413 ----------------------------------------------------------------------]]
3414
3415 ------------------------------------------------------------------------
3416 -- Marks the end of a patch list. It is an invalid value both as an absolute
3417 -- address, and as a list link (would link an element to itself).
3418 ------------------------------------------------------------------------
3419 luaK.NO_JUMP = -1
3420
3421 ------------------------------------------------------------------------
3422 -- grep "ORDER OPR" if you change these enums
3423 ------------------------------------------------------------------------
3424 luaK.BinOpr = {
3425 OPR_ADD = 0, OPR_SUB = 1, OPR_MUL = 2, OPR_DIV = 3, OPR_MOD = 4, OPR_POW = 5,
3426 OPR_CONCAT = 6,
3427 OPR_NE = 7, OPR_EQ = 8,
3428 OPR_LT = 9, OPR_LE = 10, OPR_GT = 11, OPR_GE = 12,
3429 OPR_AND = 13, OPR_OR = 14,
3430 OPR_NOBINOPR = 15,
3431 }
3432
3433 -- * UnOpr is used by luaK:prefix's op argument, but not directly used
3434 -- because the function receives the symbols as strings, e.g. "OPR_NOT"
3435 luaK.UnOpr = {
3436 OPR_MINUS = 0, OPR_NOT = 1, OPR_LEN = 2, OPR_NOUNOPR = 3
3437 }
3438
3439 ------------------------------------------------------------------------
3440 -- returns the instruction object for given e (expdesc), was a macro
3441 ------------------------------------------------------------------------
3442 function luaK:getcode(fs, e)
3443 return fs.f.code[e.info]
3444 end
3445
3446 ------------------------------------------------------------------------
3447 -- codes an instruction with a signed Bx (sBx) field, was a macro
3448 -- * used in luaK:jump(), (lparser) luaY:forbody()
3449 ------------------------------------------------------------------------
3450 function luaK:codeAsBx(fs, o, A, sBx)
3451 return self:codeABx(fs, o, A, sBx + luaP.MAXARG_sBx)
3452 end
3453
3454 ------------------------------------------------------------------------
3455 -- set the expdesc e instruction for multiple returns, was a macro
3456 ------------------------------------------------------------------------
3457 function luaK:setmultret(fs, e)
3458 self:setreturns(fs, e, luaY.LUA_MULTRET)
3459 end
3460
3461 ------------------------------------------------------------------------
3462 -- there is a jump if patch lists are not identical, was a macro
3463 -- * used in luaK:exp2reg(), luaK:exp2anyreg(), luaK:exp2val()
3464 ------------------------------------------------------------------------
3465 function luaK:hasjumps(e)
3466 return e.t ~= e.f
3467 end
3468
3469 ------------------------------------------------------------------------
3470 -- true if the expression is a constant number (for constant folding)
3471 -- * used in constfolding(), infix()
3472 ------------------------------------------------------------------------
3473 function luaK:isnumeral(e)
3474 return e.k == "VKNUM" and e.t == self.NO_JUMP and e.f == self.NO_JUMP
3475 end
3476
3477 ------------------------------------------------------------------------
3478 -- codes loading of nil, optimization done if consecutive locations
3479 -- * used in luaK:discharge2reg(), (lparser) luaY:adjust_assign()
3480 ------------------------------------------------------------------------
3481 function luaK:_nil(fs, from, n)
3482 if fs.pc > fs.lasttarget then -- no jumps to current position?
3483 if fs.pc == 0 then -- function start?
3484 if from >= fs.nactvar then
3485 return -- positions are already clean
3486 end
3487 else
3488 local previous = fs.f.code[fs.pc - 1]
3489 if luaP:GET_OPCODE(previous) == "OP_LOADNIL" then
3490 local pfrom = luaP:GETARG_A(previous)
3491 local pto = luaP:GETARG_B(previous)
3492 if pfrom <= from and from <= pto + 1 then -- can connect both?
3493 if from + n - 1 > pto then
3494 luaP:SETARG_B(previous, from + n - 1)
3495 end
3496 return
3497 end
3498 end
3499 end
3500 end
3501 self:codeABC(fs, "OP_LOADNIL", from, from + n - 1, 0) -- else no optimization
3502 end
3503
3504 ------------------------------------------------------------------------
3505 --
3506 -- * used in multiple locations
3507 ------------------------------------------------------------------------
3508 function luaK:jump(fs)
3509 local jpc = fs.jpc -- save list of jumps to here
3510 fs.jpc = self.NO_JUMP
3511 local j = self:codeAsBx(fs, "OP_JMP", 0, self.NO_JUMP)
3512 j = self:concat(fs, j, jpc) -- keep them on hold
3513 return j
3514 end
3515
3516 ------------------------------------------------------------------------
3517 -- codes a RETURN instruction
3518 -- * used in luaY:close_func(), luaY:retstat()
3519 ------------------------------------------------------------------------
3520 function luaK:ret(fs, first, nret)
3521 self:codeABC(fs, "OP_RETURN", first, nret + 1, 0)
3522 end
3523
3524 ------------------------------------------------------------------------
3525 --
3526 -- * used in luaK:jumponcond(), luaK:codecomp()
3527 ------------------------------------------------------------------------
3528 function luaK:condjump(fs, op, A, B, C)
3529 self:codeABC(fs, op, A, B, C)
3530 return self:jump(fs)
3531 end
3532
3533 ------------------------------------------------------------------------
3534 --
3535 -- * used in luaK:patchlistaux(), luaK:concat()
3536 ------------------------------------------------------------------------
3537 function luaK:fixjump(fs, pc, dest)
3538 local jmp = fs.f.code[pc]
3539 local offset = dest - (pc + 1)
3540 assert(dest ~= self.NO_JUMP)
3541 if math.abs(offset) > luaP.MAXARG_sBx then
3542 luaX:syntaxerror(fs.ls, "control structure too long")
3543 end
3544 luaP:SETARG_sBx(jmp, offset)
3545 end
3546
3547 ------------------------------------------------------------------------
3548 -- returns current 'pc' and marks it as a jump target (to avoid wrong
3549 -- optimizations with consecutive instructions not in the same basic block).
3550 -- * used in multiple locations
3551 -- * fs.lasttarget tested only by luaK:_nil() when optimizing OP_LOADNIL
3552 ------------------------------------------------------------------------
3553 function luaK:getlabel(fs)
3554 fs.lasttarget = fs.pc
3555 return fs.pc
3556 end
3557
3558 ------------------------------------------------------------------------
3559 --
3560 -- * used in luaK:need_value(), luaK:removevalues(), luaK:patchlistaux(),
3561 -- luaK:concat()
3562 ------------------------------------------------------------------------
3563 function luaK:getjump(fs, pc)
3564 local offset = luaP:GETARG_sBx(fs.f.code[pc])
3565 if offset == self.NO_JUMP then -- point to itself represents end of list
3566 return self.NO_JUMP -- end of list
3567 else
3568 return (pc + 1) + offset -- turn offset into absolute position
3569 end
3570 end
3571
3572 ------------------------------------------------------------------------
3573 --
3574 -- * used in luaK:need_value(), luaK:patchtestreg(), luaK:invertjump()
3575 ------------------------------------------------------------------------
3576 function luaK:getjumpcontrol(fs, pc)
3577 local pi = fs.f.code[pc]
3578 local ppi = fs.f.code[pc - 1]
3579 if pc >= 1 and luaP:testTMode(luaP:GET_OPCODE(ppi)) ~= 0 then
3580 return ppi
3581 else
3582 return pi
3583 end
3584 end
3585
3586 ------------------------------------------------------------------------
3587 -- check whether list has any jump that do not produce a value
3588 -- (or produce an inverted value)
3589 -- * return value changed to boolean
3590 -- * used only in luaK:exp2reg()
3591 ------------------------------------------------------------------------
3592 function luaK:need_value(fs, list)
3593 while list ~= self.NO_JUMP do
3594 local i = self:getjumpcontrol(fs, list)
3595 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then return true end
3596 list = self:getjump(fs, list)
3597 end
3598 return false -- not found
3599 end
3600
3601 ------------------------------------------------------------------------
3602 --
3603 -- * used in luaK:removevalues(), luaK:patchlistaux()
3604 ------------------------------------------------------------------------
3605 function luaK:patchtestreg(fs, node, reg)
3606 local i = self:getjumpcontrol(fs, node)
3607 if luaP:GET_OPCODE(i) ~= "OP_TESTSET" then
3608 return false -- cannot patch other instructions
3609 end
3610 if reg ~= luaP.NO_REG and reg ~= luaP:GETARG_B(i) then
3611 luaP:SETARG_A(i, reg)
3612 else -- no register to put value or register already has the value
3613 -- due to use of a table as i, i cannot be replaced by another table
3614 -- so the following is required; there is no change to ARG_C
3615 luaP:SET_OPCODE(i, "OP_TEST")
3616 local b = luaP:GETARG_B(i)
3617 luaP:SETARG_A(i, b)
3618 luaP:SETARG_B(i, 0)
3619 -- *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); /* C */
3620 end
3621 return true
3622 end
3623
3624 ------------------------------------------------------------------------
3625 --
3626 -- * used only in luaK:codenot()
3627 ------------------------------------------------------------------------
3628 function luaK:removevalues(fs, list)
3629 while list ~= self.NO_JUMP do
3630 self:patchtestreg(fs, list, luaP.NO_REG)
3631 list = self:getjump(fs, list)
3632 end
3633 end
3634
3635 ------------------------------------------------------------------------
3636 --
3637 -- * used in luaK:dischargejpc(), luaK:patchlist(), luaK:exp2reg()
3638 ------------------------------------------------------------------------
3639 function luaK:patchlistaux(fs, list, vtarget, reg, dtarget)
3640 while list ~= self.NO_JUMP do
3641 local _next = self:getjump(fs, list)
3642 if self:patchtestreg(fs, list, reg) then
3643 self:fixjump(fs, list, vtarget)
3644 else
3645 self:fixjump(fs, list, dtarget) -- jump to default target
3646 end
3647 list = _next
3648 end
3649 end
3650
3651 ------------------------------------------------------------------------
3652 --
3653 -- * used only in luaK:code()
3654 ------------------------------------------------------------------------
3655 function luaK:dischargejpc(fs)
3656 self:patchlistaux(fs, fs.jpc, fs.pc, luaP.NO_REG, fs.pc)
3657 fs.jpc = self.NO_JUMP
3658 end
3659
3660 ------------------------------------------------------------------------
3661 --
3662 -- * used in (lparser) luaY:whilestat(), luaY:repeatstat(), luaY:forbody()
3663 ------------------------------------------------------------------------
3664 function luaK:patchlist(fs, list, target)
3665 if target == fs.pc then
3666 self:patchtohere(fs, list)
3667 else
3668 assert(target < fs.pc)
3669 self:patchlistaux(fs, list, target, luaP.NO_REG, target)
3670 end
3671 end
3672
3673 ------------------------------------------------------------------------
3674 --
3675 -- * used in multiple locations
3676 ------------------------------------------------------------------------
3677 function luaK:patchtohere(fs, list)
3678 self:getlabel(fs)
3679 fs.jpc = self:concat(fs, fs.jpc, list)
3680 end
3681
3682 ------------------------------------------------------------------------
3683 -- * l1 was a pointer, now l1 is returned and callee assigns the value
3684 -- * used in multiple locations
3685 ------------------------------------------------------------------------
3686 function luaK:concat(fs, l1, l2)
3687 if l2 == self.NO_JUMP then return l1
3688 elseif l1 == self.NO_JUMP then
3689 return l2
3690 else
3691 local list = l1
3692 local _next = self:getjump(fs, list)
3693 while _next ~= self.NO_JUMP do -- find last element
3694 list = _next
3695 _next = self:getjump(fs, list)
3696 end
3697 self:fixjump(fs, list, l2)
3698 end
3699 return l1
3700 end
3701
3702 ------------------------------------------------------------------------
3703 --
3704 -- * used in luaK:reserveregs(), (lparser) luaY:forlist()
3705 ------------------------------------------------------------------------
3706 function luaK:checkstack(fs, n)
3707 local newstack = fs.freereg + n
3708 if newstack > fs.f.maxstacksize then
3709 if newstack >= self.MAXSTACK then
3710 luaX:syntaxerror(fs.ls, "function or expression too complex")
3711 end
3712 fs.f.maxstacksize = newstack
3713 end
3714 end
3715
3716 ------------------------------------------------------------------------
3717 --
3718 -- * used in multiple locations
3719 ------------------------------------------------------------------------
3720 function luaK:reserveregs(fs, n)
3721 self:checkstack(fs, n)
3722 fs.freereg = fs.freereg + n
3723 end
3724
3725 ------------------------------------------------------------------------
3726 --
3727 -- * used in luaK:freeexp(), luaK:dischargevars()
3728 ------------------------------------------------------------------------
3729 function luaK:freereg(fs, reg)
3730 if not luaP:ISK(reg) and reg >= fs.nactvar then
3731 fs.freereg = fs.freereg - 1
3732 assert(reg == fs.freereg)
3733 end
3734 end
3735
3736 ------------------------------------------------------------------------
3737 --
3738 -- * used in multiple locations
3739 ------------------------------------------------------------------------
3740 function luaK:freeexp(fs, e)
3741 if e.k == "VNONRELOC" then
3742 self:freereg(fs, e.info)
3743 end
3744 end
3745
3746 ------------------------------------------------------------------------
3747 -- * TODO NOTE implementation is not 100% correct, since the assert fails
3748 -- * luaH_set, setobj deleted; direct table access used instead
3749 -- * used in luaK:stringK(), luaK:numberK(), luaK:boolK(), luaK:nilK()
3750 ------------------------------------------------------------------------
3751 function luaK:addk(fs, k, v)
3752 local L = fs.L
3753 local idx = fs.h[k.value]
3754 --TValue *idx = luaH_set(L, fs->h, k); /* C */
3755 local f = fs.f
3756 if self:ttisnumber(idx) then
3757 --TODO this assert currently FAILS (last tested for 5.0.2)
3758 --assert(fs.f.k[self:nvalue(idx)] == v)
3759 --assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); /* C */
3760 return self:nvalue(idx)
3761 else -- constant not found; create a new entry
3762 idx = {}
3763 self:setnvalue(idx, fs.nk)
3764 fs.h[k.value] = idx
3765 -- setnvalue(idx, cast_num(fs->nk)); /* C */
3766 luaY:growvector(L, f.k, fs.nk, f.sizek, nil,
3767 luaP.MAXARG_Bx, "constant table overflow")
3768 -- loop to initialize empty f.k positions not required
3769 f.k[fs.nk] = v
3770 -- setobj(L, &f->k[fs->nk], v); /* C */
3771 -- luaC_barrier(L, f, v); /* GC */
3772 local nk = fs.nk
3773 fs.nk = fs.nk + 1
3774 return nk
3775 end
3776
3777 end
3778
3779 ------------------------------------------------------------------------
3780 -- creates and sets a string object
3781 -- * used in (lparser) luaY:codestring(), luaY:singlevar()
3782 ------------------------------------------------------------------------
3783 function luaK:stringK(fs, s)
3784 local o = {} -- TValue
3785 self:setsvalue(o, s)
3786 return self:addk(fs, o, o)
3787 end
3788
3789 ------------------------------------------------------------------------
3790 -- creates and sets a number object
3791 -- * used in luaK:prefix() for negative (or negation of) numbers
3792 -- * used in (lparser) luaY:simpleexp(), luaY:fornum()
3793 ------------------------------------------------------------------------
3794 function luaK:numberK(fs, r)
3795 local o = {} -- TValue
3796 self:setnvalue(o, r)
3797 return self:addk(fs, o, o)
3798 end
3799
3800 ------------------------------------------------------------------------
3801 -- creates and sets a boolean object
3802 -- * used only in luaK:exp2RK()
3803 ------------------------------------------------------------------------
3804 function luaK:boolK(fs, b)
3805 local o = {} -- TValue
3806 self:setbvalue(o, b)
3807 return self:addk(fs, o, o)
3808 end
3809
3810 ------------------------------------------------------------------------
3811 -- creates and sets a nil object
3812 -- * used only in luaK:exp2RK()
3813 ------------------------------------------------------------------------
3814 function luaK:nilK(fs)
3815 local k, v = {}, {} -- TValue
3816 self:setnilvalue(v)
3817 -- cannot use nil as key; instead use table itself to represent nil
3818 self:sethvalue(k, fs.h)
3819 return self:addk(fs, k, v)
3820 end
3821
3822 ------------------------------------------------------------------------
3823 --
3824 -- * used in luaK:setmultret(), (lparser) luaY:adjust_assign()
3825 ------------------------------------------------------------------------
3826 function luaK:setreturns(fs, e, nresults)
3827 if e.k == "VCALL" then -- expression is an open function call?
3828 luaP:SETARG_C(self:getcode(fs, e), nresults + 1)
3829 elseif e.k == "VVARARG" then
3830 luaP:SETARG_B(self:getcode(fs, e), nresults + 1);
3831 luaP:SETARG_A(self:getcode(fs, e), fs.freereg);
3832 luaK:reserveregs(fs, 1)
3833 end
3834 end
3835
3836 ------------------------------------------------------------------------
3837 --
3838 -- * used in luaK:dischargevars(), (lparser) luaY:assignment()
3839 ------------------------------------------------------------------------
3840 function luaK:setoneret(fs, e)
3841 if e.k == "VCALL" then -- expression is an open function call?
3842 e.k = "VNONRELOC"
3843 e.info = luaP:GETARG_A(self:getcode(fs, e))
3844 elseif e.k == "VVARARG" then
3845 luaP:SETARG_B(self:getcode(fs, e), 2)
3846 e.k = "VRELOCABLE" -- can relocate its simple result
3847 end
3848 end
3849
3850 ------------------------------------------------------------------------
3851 --
3852 -- * used in multiple locations
3853 ------------------------------------------------------------------------
3854 function luaK:dischargevars(fs, e)
3855 local k = e.k
3856 if k == "VLOCAL" then
3857 e.k = "VNONRELOC"
3858 elseif k == "VUPVAL" then
3859 e.info = self:codeABC(fs, "OP_GETUPVAL", 0, e.info, 0)
3860 e.k = "VRELOCABLE"
3861 elseif k == "VGLOBAL" then
3862 e.info = self:codeABx(fs, "OP_GETGLOBAL", 0, e.info)
3863 e.k = "VRELOCABLE"
3864 elseif k == "VINDEXED" then
3865 self:freereg(fs, e.aux)
3866 self:freereg(fs, e.info)
3867 e.info = self:codeABC(fs, "OP_GETTABLE", 0, e.info, e.aux)
3868 e.k = "VRELOCABLE"
3869 elseif k == "VVARARG" or k == "VCALL" then
3870 self:setoneret(fs, e)
3871 else
3872 -- there is one value available (somewhere)
3873 end
3874 end
3875
3876 ------------------------------------------------------------------------
3877 --
3878 -- * used only in luaK:exp2reg()
3879 ------------------------------------------------------------------------
3880 function luaK:code_label(fs, A, b, jump)
3881 self:getlabel(fs) -- those instructions may be jump targets
3882 return self:codeABC(fs, "OP_LOADBOOL", A, b, jump)
3883 end
3884
3885 ------------------------------------------------------------------------
3886 --
3887 -- * used in luaK:discharge2anyreg(), luaK:exp2reg()
3888 ------------------------------------------------------------------------
3889 function luaK:discharge2reg(fs, e, reg)
3890 self:dischargevars(fs, e)
3891 local k = e.k
3892 if k == "VNIL" then
3893 self:_nil(fs, reg, 1)
3894 elseif k == "VFALSE" or k == "VTRUE" then
3895 self:codeABC(fs, "OP_LOADBOOL", reg, (e.k == "VTRUE") and 1 or 0, 0)
3896 elseif k == "VK" then
3897 self:codeABx(fs, "OP_LOADK", reg, e.info)
3898 elseif k == "VKNUM" then
3899 self:codeABx(fs, "OP_LOADK", reg, self:numberK(fs, e.nval))
3900 elseif k == "VRELOCABLE" then
3901 local pc = self:getcode(fs, e)
3902 luaP:SETARG_A(pc, reg)
3903 elseif k == "VNONRELOC" then
3904 if reg ~= e.info then
3905 self:codeABC(fs, "OP_MOVE", reg, e.info, 0)
3906 end
3907 else
3908 assert(e.k == "VVOID" or e.k == "VJMP")
3909 return -- nothing to do...
3910 end
3911 e.info = reg
3912 e.k = "VNONRELOC"
3913 end
3914
3915 ------------------------------------------------------------------------
3916 --
3917 -- * used in luaK:jumponcond(), luaK:codenot()
3918 ------------------------------------------------------------------------
3919 function luaK:discharge2anyreg(fs, e)
3920 if e.k ~= "VNONRELOC" then
3921 self:reserveregs(fs, 1)
3922 self:discharge2reg(fs, e, fs.freereg - 1)
3923 end
3924 end
3925
3926 ------------------------------------------------------------------------
3927 --
3928 -- * used in luaK:exp2nextreg(), luaK:exp2anyreg(), luaK:storevar()
3929 ------------------------------------------------------------------------
3930 function luaK:exp2reg(fs, e, reg)
3931 self:discharge2reg(fs, e, reg)
3932 if e.k == "VJMP" then
3933 e.t = self:concat(fs, e.t, e.info) -- put this jump in 't' list
3934 end
3935 if self:hasjumps(e) then
3936 local final -- position after whole expression
3937 local p_f = self.NO_JUMP -- position of an eventual LOAD false
3938 local p_t = self.NO_JUMP -- position of an eventual LOAD true
3939 if self:need_value(fs, e.t) or self:need_value(fs, e.f) then
3940 local fj = (e.k == "VJMP") and self.NO_JUMP or self:jump(fs)
3941 p_f = self:code_label(fs, reg, 0, 1)
3942 p_t = self:code_label(fs, reg, 1, 0)
3943 self:patchtohere(fs, fj)
3944 end
3945 final = self:getlabel(fs)
3946 self:patchlistaux(fs, e.f, final, reg, p_f)
3947 self:patchlistaux(fs, e.t, final, reg, p_t)
3948 end
3949 e.f, e.t = self.NO_JUMP, self.NO_JUMP
3950 e.info = reg
3951 e.k = "VNONRELOC"
3952 end
3953
3954 ------------------------------------------------------------------------
3955 --
3956 -- * used in multiple locations
3957 ------------------------------------------------------------------------
3958 function luaK:exp2nextreg(fs, e)
3959 self:dischargevars(fs, e)
3960 self:freeexp(fs, e)
3961 self:reserveregs(fs, 1)
3962 self:exp2reg(fs, e, fs.freereg - 1)
3963 end
3964
3965 ------------------------------------------------------------------------
3966 --
3967 -- * used in multiple locations
3968 ------------------------------------------------------------------------
3969 function luaK:exp2anyreg(fs, e)
3970 self:dischargevars(fs, e)
3971 if e.k == "VNONRELOC" then
3972 if not self:hasjumps(e) then -- exp is already in a register
3973 return e.info
3974 end
3975 if e.info >= fs.nactvar then -- reg. is not a local?
3976 self:exp2reg(fs, e, e.info) -- put value on it
3977 return e.info
3978 end
3979 end
3980 self:exp2nextreg(fs, e) -- default
3981 return e.info
3982 end
3983
3984 ------------------------------------------------------------------------
3985 --
3986 -- * used in luaK:exp2RK(), luaK:prefix(), luaK:posfix()
3987 -- * used in (lparser) luaY:yindex()
3988 ------------------------------------------------------------------------
3989 function luaK:exp2val(fs, e)
3990 if self:hasjumps(e) then
3991 self:exp2anyreg(fs, e)
3992 else
3993 self:dischargevars(fs, e)
3994 end
3995 end
3996
3997 ------------------------------------------------------------------------
3998 --
3999 -- * used in multiple locations
4000 ------------------------------------------------------------------------
4001 function luaK:exp2RK(fs, e)
4002 self:exp2val(fs, e)
4003 local k = e.k
4004 if k == "VKNUM" or k == "VTRUE" or k == "VFALSE" or k == "VNIL" then
4005 if fs.nk <= luaP.MAXINDEXRK then -- constant fit in RK operand?
4006 -- converted from a 2-deep ternary operator expression
4007 if e.k == "VNIL" then
4008 e.info = self:nilK(fs)
4009 else
4010 e.info = (e.k == "VKNUM") and self:numberK(fs, e.nval)
4011 or self:boolK(fs, e.k == "VTRUE")
4012 end
4013 e.k = "VK"
4014 return luaP:RKASK(e.info)
4015 end
4016 elseif k == "VK" then
4017 if e.info <= luaP.MAXINDEXRK then -- constant fit in argC?
4018 return luaP:RKASK(e.info)
4019 end
4020 else
4021 -- default
4022 end
4023 -- not a constant in the right range: put it in a register
4024 return self:exp2anyreg(fs, e)
4025 end
4026
4027 ------------------------------------------------------------------------
4028 --
4029 -- * used in (lparser) luaY:assignment(), luaY:localfunc(), luaY:funcstat()
4030 ------------------------------------------------------------------------
4031 function luaK:storevar(fs, var, ex)
4032 local k = var.k
4033 if k == "VLOCAL" then
4034 self:freeexp(fs, ex)
4035 self:exp2reg(fs, ex, var.info)
4036 return
4037 elseif k == "VUPVAL" then
4038 local e = self:exp2anyreg(fs, ex)
4039 self:codeABC(fs, "OP_SETUPVAL", e, var.info, 0)
4040 elseif k == "VGLOBAL" then
4041 local e = self:exp2anyreg(fs, ex)
4042 self:codeABx(fs, "OP_SETGLOBAL", e, var.info)
4043 elseif k == "VINDEXED" then
4044 local e = self:exp2RK(fs, ex)
4045 self:codeABC(fs, "OP_SETTABLE", var.info, var.aux, e)
4046 else
4047 assert(0) -- invalid var kind to store
4048 end
4049 self:freeexp(fs, ex)
4050 end
4051
4052 ------------------------------------------------------------------------
4053 --
4054 -- * used only in (lparser) luaY:primaryexp()
4055 ------------------------------------------------------------------------
4056 function luaK:_self(fs, e, key)
4057 self:exp2anyreg(fs, e)
4058 self:freeexp(fs, e)
4059 local func = fs.freereg
4060 self:reserveregs(fs, 2)
4061 self:codeABC(fs, "OP_SELF", func, e.info, self:exp2RK(fs, key))
4062 self:freeexp(fs, key)
4063 e.info = func
4064 e.k = "VNONRELOC"
4065 end
4066
4067 ------------------------------------------------------------------------
4068 --
4069 -- * used in luaK:goiftrue(), luaK:codenot()
4070 ------------------------------------------------------------------------
4071 function luaK:invertjump(fs, e)
4072 local pc = self:getjumpcontrol(fs, e.info)
4073 assert(luaP:testTMode(luaP:GET_OPCODE(pc)) ~= 0 and
4074 luaP:GET_OPCODE(pc) ~= "OP_TESTSET" and
4075 luaP:GET_OPCODE(pc) ~= "OP_TEST")
4076 luaP:SETARG_A(pc, (luaP:GETARG_A(pc) == 0) and 1 or 0)
4077 end
4078
4079 ------------------------------------------------------------------------
4080 --
4081 -- * used in luaK:goiftrue(), luaK:goiffalse()
4082 ------------------------------------------------------------------------
4083 function luaK:jumponcond(fs, e, cond)
4084 if e.k == "VRELOCABLE" then
4085 local ie = self:getcode(fs, e)
4086 if luaP:GET_OPCODE(ie) == "OP_NOT" then
4087 fs.pc = fs.pc - 1 -- remove previous OP_NOT
4088 return self:condjump(fs, "OP_TEST", luaP:GETARG_B(ie), 0, cond and 0 or 1)
4089 end
4090 -- else go through
4091 end
4092 self:discharge2anyreg(fs, e)
4093 self:freeexp(fs, e)
4094 return self:condjump(fs, "OP_TESTSET", luaP.NO_REG, e.info, cond and 1 or 0)
4095 end
4096
4097 ------------------------------------------------------------------------
4098 --
4099 -- * used in luaK:infix(), (lparser) luaY:cond()
4100 ------------------------------------------------------------------------
4101 function luaK:goiftrue(fs, e)
4102 local pc -- pc of last jump
4103 self:dischargevars(fs, e)
4104 local k = e.k
4105 if k == "VK" or k == "VKNUM" or k == "VTRUE" then
4106 pc = self.NO_JUMP -- always true; do nothing
4107 elseif k == "VFALSE" then
4108 pc = self:jump(fs) -- always jump
4109 elseif k == "VJMP" then
4110 self:invertjump(fs, e)
4111 pc = e.info
4112 else
4113 pc = self:jumponcond(fs, e, false)
4114 end
4115 e.f = self:concat(fs, e.f, pc) -- insert last jump in `f' list
4116 self:patchtohere(fs, e.t)
4117 e.t = self.NO_JUMP
4118 end
4119
4120 ------------------------------------------------------------------------
4121 --
4122 -- * used in luaK:infix()
4123 ------------------------------------------------------------------------
4124 function luaK:goiffalse(fs, e)
4125 local pc -- pc of last jump
4126 self:dischargevars(fs, e)
4127 local k = e.k
4128 if k == "VNIL" or k == "VFALSE"then
4129 pc = self.NO_JUMP -- always false; do nothing
4130 elseif k == "VTRUE" then
4131 pc = self:jump(fs) -- always jump
4132 elseif k == "VJMP" then
4133 pc = e.info
4134 else
4135 pc = self:jumponcond(fs, e, true)
4136 end
4137 e.t = self:concat(fs, e.t, pc) -- insert last jump in `t' list
4138 self:patchtohere(fs, e.f)
4139 e.f = self.NO_JUMP
4140 end
4141
4142 ------------------------------------------------------------------------
4143 --
4144 -- * used only in luaK:prefix()
4145 ------------------------------------------------------------------------
4146 function luaK:codenot(fs, e)
4147 self:dischargevars(fs, e)
4148 local k = e.k
4149 if k == "VNIL" or k == "VFALSE" then
4150 e.k = "VTRUE"
4151 elseif k == "VK" or k == "VKNUM" or k == "VTRUE" then
4152 e.k = "VFALSE"
4153 elseif k == "VJMP" then
4154 self:invertjump(fs, e)
4155 elseif k == "VRELOCABLE" or k == "VNONRELOC" then
4156 self:discharge2anyreg(fs, e)
4157 self:freeexp(fs, e)
4158 e.info = self:codeABC(fs, "OP_NOT", 0, e.info, 0)
4159 e.k = "VRELOCABLE"
4160 else
4161 assert(0) -- cannot happen
4162 end
4163 -- interchange true and false lists
4164 e.f, e.t = e.t, e.f
4165 self:removevalues(fs, e.f)
4166 self:removevalues(fs, e.t)
4167 end
4168
4169 ------------------------------------------------------------------------
4170 --
4171 -- * used in (lparser) luaY:field(), luaY:primaryexp()
4172 ------------------------------------------------------------------------
4173 function luaK:indexed(fs, t, k)
4174 t.aux = self:exp2RK(fs, k)
4175 t.k = "VINDEXED"
4176 end
4177
4178 ------------------------------------------------------------------------
4179 --
4180 -- * used only in luaK:codearith()
4181 ------------------------------------------------------------------------
4182 function luaK:constfolding(op, e1, e2)
4183 local r
4184 if not self:isnumeral(e1) or not self:isnumeral(e2) then return false end
4185 local v1 = e1.nval
4186 local v2 = e2.nval
4187 if op == "OP_ADD" then
4188 r = self:numadd(v1, v2)
4189 elseif op == "OP_SUB" then
4190 r = self:numsub(v1, v2)
4191 elseif op == "OP_MUL" then
4192 r = self:nummul(v1, v2)
4193 elseif op == "OP_DIV" then
4194 if v2 == 0 then return false end -- do not attempt to divide by 0
4195 r = self:numdiv(v1, v2)
4196 elseif op == "OP_MOD" then
4197 if v2 == 0 then return false end -- do not attempt to divide by 0
4198 r = self:nummod(v1, v2)
4199 elseif op == "OP_POW" then
4200 r = self:numpow(v1, v2)
4201 elseif op == "OP_UNM" then
4202 r = self:numunm(v1)
4203 elseif op == "OP_LEN" then
4204 return false -- no constant folding for 'len'
4205 else
4206 assert(0)
4207 r = 0
4208 end
4209 if self:numisnan(r) then return false end -- do not attempt to produce NaN
4210 e1.nval = r
4211 return true
4212 end
4213
4214 ------------------------------------------------------------------------
4215 --
4216 -- * used in luaK:prefix(), luaK:posfix()
4217 ------------------------------------------------------------------------
4218 function luaK:codearith(fs, op, e1, e2)
4219 if self:constfolding(op, e1, e2) then
4220 return
4221 else
4222 local o2 = (op ~= "OP_UNM" and op ~= "OP_LEN") and self:exp2RK(fs, e2) or 0
4223 local o1 = self:exp2RK(fs, e1)
4224 if o1 > o2 then
4225 self:freeexp(fs, e1)
4226 self:freeexp(fs, e2)
4227 else
4228 self:freeexp(fs, e2)
4229 self:freeexp(fs, e1)
4230 end
4231 e1.info = self:codeABC(fs, op, 0, o1, o2)
4232 e1.k = "VRELOCABLE"
4233 end
4234 end
4235
4236 ------------------------------------------------------------------------
4237 --
4238 -- * used only in luaK:posfix()
4239 ------------------------------------------------------------------------
4240 function luaK:codecomp(fs, op, cond, e1, e2)
4241 local o1 = self:exp2RK(fs, e1)
4242 local o2 = self:exp2RK(fs, e2)
4243 self:freeexp(fs, e2)
4244 self:freeexp(fs, e1)
4245 if cond == 0 and op ~= "OP_EQ" then
4246 -- exchange args to replace by `<' or `<='
4247 o1, o2 = o2, o1 -- o1 <==> o2
4248 cond = 1
4249 end
4250 e1.info = self:condjump(fs, op, cond, o1, o2)
4251 e1.k = "VJMP"
4252 end
4253
4254 ------------------------------------------------------------------------
4255 --
4256 -- * used only in (lparser) luaY:subexpr()
4257 ------------------------------------------------------------------------
4258 function luaK:prefix(fs, op, e)
4259 local e2 = {} -- expdesc
4260 e2.t, e2.f = self.NO_JUMP, self.NO_JUMP
4261 e2.k = "VKNUM"
4262 e2.nval = 0
4263 if op == "OPR_MINUS" then
4264 if not self:isnumeral(e) then
4265 self:exp2anyreg(fs, e) -- cannot operate on non-numeric constants
4266 end
4267 self:codearith(fs, "OP_UNM", e, e2)
4268 elseif op == "OPR_NOT" then
4269 self:codenot(fs, e)
4270 elseif op == "OPR_LEN" then
4271 self:exp2anyreg(fs, e) -- cannot operate on constants
4272 self:codearith(fs, "OP_LEN", e, e2)
4273 else
4274 assert(0)
4275 end
4276 end
4277
4278 ------------------------------------------------------------------------
4279 --
4280 -- * used only in (lparser) luaY:subexpr()
4281 ------------------------------------------------------------------------
4282 function luaK:infix(fs, op, v)
4283 if op == "OPR_AND" then
4284 self:goiftrue(fs, v)
4285 elseif op == "OPR_OR" then
4286 self:goiffalse(fs, v)
4287 elseif op == "OPR_CONCAT" then
4288 self:exp2nextreg(fs, v) -- operand must be on the 'stack'
4289 elseif op == "OPR_ADD" or op == "OPR_SUB" or
4290 op == "OPR_MUL" or op == "OPR_DIV" or
4291 op == "OPR_MOD" or op == "OPR_POW" then
4292 if not self:isnumeral(v) then self:exp2RK(fs, v) end
4293 else
4294 self:exp2RK(fs, v)
4295 end
4296 end
4297
4298 ------------------------------------------------------------------------
4299 --
4300 -- * used only in (lparser) luaY:subexpr()
4301 ------------------------------------------------------------------------
4302 -- table lookups to simplify testing
4303 luaK.arith_op = {
4304 OPR_ADD = "OP_ADD", OPR_SUB = "OP_SUB", OPR_MUL = "OP_MUL",
4305 OPR_DIV = "OP_DIV", OPR_MOD = "OP_MOD", OPR_POW = "OP_POW",
4306 }
4307 luaK.comp_op = {
4308 OPR_EQ = "OP_EQ", OPR_NE = "OP_EQ", OPR_LT = "OP_LT",
4309 OPR_LE = "OP_LE", OPR_GT = "OP_LT", OPR_GE = "OP_LE",
4310 }
4311 luaK.comp_cond = {
4312 OPR_EQ = 1, OPR_NE = 0, OPR_LT = 1,
4313 OPR_LE = 1, OPR_GT = 0, OPR_GE = 0,
4314 }
4315 function luaK:posfix(fs, op, e1, e2)
4316 -- needed because e1 = e2 doesn't copy values...
4317 -- * in 5.0.x, only k/info/aux/t/f copied, t for AND, f for OR
4318 -- but here, all elements are copied for completeness' sake
4319 local function copyexp(e1, e2)
4320 e1.k = e2.k
4321 e1.info = e2.info; e1.aux = e2.aux
4322 e1.nval = e2.nval
4323 e1.t = e2.t; e1.f = e2.f
4324 end
4325 if op == "OPR_AND" then
4326 assert(e1.t == self.NO_JUMP) -- list must be closed
4327 self:dischargevars(fs, e2)
4328 e2.f = self:concat(fs, e2.f, e1.f)
4329 copyexp(e1, e2)
4330 elseif op == "OPR_OR" then
4331 assert(e1.f == self.NO_JUMP) -- list must be closed
4332 self:dischargevars(fs, e2)
4333 e2.t = self:concat(fs, e2.t, e1.t)
4334 copyexp(e1, e2)
4335 elseif op == "OPR_CONCAT" then
4336 self:exp2val(fs, e2)
4337 if e2.k == "VRELOCABLE" and luaP:GET_OPCODE(self:getcode(fs, e2)) == "OP_CONCAT" then
4338 assert(e1.info == luaP:GETARG_B(self:getcode(fs, e2)) - 1)
4339 self:freeexp(fs, e1)
4340 luaP:SETARG_B(self:getcode(fs, e2), e1.info)
4341 e1.k = "VRELOCABLE"
4342 e1.info = e2.info
4343 else
4344 self:exp2nextreg(fs, e2) -- operand must be on the 'stack'
4345 self:codearith(fs, "OP_CONCAT", e1, e2)
4346 end
4347 else
4348 -- the following uses a table lookup in place of conditionals
4349 local arith = self.arith_op[op]
4350 if arith then
4351 self:codearith(fs, arith, e1, e2)
4352 else
4353 local comp = self.comp_op[op]
4354 if comp then
4355 self:codecomp(fs, comp, self.comp_cond[op], e1, e2)
4356 else
4357 assert(0)
4358 end
4359 end--if arith
4360 end--if op
4361 end
4362
4363 ------------------------------------------------------------------------
4364 -- adjusts debug information for last instruction written, in order to
4365 -- change the line where item comes into existence
4366 -- * used in (lparser) luaY:funcargs(), luaY:forbody(), luaY:funcstat()
4367 ------------------------------------------------------------------------
4368 function luaK:fixline(fs, line)
4369 fs.f.lineinfo[fs.pc - 1] = line
4370 end
4371
4372 ------------------------------------------------------------------------
4373 -- general function to write an instruction into the instruction buffer,
4374 -- sets debug information too
4375 -- * used in luaK:codeABC(), luaK:codeABx()
4376 -- * called directly by (lparser) luaY:whilestat()
4377 ------------------------------------------------------------------------
4378 function luaK:code(fs, i, line)
4379 local f = fs.f
4380 self:dischargejpc(fs) -- 'pc' will change
4381 -- put new instruction in code array
4382 luaY:growvector(fs.L, f.code, fs.pc, f.sizecode, nil,
4383 luaY.MAX_INT, "code size overflow")
4384 f.code[fs.pc] = i
4385 -- save corresponding line information
4386 luaY:growvector(fs.L, f.lineinfo, fs.pc, f.sizelineinfo, nil,
4387 luaY.MAX_INT, "code size overflow")
4388 f.lineinfo[fs.pc] = line
4389 local pc = fs.pc
4390 fs.pc = fs.pc + 1
4391 return pc
4392 end
4393
4394 ------------------------------------------------------------------------
4395 -- writes an instruction of type ABC
4396 -- * calls luaK:code()
4397 ------------------------------------------------------------------------
4398 function luaK:codeABC(fs, o, a, b, c)
4399 assert(luaP:getOpMode(o) == luaP.OpMode.iABC)
4400 assert(luaP:getBMode(o) ~= luaP.OpArgMask.OpArgN or b == 0)
4401 assert(luaP:getCMode(o) ~= luaP.OpArgMask.OpArgN or c == 0)
4402 return self:code(fs, luaP:CREATE_ABC(o, a, b, c), fs.ls.lastline)
4403 end
4404
4405 ------------------------------------------------------------------------
4406 -- writes an instruction of type ABx
4407 -- * calls luaK:code(), called by luaK:codeAsBx()
4408 ------------------------------------------------------------------------
4409 function luaK:codeABx(fs, o, a, bc)
4410 assert(luaP:getOpMode(o) == luaP.OpMode.iABx or
4411 luaP:getOpMode(o) == luaP.OpMode.iAsBx)
4412 assert(luaP:getCMode(o) == luaP.OpArgMask.OpArgN)
4413 return self:code(fs, luaP:CREATE_ABx(o, a, bc), fs.ls.lastline)
4414 end
4415
4416 ------------------------------------------------------------------------
4417 --
4418 -- * used in (lparser) luaY:closelistfield(), luaY:lastlistfield()
4419 ------------------------------------------------------------------------
4420 function luaK:setlist(fs, base, nelems, tostore)
4421 local c = math.floor((nelems - 1)/luaP.LFIELDS_PER_FLUSH) + 1
4422 local b = (tostore == luaY.LUA_MULTRET) and 0 or tostore
4423 assert(tostore ~= 0)
4424 if c <= luaP.MAXARG_C then
4425 self:codeABC(fs, "OP_SETLIST", base, b, c)
4426 else
4427 self:codeABC(fs, "OP_SETLIST", base, b, 0)
4428 self:code(fs, luaP:CREATE_Inst(c), fs.ls.lastline)
4429 end
4430 fs.freereg = base + 1 -- free registers with list values
4431 end
4432
4433 return function(a) luaY = a return luaK end
4434 end
4435 fake_module_scripts[script] = module_script
4436end
4437do -- nil.LuaU
4438 local script = Instance.new('ModuleScript', nil)
4439 script.Name = "LuaU"
4440 local function module_script()
4441 --[[--------------------------------------------------------------------
4442
4443 ldump.lua
4444 Save precompiled Lua chunks
4445 This file is part of Yueliang.
4446
4447 Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
4448 The COPYRIGHT file describes the conditions
4449 under which this software may be distributed.
4450
4451 See the ChangeLog for more information.
4452
4453 ----------------------------------------------------------------------]]
4454
4455 --[[--------------------------------------------------------------------
4456 -- Notes:
4457 -- * WARNING! byte order (little endian) and data type sizes for header
4458 -- signature values hard-coded; see luaU:header
4459 -- * chunk writer generators are included, see below
4460 -- * one significant difference is that instructions are still in table
4461 -- form (with OP/A/B/C/Bx fields) and luaP:Instruction() is needed to
4462 -- convert them into 4-char strings
4463 --
4464 -- Not implemented:
4465 -- * DumpVar, DumpMem has been removed
4466 -- * DumpVector folded into folded into DumpDebug, DumpCode
4467 --
4468 -- Added:
4469 -- * for convenience, the following two functions have been added:
4470 -- luaU:make_setS: create a chunk writer that writes to a string
4471 -- luaU:make_setF: create a chunk writer that writes to a file
4472 -- (lua.h contains a typedef for lua_Writer/lua_Chunkwriter, and
4473 -- a Lua-based implementation exists, writer() in lstrlib.c)
4474 -- * luaU:ttype(o) (from lobject.h)
4475 -- * for converting number types to its binary equivalent:
4476 -- luaU:from_double(x): encode double value for writing
4477 -- luaU:from_int(x): encode integer value for writing
4478 -- (error checking is limited for these conversion functions)
4479 -- (double conversion does not support denormals or NaNs)
4480 --
4481 -- Changed in 5.1.x:
4482 -- * the dumper was mostly rewritten in Lua 5.1.x, so notes on the
4483 -- differences between 5.0.x and 5.1.x is limited
4484 -- * LUAC_VERSION bumped to 0x51, LUAC_FORMAT added
4485 -- * developer is expected to adjust LUAC_FORMAT in order to identify
4486 -- non-standard binary chunk formats
4487 -- * header signature code is smaller, has been simplified, and is
4488 -- tested as a single unit; its logic is shared with the undumper
4489 -- * no more endian conversion, invalid endianness mean rejection
4490 -- * opcode field sizes are no longer exposed in the header
4491 -- * code moved to front of a prototype, followed by constants
4492 -- * debug information moved to the end of the binary chunk, and the
4493 -- relevant functions folded into a single function
4494 -- * luaU:dump returns a writer status code
4495 -- * chunk writer now implements status code because dumper uses it
4496 -- * luaU:endianness removed
4497 ----------------------------------------------------------------------]]
4498
4499 --requires luaP
4500 local luaU = {}
4501 local luaP = require(script.Parent.LuaP)
4502
4503 -- mark for precompiled code ('<esc>Lua') (from lua.h)
4504 luaU.LUA_SIGNATURE = "\27Lua"
4505
4506 -- constants used by dumper (from lua.h)
4507 luaU.LUA_TNUMBER = 3
4508 luaU.LUA_TSTRING = 4
4509 luaU.LUA_TNIL = 0
4510 luaU.LUA_TBOOLEAN = 1
4511 luaU.LUA_TNONE = -1
4512
4513 -- constants for header of binary files (from lundump.h)
4514 luaU.LUAC_VERSION = 0x51 -- this is Lua 5.1
4515 luaU.LUAC_FORMAT = 0 -- this is the official format
4516 luaU.LUAC_HEADERSIZE = 12 -- size of header of binary files
4517
4518 --[[--------------------------------------------------------------------
4519 -- Additional functions to handle chunk writing
4520 -- * to use make_setS and make_setF, see test_ldump.lua elsewhere
4521 ----------------------------------------------------------------------]]
4522
4523 ------------------------------------------------------------------------
4524 -- create a chunk writer that writes to a string
4525 -- * returns the writer function and a table containing the string
4526 -- * to get the final result, look in buff.data
4527 ------------------------------------------------------------------------
4528 function luaU:make_setS()
4529 local buff = {}
4530 buff.data = ""
4531 local writer =
4532 function(s, buff) -- chunk writer
4533 if not s then return 0 end
4534 buff.data = buff.data..s
4535 return 0
4536 end
4537 return writer, buff
4538 end
4539
4540 ------------------------------------------------------------------------
4541 -- create a chunk writer that writes to a file
4542 -- * returns the writer function and a table containing the file handle
4543 -- * if a nil is passed, then writer should close the open file
4544 ------------------------------------------------------------------------
4545
4546 --[[
4547 function luaU:make_setF(filename)
4548 local buff = {}
4549 buff.h = io.open(filename, "wb")
4550 if not buff.h then return nil end
4551 local writer =
4552 function(s, buff) -- chunk writer
4553 if not buff.h then return 0 end
4554 if not s then
4555 if buff.h:close() then return 0 end
4556 else
4557 if buff.h:write(s) then return 0 end
4558 end
4559 return 1
4560 end
4561 return writer, buff
4562 end--]]
4563
4564 ------------------------------------------------------------------------
4565 -- works like the lobject.h version except that TObject used in these
4566 -- scripts only has a 'value' field, no 'tt' field (native types used)
4567 ------------------------------------------------------------------------
4568 function luaU:ttype(o)
4569 local tt = type(o.value)
4570 if tt == "number" then return self.LUA_TNUMBER
4571 elseif tt == "string" then return self.LUA_TSTRING
4572 elseif tt == "nil" then return self.LUA_TNIL
4573 elseif tt == "boolean" then return self.LUA_TBOOLEAN
4574 else
4575 return self.LUA_TNONE -- the rest should not appear
4576 end
4577 end
4578
4579 -----------------------------------------------------------------------
4580 -- converts a IEEE754 double number to an 8-byte little-endian string
4581 -- * luaU:from_double() and luaU:from_int() are adapted from ChunkBake
4582 -- * supports +/- Infinity, but not denormals or NaNs
4583 -----------------------------------------------------------------------
4584 function luaU:from_double(x)
4585 local function grab_byte(v)
4586 local c = v % 256
4587 return (v - c) / 256, string.char(c)
4588 end
4589 local sign = 0
4590 if x < 0 then sign = 1; x = -x end
4591 local mantissa, exponent = math.frexp(x)
4592 if x == 0 then -- zero
4593 mantissa, exponent = 0, 0
4594 elseif x == 1/0 then
4595 mantissa, exponent = 0, 2047
4596 else
4597 mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, 53)
4598 exponent = exponent + 1022
4599 end
4600 local v, byte = "" -- convert to bytes
4601 x = math.floor(mantissa)
4602 for i = 1,6 do
4603 x, byte = grab_byte(x); v = v..byte -- 47:0
4604 end
4605 x, byte = grab_byte(exponent * 16 + x); v = v..byte -- 55:48
4606 x, byte = grab_byte(sign * 128 + x); v = v..byte -- 63:56
4607 return v
4608 end
4609
4610 -----------------------------------------------------------------------
4611 -- converts a number to a little-endian 32-bit integer string
4612 -- * input value assumed to not overflow, can be signed/unsigned
4613 -----------------------------------------------------------------------
4614 function luaU:from_int(x)
4615 local v = ""
4616 x = math.floor(x)
4617 if x < 0 then x = 4294967296 + x end -- ULONG_MAX+1
4618 for i = 1, 4 do
4619 local c = x % 256
4620 v = v..string.char(c); x = math.floor(x / 256)
4621 end
4622 return v
4623 end
4624
4625 --[[--------------------------------------------------------------------
4626 -- Functions to make a binary chunk
4627 -- * many functions have the size parameter removed, since output is
4628 -- in the form of a string and some sizes are implicit or hard-coded
4629 ----------------------------------------------------------------------]]
4630
4631 --[[--------------------------------------------------------------------
4632 -- struct DumpState:
4633 -- L -- lua_State (not used in this script)
4634 -- writer -- lua_Writer (chunk writer function)
4635 -- data -- void* (chunk writer context or data already written)
4636 -- strip -- if true, don't write any debug information
4637 -- status -- if non-zero, an error has occured
4638 ----------------------------------------------------------------------]]
4639
4640 ------------------------------------------------------------------------
4641 -- dumps a block of bytes
4642 -- * lua_unlock(D.L), lua_lock(D.L) unused
4643 ------------------------------------------------------------------------
4644 function luaU:DumpBlock(b, D)
4645 if D.status == 0 then
4646 -- lua_unlock(D->L);
4647 D.status = D.write(b, D.data)
4648 -- lua_lock(D->L);
4649 end
4650 end
4651
4652 ------------------------------------------------------------------------
4653 -- dumps a char
4654 ------------------------------------------------------------------------
4655 function luaU:DumpChar(y, D)
4656 self:DumpBlock(string.char(y), D)
4657 end
4658
4659 ------------------------------------------------------------------------
4660 -- dumps a 32-bit signed or unsigned integer (for int) (hard-coded)
4661 ------------------------------------------------------------------------
4662 function luaU:DumpInt(x, D)
4663 self:DumpBlock(self:from_int(x), D)
4664 end
4665
4666 ------------------------------------------------------------------------
4667 -- dumps a lua_Number (hard-coded as a double)
4668 ------------------------------------------------------------------------
4669 function luaU:DumpNumber(x, D)
4670 self:DumpBlock(self:from_double(x), D)
4671 end
4672
4673 ------------------------------------------------------------------------
4674 -- dumps a Lua string (size type is hard-coded)
4675 ------------------------------------------------------------------------
4676 function luaU:DumpString(s, D)
4677 if s == nil then
4678 self:DumpInt(0, D)
4679 else
4680 s = s.."\0" -- include trailing '\0'
4681 self:DumpInt(#s, D)
4682 self:DumpBlock(s, D)
4683 end
4684 end
4685
4686 ------------------------------------------------------------------------
4687 -- dumps instruction block from function prototype
4688 ------------------------------------------------------------------------
4689 function luaU:DumpCode(f, D)
4690 local n = f.sizecode
4691 --was DumpVector
4692 self:DumpInt(n, D)
4693 for i = 0, n - 1 do
4694 self:DumpBlock(luaP:Instruction(f.code[i]), D)
4695 end
4696 end
4697
4698 ------------------------------------------------------------------------
4699 -- dump constant pool from function prototype
4700 -- * bvalue(o), nvalue(o) and rawtsvalue(o) macros removed
4701 ------------------------------------------------------------------------
4702 function luaU:DumpConstants(f, D)
4703 local n = f.sizek
4704 self:DumpInt(n, D)
4705 for i = 0, n - 1 do
4706 local o = f.k[i] -- TValue
4707 local tt = self:ttype(o)
4708 self:DumpChar(tt, D)
4709 if tt == self.LUA_TNIL then
4710 elseif tt == self.LUA_TBOOLEAN then
4711 self:DumpChar(o.value and 1 or 0, D)
4712 elseif tt == self.LUA_TNUMBER then
4713 self:DumpNumber(o.value, D)
4714 elseif tt == self.LUA_TSTRING then
4715 self:DumpString(o.value, D)
4716 else
4717 --lua_assert(0) -- cannot happen
4718 end
4719 end
4720 n = f.sizep
4721 self:DumpInt(n, D)
4722 for i = 0, n - 1 do
4723 self:DumpFunction(f.p[i], f.source, D)
4724 end
4725 end
4726
4727 ------------------------------------------------------------------------
4728 -- dump debug information
4729 ------------------------------------------------------------------------
4730 function luaU:DumpDebug(f, D)
4731 local n
4732 n = D.strip and 0 or f.sizelineinfo -- dump line information
4733 --was DumpVector
4734 self:DumpInt(n, D)
4735 for i = 0, n - 1 do
4736 self:DumpInt(f.lineinfo[i], D)
4737 end
4738 n = D.strip and 0 or f.sizelocvars -- dump local information
4739 self:DumpInt(n, D)
4740 for i = 0, n - 1 do
4741 self:DumpString(f.locvars[i].varname, D)
4742 self:DumpInt(f.locvars[i].startpc, D)
4743 self:DumpInt(f.locvars[i].endpc, D)
4744 end
4745 n = D.strip and 0 or f.sizeupvalues -- dump upvalue information
4746 self:DumpInt(n, D)
4747 for i = 0, n - 1 do
4748 self:DumpString(f.upvalues[i], D)
4749 end
4750 end
4751
4752 ------------------------------------------------------------------------
4753 -- dump child function prototypes from function prototype
4754 ------------------------------------------------------------------------
4755 function luaU:DumpFunction(f, p, D)
4756 local source = f.source
4757 if source == p or D.strip then source = nil end
4758 self:DumpString(source, D)
4759 self:DumpInt(f.lineDefined, D)
4760 self:DumpInt(f.lastlinedefined, D)
4761 self:DumpChar(f.nups, D)
4762 self:DumpChar(f.numparams, D)
4763 self:DumpChar(f.is_vararg, D)
4764 self:DumpChar(f.maxstacksize, D)
4765 self:DumpCode(f, D)
4766 self:DumpConstants(f, D)
4767 self:DumpDebug(f, D)
4768 end
4769
4770 ------------------------------------------------------------------------
4771 -- dump Lua header section (some sizes hard-coded)
4772 ------------------------------------------------------------------------
4773 function luaU:DumpHeader(D)
4774 local h = self:header()
4775 assert(#h == self.LUAC_HEADERSIZE) -- fixed buffer now an assert
4776 self:DumpBlock(h, D)
4777 end
4778
4779 ------------------------------------------------------------------------
4780 -- make header (from lundump.c)
4781 -- returns the header string
4782 ------------------------------------------------------------------------
4783 function luaU:header()
4784 local x = 1
4785 return self.LUA_SIGNATURE..
4786 string.char(
4787 self.LUAC_VERSION,
4788 self.LUAC_FORMAT,
4789 x, -- endianness (1=little)
4790 4, -- sizeof(int)
4791 4, -- sizeof(size_t)
4792 4, -- sizeof(Instruction)
4793 8, -- sizeof(lua_Number)
4794 0) -- is lua_Number integral?
4795 end
4796
4797 ------------------------------------------------------------------------
4798 -- dump Lua function as precompiled chunk
4799 -- (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)
4800 -- * w, data are created from make_setS, make_setF
4801 ------------------------------------------------------------------------
4802 function luaU:dump(L, f, w, data, strip)
4803 local D = {} -- DumpState
4804 D.L = L
4805 D.write = w
4806 D.data = data
4807 D.strip = strip
4808 D.status = 0
4809 self:DumpHeader(D)
4810 self:DumpFunction(f, nil, D)
4811 -- added: for a chunk writer writing to a file, this final call with
4812 -- nil data is to indicate to the writer to close the file
4813 D.write(nil, D.data)
4814 return D.status
4815 end
4816
4817 return luaU
4818 end
4819 fake_module_scripts[script] = module_script
4820end
4821do -- nil.LuaP
4822 local script = Instance.new('ModuleScript', nil)
4823 script.Name = "LuaP"
4824 local function module_script()
4825 --[[--------------------------------------------------------------------
4826
4827 lopcodes.lua
4828 Lua 5 virtual machine opcodes in Lua
4829 This file is part of Yueliang.
4830
4831 Copyright (c) 2006 Kein-Hong Man <khman@users.sf.net>
4832 The COPYRIGHT file describes the conditions
4833 under which this software may be distributed.
4834
4835 See the ChangeLog for more information.
4836
4837 ----------------------------------------------------------------------]]
4838
4839 --[[--------------------------------------------------------------------
4840 -- Notes:
4841 -- * an Instruction is a table with OP, A, B, C, Bx elements; this
4842 -- makes the code easy to follow and should allow instruction handling
4843 -- to work with doubles and ints
4844 -- * WARNING luaP:Instruction outputs instructions encoded in little-
4845 -- endian form and field size and positions are hard-coded
4846 --
4847 -- Not implemented:
4848 -- *
4849 --
4850 -- Added:
4851 -- * luaP:CREATE_Inst(c): create an inst from a number (for OP_SETLIST)
4852 -- * luaP:Instruction(i): convert field elements to a 4-char string
4853 -- * luaP:DecodeInst(x): convert 4-char string into field elements
4854 --
4855 -- Changed in 5.1.x:
4856 -- * POS_OP added, instruction field positions changed
4857 -- * some symbol names may have changed, e.g. LUAI_BITSINT
4858 -- * new operators for RK indices: BITRK, ISK(x), INDEXK(r), RKASK(x)
4859 -- * OP_MOD, OP_LEN is new
4860 -- * OP_TEST is now OP_TESTSET, OP_TEST is new
4861 -- * OP_FORLOOP, OP_TFORLOOP adjusted, OP_FORPREP is new
4862 -- * OP_TFORPREP deleted
4863 -- * OP_SETLIST and OP_SETLISTO merged and extended
4864 -- * OP_VARARG is new
4865 -- * many changes to implementation of OpMode data
4866 ----------------------------------------------------------------------]]
4867
4868 local luaP = {}
4869
4870 --[[
4871 ===========================================================================
4872 We assume that instructions are unsigned numbers.
4873 All instructions have an opcode in the first 6 bits.
4874 Instructions can have the following fields:
4875 'A' : 8 bits
4876 'B' : 9 bits
4877 'C' : 9 bits
4878 'Bx' : 18 bits ('B' and 'C' together)
4879 'sBx' : signed Bx
4880
4881 A signed argument is represented in excess K; that is, the number
4882 value is the unsigned value minus K. K is exactly the maximum value
4883 for that argument (so that -max is represented by 0, and +max is
4884 represented by 2*max), which is half the maximum for the corresponding
4885 unsigned argument.
4886 ===========================================================================
4887 --]]
4888
4889 luaP.OpMode = { iABC = 0, iABx = 1, iAsBx = 2 } -- basic instruction format
4890
4891 ------------------------------------------------------------------------
4892 -- size and position of opcode arguments.
4893 -- * WARNING size and position is hard-coded elsewhere in this script
4894 ------------------------------------------------------------------------
4895 luaP.SIZE_C = 9
4896 luaP.SIZE_B = 9
4897 luaP.SIZE_Bx = luaP.SIZE_C + luaP.SIZE_B
4898 luaP.SIZE_A = 8
4899
4900 luaP.SIZE_OP = 6
4901
4902 luaP.POS_OP = 0
4903 luaP.POS_A = luaP.POS_OP + luaP.SIZE_OP
4904 luaP.POS_C = luaP.POS_A + luaP.SIZE_A
4905 luaP.POS_B = luaP.POS_C + luaP.SIZE_C
4906 luaP.POS_Bx = luaP.POS_C
4907
4908 ------------------------------------------------------------------------
4909 -- limits for opcode arguments.
4910 -- we use (signed) int to manipulate most arguments,
4911 -- so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
4912 ------------------------------------------------------------------------
4913 -- removed "#if SIZE_Bx < BITS_INT-1" test, assume this script is
4914 -- running on a Lua VM with double or int as LUA_NUMBER
4915
4916 luaP.MAXARG_Bx = math.ldexp(1, luaP.SIZE_Bx) - 1
4917 luaP.MAXARG_sBx = math.floor(luaP.MAXARG_Bx / 2) -- 'sBx' is signed
4918
4919 luaP.MAXARG_A = math.ldexp(1, luaP.SIZE_A) - 1
4920 luaP.MAXARG_B = math.ldexp(1, luaP.SIZE_B) - 1
4921 luaP.MAXARG_C = math.ldexp(1, luaP.SIZE_C) - 1
4922
4923 -- creates a mask with 'n' 1 bits at position 'p'
4924 -- MASK1(n,p) deleted, not required
4925 -- creates a mask with 'n' 0 bits at position 'p'
4926 -- MASK0(n,p) deleted, not required
4927
4928 --[[--------------------------------------------------------------------
4929 Visual representation for reference:
4930
4931 31 | | | 0 bit position
4932 +-----+-----+-----+----------+
4933 | B | C | A | Opcode | iABC format
4934 +-----+-----+-----+----------+
4935 - 9 - 9 - 8 - 6 - field sizes
4936 +-----+-----+-----+----------+
4937 | [s]Bx | A | Opcode | iABx | iAsBx format
4938 +-----+-----+-----+----------+
4939
4940 ----------------------------------------------------------------------]]
4941
4942 ------------------------------------------------------------------------
4943 -- the following macros help to manipulate instructions
4944 -- * changed to a table object representation, very clean compared to
4945 -- the [nightmare] alternatives of using a number or a string
4946 -- * Bx is a separate element from B and C, since there is never a need
4947 -- to split Bx in the parser or code generator
4948 ------------------------------------------------------------------------
4949
4950 -- these accept or return opcodes in the form of string names
4951 function luaP:GET_OPCODE(i) return self.ROpCode[i.OP] end
4952 function luaP:SET_OPCODE(i, o) i.OP = self.OpCode[o] end
4953
4954 function luaP:GETARG_A(i) return i.A end
4955 function luaP:SETARG_A(i, u) i.A = u end
4956
4957 function luaP:GETARG_B(i) return i.B end
4958 function luaP:SETARG_B(i, b) i.B = b end
4959
4960 function luaP:GETARG_C(i) return i.C end
4961 function luaP:SETARG_C(i, b) i.C = b end
4962
4963 function luaP:GETARG_Bx(i) return i.Bx end
4964 function luaP:SETARG_Bx(i, b) i.Bx = b end
4965
4966 function luaP:GETARG_sBx(i) return i.Bx - self.MAXARG_sBx end
4967 function luaP:SETARG_sBx(i, b) i.Bx = b + self.MAXARG_sBx end
4968
4969 function luaP:CREATE_ABC(o,a,b,c)
4970 return {OP = self.OpCode[o], A = a, B = b, C = c}
4971 end
4972
4973 function luaP:CREATE_ABx(o,a,bc)
4974 return {OP = self.OpCode[o], A = a, Bx = bc}
4975 end
4976
4977 ------------------------------------------------------------------------
4978 -- create an instruction from a number (for OP_SETLIST)
4979 ------------------------------------------------------------------------
4980 function luaP:CREATE_Inst(c)
4981 local o = c % 64
4982 c = (c - o) / 64
4983 local a = c % 256
4984 c = (c - a) / 256
4985 return self:CREATE_ABx(o, a, c)
4986 end
4987
4988 ------------------------------------------------------------------------
4989 -- returns a 4-char string little-endian encoded form of an instruction
4990 ------------------------------------------------------------------------
4991 function luaP:Instruction(i)
4992 if i.Bx then
4993 -- change to OP/A/B/C format
4994 i.C = i.Bx % 512
4995 i.B = (i.Bx - i.C) / 512
4996 end
4997 local I = i.A * 64 + i.OP
4998 local c0 = I % 256
4999 I = i.C * 64 + (I - c0) / 256 -- 6 bits of A left
5000 local c1 = I % 256
5001 I = i.B * 128 + (I - c1) / 256 -- 7 bits of C left
5002 local c2 = I % 256
5003 local c3 = (I - c2) / 256
5004 return string.char(c0, c1, c2, c3)
5005 end
5006
5007 ------------------------------------------------------------------------
5008 -- decodes a 4-char little-endian string into an instruction struct
5009 ------------------------------------------------------------------------
5010 function luaP:DecodeInst(x)
5011 local byte = string.byte
5012 local i = {}
5013 local I = byte(x, 1)
5014 local op = I % 64
5015 i.OP = op
5016 I = byte(x, 2) * 4 + (I - op) / 64 -- 2 bits of c0 left
5017 local a = I % 256
5018 i.A = a
5019 I = byte(x, 3) * 4 + (I - a) / 256 -- 2 bits of c1 left
5020 local c = I % 512
5021 i.C = c
5022 i.B = byte(x, 4) * 2 + (I - c) / 512 -- 1 bits of c2 left
5023 local opmode = self.OpMode[tonumber(string.sub(self.opmodes[op + 1], 7, 7))]
5024 if opmode ~= "iABC" then
5025 i.Bx = i.B * 512 + i.C
5026 end
5027 return i
5028 end
5029
5030 ------------------------------------------------------------------------
5031 -- Macros to operate RK indices
5032 -- * these use arithmetic instead of bit ops
5033 ------------------------------------------------------------------------
5034
5035 -- this bit 1 means constant (0 means register)
5036 luaP.BITRK = math.ldexp(1, luaP.SIZE_B - 1)
5037
5038 -- test whether value is a constant
5039 function luaP:ISK(x) return x >= self.BITRK end
5040
5041 -- gets the index of the constant
5042 function luaP:INDEXK(x) return x - self.BITRK end
5043
5044 luaP.MAXINDEXRK = luaP.BITRK - 1
5045
5046 -- code a constant index as a RK value
5047 function luaP:RKASK(x) return x + self.BITRK end
5048
5049 ------------------------------------------------------------------------
5050 -- invalid register that fits in 8 bits
5051 ------------------------------------------------------------------------
5052 luaP.NO_REG = luaP.MAXARG_A
5053
5054 ------------------------------------------------------------------------
5055 -- R(x) - register
5056 -- Kst(x) - constant (in constant table)
5057 -- RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
5058 ------------------------------------------------------------------------
5059
5060 ------------------------------------------------------------------------
5061 -- grep "ORDER OP" if you change these enums
5062 ------------------------------------------------------------------------
5063
5064 --[[--------------------------------------------------------------------
5065 Lua virtual machine opcodes (enum OpCode):
5066 ------------------------------------------------------------------------
5067 name args description
5068 ------------------------------------------------------------------------
5069 OP_MOVE A B R(A) := R(B)
5070 OP_LOADK A Bx R(A) := Kst(Bx)
5071 OP_LOADBOOL A B C R(A) := (Bool)B; if (C) pc++
5072 OP_LOADNIL A B R(A) := ... := R(B) := nil
5073 OP_GETUPVAL A B R(A) := UpValue[B]
5074 OP_GETGLOBAL A Bx R(A) := Gbl[Kst(Bx)]
5075 OP_GETTABLE A B C R(A) := R(B)[RK(C)]
5076 OP_SETGLOBAL A Bx Gbl[Kst(Bx)] := R(A)
5077 OP_SETUPVAL A B UpValue[B] := R(A)
5078 OP_SETTABLE A B C R(A)[RK(B)] := RK(C)
5079 OP_NEWTABLE A B C R(A) := {} (size = B,C)
5080 OP_SELF A B C R(A+1) := R(B); R(A) := R(B)[RK(C)]
5081 OP_ADD A B C R(A) := RK(B) + RK(C)
5082 OP_SUB A B C R(A) := RK(B) - RK(C)
5083 OP_MUL A B C R(A) := RK(B) * RK(C)
5084 OP_DIV A B C R(A) := RK(B) / RK(C)
5085 OP_MOD A B C R(A) := RK(B) % RK(C)
5086 OP_POW A B C R(A) := RK(B) ^ RK(C)
5087 OP_UNM A B R(A) := -R(B)
5088 OP_NOT A B R(A) := not R(B)
5089 OP_LEN A B R(A) := length of R(B)
5090 OP_CONCAT A B C R(A) := R(B).. ... ..R(C)
5091 OP_JMP sBx pc+=sBx
5092 OP_EQ A B C if ((RK(B) == RK(C)) ~= A) then pc++
5093 OP_LT A B C if ((RK(B) < RK(C)) ~= A) then pc++
5094 OP_LE A B C if ((RK(B) <= RK(C)) ~= A) then pc++
5095 OP_TEST A C if not (R(A) <=> C) then pc++
5096 OP_TESTSET A B C if (R(B) <=> C) then R(A) := R(B) else pc++
5097 OP_CALL A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1))
5098 OP_TAILCALL A B C return R(A)(R(A+1), ... ,R(A+B-1))
5099 OP_RETURN A B return R(A), ... ,R(A+B-2) (see note)
5100 OP_FORLOOP A sBx R(A)+=R(A+2);
5101 if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }
5102 OP_FORPREP A sBx R(A)-=R(A+2); pc+=sBx
5103 OP_TFORLOOP A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));
5104 if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++
5105 OP_SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
5106 OP_CLOSE A close all variables in the stack up to (>=) R(A)
5107 OP_CLOSURE A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))
5108 OP_VARARG A B R(A), R(A+1), ..., R(A+B-1) = vararg
5109 ----------------------------------------------------------------------]]
5110
5111 luaP.opnames = {} -- opcode names
5112 luaP.OpCode = {} -- lookup name -> number
5113 luaP.ROpCode = {} -- lookup number -> name
5114
5115 ------------------------------------------------------------------------
5116 -- ORDER OP
5117 ------------------------------------------------------------------------
5118 local i = 0
5119 for v in string.gmatch([[
5120 MOVE LOADK LOADBOOL LOADNIL GETUPVAL
5121 GETGLOBAL GETTABLE SETGLOBAL SETUPVAL SETTABLE
5122 NEWTABLE SELF ADD SUB MUL
5123 DIV MOD POW UNM NOT
5124 LEN CONCAT JMP EQ LT
5125 LE TEST TESTSET CALL TAILCALL
5126 RETURN FORLOOP FORPREP TFORLOOP SETLIST
5127 CLOSE CLOSURE VARARG
5128 ]], "%S+") do
5129 local n = "OP_"..v
5130 luaP.opnames[i] = v
5131 luaP.OpCode[n] = i
5132 luaP.ROpCode[i] = n
5133 i = i + 1
5134 end
5135 luaP.NUM_OPCODES = i
5136
5137 --[[
5138 ===========================================================================
5139 Notes:
5140 (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
5141 and can be 0: OP_CALL then sets 'top' to last_result+1, so
5142 next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use 'top'.
5143 (*) In OP_VARARG, if (B == 0) then use actual number of varargs and
5144 set top (like in OP_CALL with C == 0).
5145 (*) In OP_RETURN, if (B == 0) then return up to 'top'
5146 (*) In OP_SETLIST, if (B == 0) then B = 'top';
5147 if (C == 0) then next 'instruction' is real C
5148 (*) For comparisons, A specifies what condition the test should accept
5149 (true or false).
5150 (*) All 'skips' (pc++) assume that next instruction is a jump
5151 ===========================================================================
5152 --]]
5153
5154 --[[--------------------------------------------------------------------
5155 masks for instruction properties. The format is:
5156 bits 0-1: op mode
5157 bits 2-3: C arg mode
5158 bits 4-5: B arg mode
5159 bit 6: instruction set register A
5160 bit 7: operator is a test
5161
5162 for OpArgMask:
5163 OpArgN - argument is not used
5164 OpArgU - argument is used
5165 OpArgR - argument is a register or a jump offset
5166 OpArgK - argument is a constant or register/constant
5167 ----------------------------------------------------------------------]]
5168
5169 -- was enum OpArgMask
5170 luaP.OpArgMask = { OpArgN = 0, OpArgU = 1, OpArgR = 2, OpArgK = 3 }
5171
5172 ------------------------------------------------------------------------
5173 -- e.g. to compare with symbols, luaP:getOpMode(...) == luaP.OpCode.iABC
5174 -- * accepts opcode parameter as strings, e.g. "OP_MOVE"
5175 ------------------------------------------------------------------------
5176
5177 function luaP:getOpMode(m)
5178 return self.opmodes[self.OpCode[m]] % 4
5179 end
5180
5181 function luaP:getBMode(m)
5182 return math.floor(self.opmodes[self.OpCode[m]] / 16) % 4
5183 end
5184
5185 function luaP:getCMode(m)
5186 return math.floor(self.opmodes[self.OpCode[m]] / 4) % 4
5187 end
5188
5189 function luaP:testAMode(m)
5190 return math.floor(self.opmodes[self.OpCode[m]] / 64) % 2
5191 end
5192
5193 function luaP:testTMode(m)
5194 return math.floor(self.opmodes[self.OpCode[m]] / 128)
5195 end
5196
5197 -- luaP_opnames[] is set above, as the luaP.opnames table
5198
5199 -- number of list items to accumulate before a SETLIST instruction
5200 luaP.LFIELDS_PER_FLUSH = 50
5201
5202 ------------------------------------------------------------------------
5203 -- build instruction properties array
5204 -- * deliberately coded to look like the C equivalent
5205 ------------------------------------------------------------------------
5206 local function opmode(t, a, b, c, m)
5207 local luaP = luaP
5208 return t * 128 + a * 64 +
5209 luaP.OpArgMask[b] * 16 + luaP.OpArgMask[c] * 4 + luaP.OpMode[m]
5210 end
5211
5212 -- ORDER OP
5213 luaP.opmodes = {
5214 -- T A B C mode opcode
5215 opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_LOADK
5216 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_LOADBOOL
5217 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LOADNIL
5218 opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_GETUPVAL
5219 opmode(0, 1, "OpArgK", "OpArgN", "iABx"), -- OP_GETGLOBAL
5220 opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_GETTABLE
5221 opmode(0, 0, "OpArgK", "OpArgN", "iABx"), -- OP_SETGLOBAL
5222 opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_SETUPVAL
5223 opmode(0, 0, "OpArgK", "OpArgK", "iABC"), -- OP_SETTABLE
5224 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_NEWTABLE
5225 opmode(0, 1, "OpArgR", "OpArgK", "iABC"), -- OP_SELF
5226 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_ADD
5227 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_SUB
5228 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MUL
5229 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_DIV
5230 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_MOD
5231 opmode(0, 1, "OpArgK", "OpArgK", "iABC"), -- OP_POW
5232 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_UNM
5233 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_NOT
5234 opmode(0, 1, "OpArgR", "OpArgN", "iABC"), -- OP_LEN
5235 opmode(0, 1, "OpArgR", "OpArgR", "iABC"), -- OP_CONCAT
5236 opmode(0, 0, "OpArgR", "OpArgN", "iAsBx"), -- OP_JMP
5237 opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_EQ
5238 opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LT
5239 opmode(1, 0, "OpArgK", "OpArgK", "iABC"), -- OP_LE
5240 opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TEST
5241 opmode(1, 1, "OpArgR", "OpArgU", "iABC"), -- OP_TESTSET
5242 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_CALL
5243 opmode(0, 1, "OpArgU", "OpArgU", "iABC"), -- OP_TAILCALL
5244 opmode(0, 0, "OpArgU", "OpArgN", "iABC"), -- OP_RETURN
5245 opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORLOOP
5246 opmode(0, 1, "OpArgR", "OpArgN", "iAsBx"), -- OP_FORPREP
5247 opmode(1, 0, "OpArgN", "OpArgU", "iABC"), -- OP_TFORLOOP
5248 opmode(0, 0, "OpArgU", "OpArgU", "iABC"), -- OP_SETLIST
5249 opmode(0, 0, "OpArgN", "OpArgN", "iABC"), -- OP_CLOSE
5250 opmode(0, 1, "OpArgU", "OpArgN", "iABx"), -- OP_CLOSURE
5251 opmode(0, 1, "OpArgU", "OpArgN", "iABC"), -- OP_VARARG
5252 }
5253 -- an awkward way to set a zero-indexed table...
5254 luaP.opmodes[0] =
5255 opmode(0, 1, "OpArgR", "OpArgN", "iABC") -- OP_MOVE
5256
5257 return luaP
5258 end
5259 fake_module_scripts[script] = module_script
5260end
5261do -- nil.Rerubi
5262 local script = Instance.new('ModuleScript', nil)
5263 script.Name = "Rerubi"
5264 local function module_script()
5265 local Concat = table.concat;
5266 local Select = select;
5267 local _Byte = string.byte;
5268 local Sub = string.sub;
5269 local Opcode = { -- Opcode types.
5270 'ABC', 'ABx', 'ABC', 'ABC';
5271 'ABC', 'ABx', 'ABC', 'ABx';
5272 'ABC', 'ABC', 'ABC', 'ABC';
5273 'ABC', 'ABC', 'ABC', 'ABC';
5274 'ABC', 'ABC', 'ABC', 'ABC';
5275 'ABC', 'ABC', 'AsBx', 'ABC';
5276 'ABC', 'ABC', 'ABC', 'ABC';
5277 'ABC', 'ABC', 'ABC', 'AsBx';
5278 'AsBx', 'ABC', 'ABC', 'ABC';
5279 'ABx', 'ABC';
5280 };
5281
5282 -- rlbi author -> Rerumu
5283
5284 --[[
5285 Features;
5286 * Almost complete rework/rewrite
5287 * Fast and performant
5288 * Fixes to upvalues
5289 * C Stack overflow fixes in opcodes
5290 * Fixed missing/broken returns
5291 * Numeric constant 0 is properly handled
5292 * Formatted in a more readable manner
5293 * Tailcalls and stack issues have been fixed
5294 * CLOSE implemented
5295 * SETLIST (extended) implemented
5296 * VARARG fixes
5297 --]]
5298
5299 local function gBit(Bit, Start, End) -- No tail-calls, yay.
5300 if End then -- Thanks to cntkillme for giving input on this shorter, better approach.
5301 local Res = (Bit / 2 ^ (Start - 1)) % 2 ^ ((End - 1) - (Start - 1) + 1);
5302
5303 return Res - Res % 1;
5304 else
5305 local Plc = 2 ^ (Start - 1);
5306
5307 if (Bit % (Plc + Plc) >= Plc) then
5308 return 1;
5309 else
5310 return 0;
5311 end;
5312 end;
5313 end;
5314
5315 local function GetMeaning(ByteString)
5316 local Pos = 1;
5317 local gSizet;
5318 local gInt;
5319
5320 local function gBits8() -- Get the next byte in the stream.
5321 local F = _Byte(ByteString, Pos, Pos);
5322
5323 Pos = Pos + 1;
5324
5325 return F;
5326 end;
5327
5328 local function gBits32()
5329 local W, X, Y, Z = _Byte(ByteString, Pos, Pos + 3);
5330
5331 Pos = Pos + 4;
5332
5333 return (Z * 16777216) + (Y * 65536) + (X * 256) + W;
5334 end;
5335
5336 local function gBits64()
5337 return gBits32() * 4294967296 + gBits32();
5338 end;
5339
5340 local function gFloat()
5341 local A, B = gBits32(), gBits32();
5342
5343 if ((A + B) == 0) then
5344 return 0; -- Float 0 tends to be very messy, so this is a temp fix until I figure out what's up.
5345 else
5346 return (-2 * gBit(B, 32) + 1) * (2 ^ (gBit(B, 21, 31) - 1023)) * ((gBit(B, 1, 20) * (2^32) + A) / (2 ^ 52) + 1);
5347 end;
5348 end;
5349
5350 local function gString(Len)
5351 local Str;
5352
5353 if Len then
5354 Str = Sub(ByteString, Pos, Pos + Len - 1);
5355
5356 Pos = Pos + Len;
5357 else
5358 Len = gSizet();
5359
5360 if (Len == 0) then return; end;
5361
5362 Str = Sub(ByteString, Pos, Pos + Len - 1);
5363
5364 Pos = Pos + Len;
5365 end;
5366
5367 return Str;
5368 end;
5369
5370 local function ChunkDecode()
5371 local Instr = {};
5372 local Const = {};
5373 local Proto = {};
5374 local Chunk = {
5375 Instr = Instr; -- Instructions
5376 Const = Const; -- Constants
5377 Proto = Proto; -- Prototypes
5378 Lines = {}; -- Lines
5379 Name = gString(); -- Grab name string.
5380 FirstL = gInt(); -- First line.
5381 LastL = gInt(); -- Last line.
5382 Upvals = gBits8(); -- Upvalue count.
5383 Args = gBits8(); -- Arg count.
5384 Vargs = gBits8(); -- Vararg type.
5385 Stack = gBits8(); -- Stack.
5386 };
5387
5388 if Chunk.Name then
5389 Chunk.Name = Sub(Chunk.Name, 1, -2);
5390 end;
5391
5392 for Idx = 1, gInt() do -- Loading instructions to the chunk.
5393 local Data = gBits32();
5394 local Opco = gBit(Data, 1, 6);
5395 local Type = Opcode[Opco + 1];
5396 local Inst;
5397
5398 if Type then
5399 Inst = {
5400 Enum = Opco;
5401 gBit(Data, 7, 14); -- Register A.
5402 };
5403
5404 if (Type == 'ABC') then -- Most common, basic instruction type.
5405 Inst[2] = gBit(Data, 24, 32);
5406 Inst[3] = gBit(Data, 15, 23);
5407 elseif (Type == 'ABx') then
5408 Inst[2] = gBit(Data, 15, 32);
5409 elseif (Type == 'AsBx') then
5410 Inst[2] = gBit(Data, 15, 32) - 131071;
5411 end;
5412 else
5413 Inst = Data; -- Extended SETLIST
5414 end;
5415
5416 Instr[Idx] = Inst;
5417 end;
5418
5419 for Idx = 1, gInt() do -- Load constants.
5420 local Type = gBits8();
5421 local Cons;
5422
5423 if (Type == 1) then -- Boolean
5424 Cons = (gBits8() ~= 0);
5425 elseif (Type == 3) then -- Float/Double
5426 Cons = gFloat();
5427 elseif (Type == 4) then
5428 Cons = Sub(gString(), 1, -2);
5429 end;
5430
5431 Const[Idx - 1] = Cons;
5432 end;
5433
5434 for Idx = 1, gInt() do -- Nested function prototypes.
5435 Proto[Idx - 1] = ChunkDecode();
5436 end;
5437
5438 do -- Debugging
5439 local Lines = Chunk.Lines;
5440
5441 for Idx = 1, gInt() do
5442 Lines[Idx] = gBits32();
5443 end;
5444
5445 for Idx = 1, gInt() do -- Locals in stack.
5446 gString(); -- Name of local.
5447 gBits32(); -- Starting point.
5448 gBits32(); -- End point.
5449 end;
5450
5451 for Idx = 1, gInt() do -- Upvalues.
5452 gString(); -- Name of upvalue.
5453 end;
5454 end;
5455
5456 return Chunk; -- Finished chunk.
5457 end;
5458
5459 do -- Most of this chunk I was too lazy to reformat or change
5460 assert(gString(4) == "\27Lua", "Lua bytecode expected.");
5461 assert(gBits8() == 0x51, "Only Lua 5.1 is supported.");
5462
5463 gBits8(); -- Probably version control.
5464 gBits8(); -- Is small endians.
5465
5466 local IntSize = gBits8(); -- Int size
5467 local Sizet = gBits8(); -- size_t
5468
5469 if (IntSize == 4) then
5470 gInt = gBits32;
5471 elseif (IntSize == 8) then
5472 gInt = gBits64;
5473 else
5474 error('Integer size not supported', 2);
5475 end;
5476
5477 if (Sizet == 4) then
5478 gSizet = gBits32;
5479 elseif (Sizet == 8) then
5480 gSizet = gBits64;
5481 else
5482 error('Sizet size not supported', 2);
5483 end;
5484
5485 assert(gString(3) == "\4\8\0", "Unsupported bytecode target platform");
5486 end;
5487
5488 return ChunkDecode();
5489 end;
5490
5491 local function _Returns(...)
5492 return Select('#', ...), {...};
5493 end;
5494
5495 local function Wrap(Chunk, Env, Upvalues)
5496 local Instr = Chunk.Instr;
5497 local Const = Chunk.Const;
5498 local Proto = Chunk.Proto;
5499
5500 local function OnError(Err, Position) -- Handle your errors in whatever way.
5501 local Name = Chunk.Name or 'Code';
5502 local Line = Chunk.Lines[Position] or '?';
5503 local Err = Err:match'^.+:%s*(.+)' or Err;
5504
5505 error(string.format('%s (%s): %s', Name, Line, Err), 0);
5506 end;
5507
5508 return function(...) -- Returned function to run bytecode chunk (Don't be stupid, you can't setfenv this to work your way).
5509 local Upvalues = Upvalues;
5510 local Instr = Instr;
5511 local Const = Const;
5512 local Proto = Proto;
5513
5514 local InstrPoint, Top = 1, -1;
5515 local Vararg, Varargsz = {}, Select('#', ...) - 1;
5516
5517 local GStack = {};
5518 local Lupvals = {};
5519 local Stack = setmetatable({}, {
5520 __index = GStack;
5521 __newindex = function(_, Key, Value)
5522 if (Key > Top) and Value then
5523 Top = Key;
5524 end;
5525
5526 GStack[Key] = Value;
5527 end;
5528 });
5529
5530 local function Loop()
5531 local Instr = Instr;
5532 local Inst, Enum, A, B;
5533
5534 while true do
5535 Inst = Instr[InstrPoint];
5536 Enum = Inst.Enum;
5537 InstrPoint = InstrPoint + 1;
5538
5539 if (Enum == 0) then -- MOVE
5540 Stack[Inst[1]] = Stack[Inst[2]];
5541 elseif (Enum == 1) then -- LOADK
5542 Stack[Inst[1]] = Const[Inst[2]];
5543 elseif (Enum == 2) then -- LOADBOOL
5544 Stack[Inst[1]] = (Inst[2] ~= 0);
5545
5546 if (Inst[3] ~= 0) then
5547 InstrPoint = InstrPoint + 1;
5548 end;
5549 elseif (Enum == 3) then -- LOADNIL
5550 local Stk = Stack;
5551
5552 for Idx = Inst[1], Inst[2] do
5553 Stk[Idx] = nil;
5554 end;
5555 elseif (Enum == 4) then -- GETUPVAL
5556 Stack[Inst[1]] = Upvalues[Inst[2]];
5557 elseif (Enum == 5) then -- GETGLOBAL
5558 Stack[Inst[1]] = Env[Const[Inst[2]]];
5559 elseif (Enum == 6) then -- GETTABLE
5560 local C = Inst[3];
5561 local Stk = Stack;
5562
5563 if (C > 255) then
5564 C = Const[C - 256];
5565 else
5566 C = Stk[C];
5567 end;
5568
5569 Stk[Inst[1]] = Stk[Inst[2]][C];
5570 elseif (Enum == 7) then -- SETGLOBAL
5571 Env[Const[Inst[2]]] = Stack[Inst[1]];
5572 elseif (Enum == 8) then -- SETUPVAL
5573 Upvalues[Inst[2]] = Stack[Inst[1]];
5574 elseif (Enum == 9) then -- SETTABLE
5575 local B, C = Inst[2], Inst[3];
5576 local Stk = Stack;
5577
5578 if (B > 255) then
5579 B = Const[B - 256];
5580 else
5581 B = Stk[B];
5582 end;
5583
5584 if (C > 255) then
5585 C = Const[C - 256];
5586 else
5587 C = Stk[C];
5588 end;
5589
5590 Stk[Inst[1]][B] = C;
5591 elseif (Enum == 10) then -- NEWTABLE
5592 Stack[Inst[1]] = {};
5593 elseif (Enum == 11) then -- SELF
5594 local A = Inst[1];
5595 local B = Inst[2];
5596 local C = Inst[3];
5597 local Stk = Stack;
5598
5599 B = Stk[B];
5600
5601 if (C > 255) then
5602 C = Const[C - 256];
5603 else
5604 C = Stk[C];
5605 end;
5606
5607 Stk[A + 1] = B;
5608 Stk[A] = B[C];
5609 elseif (Enum == 12) then -- ADD
5610 local B = Inst[2];
5611 local C = Inst[3];
5612 local Stk, Con = Stack, Const;
5613
5614 if (B > 255) then
5615 B = Const[B - 256];
5616 else
5617 B = Stk[B];
5618 end;
5619
5620 if (C > 255) then
5621 C = Const[C - 256];
5622 else
5623 C = Stk[C];
5624 end;
5625
5626 Stk[Inst[1]] = B + C;
5627 elseif (Enum == 13) then -- SUB
5628 local B = Inst[2];
5629 local C = Inst[3];
5630 local Stk, Con = Stack, Const;
5631
5632 if (B > 255) then
5633 B = Const[B - 256];
5634 else
5635 B = Stk[B];
5636 end;
5637
5638 if (C > 255) then
5639 C = Const[C - 256];
5640 else
5641 C = Stk[C];
5642 end;
5643
5644 Stk[Inst[1]] = B - C;
5645 elseif (Enum == 14) then -- MUL
5646 local B = Inst[2];
5647 local C = Inst[3];
5648 local Stk, Con = Stack, Const;
5649
5650 if (B > 255) then
5651 B = Const[B - 256];
5652 else
5653 B = Stk[B];
5654 end;
5655
5656 if (C > 255) then
5657 C = Const[C - 256];
5658 else
5659 C = Stk[C];
5660 end;
5661
5662 Stk[Inst[1]] = B * C;
5663 elseif (Enum == 15) then -- DIV
5664 local B = Inst[2];
5665 local C = Inst[3];
5666 local Stk, Con = Stack, Const;
5667
5668 if (B > 255) then
5669 B = Const[B - 256];
5670 else
5671 B = Stk[B];
5672 end;
5673
5674 if (C > 255) then
5675 C = Const[C - 256];
5676 else
5677 C = Stk[C];
5678 end;
5679
5680 Stk[Inst[1]] = B / C;
5681 elseif (Enum == 16) then -- MOD
5682 local B = Inst[2];
5683 local C = Inst[3];
5684 local Stk, Con = Stack, Const;
5685
5686 if (B > 255) then
5687 B = Const[B - 256];
5688 else
5689 B = Stk[B];
5690 end;
5691
5692 if (C > 255) then
5693 C = Const[C - 256];
5694 else
5695 C = Stk[C];
5696 end;
5697
5698 Stk[Inst[1]] = B % C;
5699 elseif (Enum == 17) then -- POW
5700 local B = Inst[2];
5701 local C = Inst[3];
5702 local Stk, Con = Stack, Const;
5703
5704 if (B > 255) then
5705 B = Const[B - 256];
5706 else
5707 B = Stk[B];
5708 end;
5709
5710 if (C > 255) then
5711 C = Const[C - 256];
5712 else
5713 C = Stk[C];
5714 end;
5715
5716 Stk[Inst[1]] = B ^ C;
5717 elseif (Enum == 18) then -- UNM
5718 Stack[Inst[1]] = -Stack[Inst[2]];
5719 elseif (Enum == 19) then -- NOT
5720 Stack[Inst[1]] = (not Stack[Inst[2]]);
5721 elseif (Enum == 20) then -- LEN
5722 Stack[Inst[1]] = #Stack[Inst[2]];
5723 elseif (Enum == 21) then -- CONCAT
5724 local Stk = Stack;
5725 local B = Inst[2];
5726 local K = {Stack[B]};
5727
5728 for Idx = B + 1, Inst[3] do
5729 K[#K + 1] = Stk[Idx];
5730 end;
5731
5732 Stack[Inst[1]] = Concat(K);
5733 elseif (Enum == 22) then -- JUMP
5734 InstrPoint = InstrPoint + Inst[2];
5735 elseif (Enum == 23) then -- EQ
5736 local A = Inst[1] ~= 0;
5737 local B = Inst[2];
5738 local C = Inst[3];
5739 local Stk, Con = Stack, Const;
5740
5741 if (B > 255) then
5742 B = Const[B - 256];
5743 else
5744 B = Stk[B];
5745 end;
5746
5747 if (C > 255) then
5748 C = Const[C - 256];
5749 else
5750 C = Stk[C];
5751 end;
5752
5753 if (B == C) ~= A then
5754 InstrPoint = InstrPoint + 1;
5755 end;
5756 elseif (Enum == 24) then -- LT
5757 local A = Inst[1] ~= 0;
5758 local B = Inst[2];
5759 local C = Inst[3];
5760 local Stk, Con = Stack, Const;
5761
5762 if (B > 255) then
5763 B = Const[B - 256];
5764 else
5765 B = Stk[B];
5766 end;
5767
5768 if (C > 255) then
5769 C = Const[C - 256];
5770 else
5771 C = Stk[C];
5772 end;
5773
5774 if (B < C) ~= A then
5775 InstrPoint = InstrPoint + 1;
5776 end;
5777 elseif (Enum == 25) then -- LE
5778 local A = Inst[1] ~= 0;
5779 local B = Inst[2];
5780 local C = Inst[3];
5781 local Stk, Con = Stack, Const;
5782
5783 if (B > 255) then
5784 B = Const[B - 256];
5785 else
5786 B = Stk[B];
5787 end;
5788
5789 if (C > 255) then
5790 C = Const[C - 256];
5791 else
5792 C = Stk[C];
5793 end;
5794
5795 if (B <= C) ~= A then
5796 InstrPoint = InstrPoint + 1;
5797 end;
5798 elseif (Enum == 26) then -- TEST
5799 if (not not Stack[Inst[1]]) == (Inst[3] == 0) then
5800 InstrPoint = InstrPoint + 1;
5801 end;
5802 elseif (Enum == 27) then -- TESTSET
5803 local B = Stack[Inst[2]];
5804
5805 if (not not B) == (Inst[3] == 0) then
5806 InstrPoint = InstrPoint + 1;
5807 else
5808 Stack[Inst[1]] = B;
5809 end;
5810 elseif (Enum == 28) then -- CALL
5811 local A = Inst[1];
5812 local B = Inst[2];
5813 local C = Inst[3];
5814 local Stk = Stack;
5815 local Args, Results;
5816 local Limit, Loop;
5817
5818 Args = {};
5819
5820 if (B ~= 1) then
5821 if (B ~= 0) then
5822 Limit = A + B - 1;
5823 else
5824 Limit = Top;
5825 end;
5826
5827 Loop = 0;
5828
5829 for Idx = A + 1, Limit do
5830 Loop = Loop + 1;
5831
5832 Args[Loop] = Stk[Idx];
5833 end;
5834
5835 Limit, Results = _Returns(Stk[A](unpack(Args, 1, Limit - A)));
5836 else
5837 Limit, Results = _Returns(Stk[A]());
5838 end;
5839
5840 Top = A - 1;
5841
5842 if (C ~= 1) then
5843 if (C ~= 0) then
5844 Limit = A + C - 2;
5845 else
5846 Limit = Limit + A;
5847 end;
5848
5849 Loop = 0;
5850
5851 for Idx = A, Limit do
5852 Loop = Loop + 1;
5853
5854 Stk[Idx] = Results[Loop];
5855 end;
5856 end;
5857 elseif (Enum == 29) then -- TAILCALL
5858 local A = Inst[1];
5859 local B = Inst[2];
5860 local C = Inst[3];
5861 local Stk = Stack;
5862 local Args, Results;
5863 local Limit, Loop;
5864
5865 Args = {};
5866
5867 if (B ~= 1) then
5868 if (B ~= 0) then
5869 Limit = A + B - 1;
5870 else
5871 Limit = Top;
5872 end
5873
5874 Loop = 0;
5875
5876 for Idx = A + 1, Limit do
5877 Loop = Loop + 1;
5878
5879 Args[#Args + 1] = Stk[Idx];
5880 end
5881
5882 Results = {Stk[A](unpack(Args, 1, Limit - A))};
5883 else
5884 Results = {Stk[A]()};
5885 end;
5886
5887 return Results;
5888 elseif (Enum == 30) then -- RETURN
5889 local A = Inst[1];
5890 local B = Inst[2];
5891 local Stk = Stack;
5892 local Loop, Output;
5893 local Limit;
5894
5895 if (B == 1) then
5896 return;
5897 elseif (B == 0) then
5898 Limit = Top;
5899 else
5900 Limit = A + B - 2;
5901 end;
5902
5903 Output = {};
5904
5905 local Loop = 0;
5906
5907 for Idx = A, Limit do
5908 Loop = Loop + 1;
5909
5910 Output[Loop] = Stk[Idx];
5911 end;
5912
5913 return Output;
5914 elseif (Enum == 31) then -- FORLOOP
5915 local A = Inst[1];
5916 local Stk = Stack;
5917
5918 local Step = Stk[A + 2];
5919 local Index = Stk[A] + Step;
5920
5921 Stk[A] = Index;
5922
5923 if (Step > 0) then
5924 if Index <= Stk[A + 1] then
5925 InstrPoint = InstrPoint + Inst[2];
5926
5927 Stk[A + 3] = Index;
5928 end;
5929 else
5930 if Index >= Stk[A + 1] then
5931 InstrPoint = InstrPoint + Inst[2];
5932
5933 Stk[A + 3] = Index;
5934 end
5935 end
5936 elseif (Enum == 32) then -- FORPREP
5937 local A = Inst[1];
5938 local Stk = Stack;
5939
5940 Stk[A] = Stk[A] - Stk[A + 2];
5941
5942 InstrPoint = InstrPoint + Inst[2];
5943 elseif (Enum == 33) then -- TFORLOOP
5944 local A = Inst[1];
5945 local B = Inst[2];
5946 local C = Inst[3];
5947 local Stk = Stack;
5948
5949 local Offset = A + 2;
5950 local Result = {Stk[A](Stk[A + 1], Stk[A + 2])};
5951
5952 for Idx = 1, C do
5953 Stack[Offset + Idx] = Result[Idx];
5954 end;
5955
5956 if (Stk[A + 3] ~= nil) then
5957 Stk[A + 2] = Stk[A + 3];
5958 else
5959 InstrPoint = InstrPoint + 1;
5960 end;
5961 elseif (Enum == 34) then -- SETLIST
5962 local A = Inst[1];
5963 local B = Inst[2];
5964 local C = Inst[3];
5965 local Stk = Stack;
5966
5967 if (C == 0) then
5968 InstrPoint = InstrPoint + 1;
5969 C = Instr[InstrPoint]; -- This implementation was ambiguous! Will eventually re-test.
5970 end;
5971
5972 local Offset = (C - 1) * 50;
5973 local T = Stk[A]; -- Assuming T is the newly created table.
5974
5975 if (B == 0) then
5976 B = Top;
5977 end;
5978
5979 for Idx = 1, B do
5980 T[Offset + Idx] = Stk[A + Idx];
5981 end;
5982 elseif (Enum == 35) then -- CLOSE
5983 local A = Inst[1];
5984 local Cls = {}; -- Slight doubts on any issues this may cause
5985
5986 for Idx = 1, #Lupvals do
5987 local List = Lupvals[Idx];
5988
5989 for Idz = 0, #List do
5990 local Upv = List[Idz];
5991 local Stk = Upv[1];
5992 local Pos = Upv[2];
5993
5994 if (Stk == Stack) and (Pos >= A) then
5995 Cls[Pos] = Stk[Pos];
5996 Upv[1] = Cls; -- @memcorrupt credit me for the spoonfeed
5997 end;
5998 end;
5999 end;
6000 elseif (Enum == 36) then -- CLOSURE
6001 local Proto = Proto[Inst[2]];
6002 local Instr = Instr;
6003 local Stk = Stack;
6004
6005 local Indexes;
6006 local NewUvals;
6007
6008 if (Proto.Upvals ~= 0) then
6009 Indexes = {};
6010 NewUvals = setmetatable({}, {
6011 __index = function(_, Key)
6012 local Val = Indexes[Key];
6013
6014 return Val[1][Val[2]];
6015 end,
6016 __newindex = function(_, Key, Value)
6017 local Val = Indexes[Key];
6018
6019 Val[1][Val[2]] = Value;
6020 end;
6021 }
6022 );
6023
6024 for Idx = 1, Proto.Upvals do
6025 local Mvm = Instr[InstrPoint];
6026
6027 if (Mvm.Enum == 0) then -- MOVE
6028 Indexes[Idx - 1] = {Stk, Mvm[2]};
6029 elseif (Mvm.Enum == 4) then -- GETUPVAL
6030 Indexes[Idx - 1] = {Upvalues, Mvm[2]};
6031 end;
6032
6033 InstrPoint = InstrPoint + 1;
6034 end;
6035
6036 Lupvals[#Lupvals + 1] = Indexes;
6037 end;
6038
6039 Stk[Inst[1]] = Wrap(Proto, Env, NewUvals);
6040 elseif (Enum == 37) then -- VARARG
6041 local A = Inst[1];
6042 local B = Inst[2];
6043 local Stk, Vararg = Stack, Vararg;
6044
6045 for Idx = A, A + (B > 0 and B - 1 or Varargsz) do
6046 Stk[Idx] = Vararg[Idx - A];
6047 end;
6048 end;
6049 end;
6050 end;
6051
6052 local Args = {...};
6053
6054 for Idx = 0, Varargsz do
6055 Stack[Idx] = Args[Idx + 1];
6056
6057 if (Idx >= Chunk.Args) then
6058 Vararg[Idx - Chunk.Args] = Args[Idx + 1];
6059 end;
6060 end;
6061
6062 local A, B = pcall(Loop); -- Pcalling to allow yielding
6063
6064 if A then -- We're always expecting this to come out true (because errorless code)
6065 if B then -- So I flipped the conditions.
6066 return unpack(B);
6067 end;
6068
6069 return;
6070 else
6071 OnError(B, InstrPoint - 1); -- Didn't get time to test the `-1` honestly, but I assume it works properly
6072 end;
6073 end;
6074 end;
6075
6076 return function(BCode, Env) -- lua_function LoadBytecode (string BCode, table Env)
6077 local Buffer = GetMeaning(BCode);
6078
6079 return Wrap(Buffer, Env or getfenv(0)), Buffer;
6080 end;
6081 end
6082 fake_module_scripts[script] = module_script
6083end
6084
6085
6086-- Scripts:
6087local gay = Instance.new("RemoteEvent",ExecuteButton)
6088local function KVBS_fake_script() -- ExecuteButton.Script
6089 local script = Instance.new('Script', ExecuteButton)
6090 local req = require
6091 local require = function(obj)
6092 local fake = fake_module_scripts[obj]
6093 if fake then
6094 return fake()
6095 end
6096 return req(obj)
6097 end
6098
6099 local remote = gay -- your remote ebicgamermolment
6100
6101 remote.OnServerEvent:Connect(function(idk, lol) -- function for your executor
6102 require(script.Loadstring)(lol)() -- this code so it actally executes requires and things
6103 end)-- end) meaning this is the end of the script return function
6104end
6105coroutine.wrap(KVBS_fake_script)()
6106local function BORXUZ_fake_script() -- ExecuteButton.LocalScript
6107 local script = Instance.new('LocalScript', ExecuteButton)
6108 local req = require
6109 local require = function(obj)
6110 local fake = fake_module_scripts[obj]
6111 if fake then
6112 return fake()
6113 end
6114 return req(obj)
6115 end
6116
6117 local execute = ExecuteButton
6118 local text = Box
6119 local remote = gay
6120
6121 execute.MouseButton1Click:Connect(function()
6122 remote:FireServer(text.Text)
6123 end)
6124end
6125coroutine.wrap(BORXUZ_fake_script)()
6126 end
6127
6128 ClearButton.MouseButton1Click:Connect(function()
6129 Box_3.Text = ""
6130 end)
6131 Container_2.Size = Container_2.Size + UDim2.new(0,0,0,Execute.Size.Y.Offset+5)
6132 end
6133 Container.MouseEnter:Connect(function()
6134 if Underline.Size ~= UDim2.new(1,0,0,4) then
6135 Underline:TweenSizeAndPosition(UDim2.new(1,0,0,4),UDim2.new(0,0,0.95,0),"Out","Sine",0.75,false,nil)
6136 wait(0.75)
6137 else
6138 Underline:TweenSizeAndPosition(UDim2.new(0,0,0,4),UDim2.new(0.5,0,0.95,0),"In","Sine",0.75,false,nil)
6139 wait(0.75)
6140 end
6141 end)
6142 local size = 0
6143 Container.MouseEnter:Connect(function()
6144 if Container_2.Size ~= UDim2.new(0,0,0,40) then
6145 size = Container_2.Size.Y.Offset
6146 Container_2:TweenSize(UDim2.new(0,0,0,40),"In","Sine",0.75,false,nil)
6147 wait(0.75)
6148 else
6149 Container_2:TweenSize(UDim2.new(0,240,0,size),"Out","Sine",0.75,false,nil)
6150 wait(0.75)
6151 end
6152 end)
6153 return Tourmaline;
6154end
6155
6156return Library;