Forum

> > CS2D > Scripts > Overloading CS2D functions
Forums overviewCS2D overview Scripts overviewLog in to reply

English Overloading CS2D functions

7 replies
To the start Previous 1 Next To the start

old Overloading CS2D functions

Blighted Song
User Off Offline

Quote
In writing some code recently I came to a point where adding some overloads to my function would be beneficial.

Does anyone know whether you can use overloads in CS2D functions, and of course if you do, how so.

Its not vitally important that I use overloads, as all it is doing is removeing unused variables, but it would be nice.

old Re: Overloading CS2D functions

Apache uwu
User Off Offline

Quote
Is this close to what you are thinking of?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function spawnPlayer(...)
	funcs={
		function(id)
			parse("spawnplayer "..id.." 32 32")
		end,
		function(id,x)
			parse("spawnplayer "..id.." "..x.." "..math.ceil(math.random()))
		end,
		function(id,x,y)
			parse("spawnplayer "..id.." "..x.." "..y)
		end
	}
	funcs[#arg](unpack(arg))
end

spawnPlayer(1) --> Spawn player 1 @ x:32|y:32
spawnPlayer(1,64) --> Spawn player 1 @ x:64|y:random
spawnPlayer(1,64,128) --> Spawn player 1 @ x:64|y:128

old Re: Overloading CS2D functions

omg
User Off Offline

Quote
every programming language ive come across has the ability to do this, so i wouldnt be surprized if lua has this ability, although i havent tried it yet

old Re: Overloading CS2D functions

Apache uwu
User Off Offline

Quote
Maybe. However if it involves using the debug library then it's not worth it.

imo I think it's not possible because:

1
2
3
function a()
	print(1)
end

is the exact same as:

1
2
3
a=function()
	print(1)
end

So you can't declare twice of the same variable name.

old Re: Overloading CS2D functions

Lee
Moderator Off Offline

Quote
Uh uh, no overloading for lua, for one it's ambiguous which of the following functions is called by f(x)

1
2
3
4
5
6
7
function f(x, y)
	return math.sqrt(x^2 + y^2)
end

function f(x, y, z)
	return math.sqrt(x^2 + y^2 + z^2)
end

However, there's a hackaround if we resolve the above issue. If we arbitrarily allow only functions declared globally to be overloaded, then we could instead do something like this

http://codepad.org/ZBqvdfU8

old Re: Overloading CS2D functions

Apache uwu
User Off Offline

Quote
What about local functions, this would potentially work as well by changing the _G to work inside of the function right?

1
2
3
4
5
6
7
8
9
10
11
function a()
	local b=function(a)
			print("1 "..a)
		end
	b=function(a,b)
		print("2 "..a.." "..b)
	end
	return a(1),a(1,2)
end

a()

old Re: Overloading CS2D functions

Lee
Moderator Off Offline

Quote
I haven't found out a way to preserve the local information except by creating successively smaller lexical scope. Take for example

1
2
3
4
5
6
7
8
9
do 
	local f = function() end 
	do
		local f = function(x) end
		do
			...
		end
	end
end

And at the inner most scope, we could use some debug function to traverse up on the scope "ladder" and keep track of local variables that qualify as overloads. But this method isn't as elegant as the method you suggested.

Alternatively, it is possible to take the bytecode of a function and replace all occurrences of the CLOSURE instruction and all following reachable definition such that the reachable register is a currently in scope local value (albeit this may be unnecessary). Take the following contrived example

1
2
3
4
5
6
7
8
9
function test()
	local f = function(a)
		print("1", a)
	end
    
	f = function(a, b)
		print("2", b)
	end
end

This generates the following code for test()
1
2
3
4
function <test.lua:1,9> (3 instructions, 12 bytes at 00258E30)
0 params, 2 slots, 0 upvalues, 1 local, 0 constants, 2 functions
        1       [4]     CLOSURE         0 0     ; 00258F90
        2       [8]     CLOSURE         0 1     ; 00597E90

Consulting https://gist.github.com/2918746 for references, we see that this means that the local variable 0 is first set to the 0th index function (00258F90) in the function table associated with test(), which is

1
2
3
4
5
6
7
function <test.lua:2,4> (5 instructions, 20 bytes at 00258F90)
1 param, 4 slots, 0 upvalues, 1 local, 2 constants, 0 functions
        1       [3]     GETGLOBAL       1 -1    ; print
        2       [3]     LOADK           2 -2    ; "1"
        3       [3]     MOVE            3 0
        4       [3]     CALL            1 3 1
        5       [4]     RETURN          0 1

and next sets local variable 0 to the second function, which is

1
2
3
4
5
6
7
function <test.lua:2,4> (5 instructions, 20 bytes at 00258F90)
1 param, 4 slots, 0 upvalues, 1 local, 2 constants, 0 functions
        1       [3]     GETGLOBAL       1 -1    ; print
        2       [3]     LOADK           2 -2    ; "1"
        3       [3]     MOVE            3 0
        4       [3]     CALL            1 3 1
        5       [4]     RETURN          0 1

It's possible to check the 0th local variable to see if there's a name associated with it. If there is, this is a user defined local variable and eligible for overloading.

Due to the way that Lua currently handles bytecode generation, expressions of the type

1
local f = function() end

will always directly translate to

1
CLOSURE(Local('f'), f-index)

rather than

1
2
3
4
SEQUENCE(
	CLOSURE(Reg(0), f-index), 
	MOVE(Local('f'), Reg(0))
)

it should be okay to get away with only translating CLOSURE opcodes. However, there's a slight hitch to this plan. If for some reason multiple chunks are created for a single function, we'll have to do extra work to synchronize all of the other closures with the root closure. Furthermore this may or may not be what the user.

So once we figure out what to translate, we now need to figure out how to translate the byte code. This is actually quite simple. We set up our helper method that looks approximately like

1
2
3
4
5
6
7
8
9
10
11
12
function(...)
			local args = {...}
			for _,fstruct in ipairs(funcs) do
				local n,f = unpack(fstruct)
				-- we call the function with the next largest.
				if #args <= n then
					return f(unpack(args))
				end
			end
			-- if we ever reach this point, just use the last function
			funcs[#funcs][2](unpack(args))
		end

translated pretty much bytecode for bytecode. This will take in exactly one previously undefined upvalue (ie: local variables from a previous scope). We purposely inject a local at the end of the register stack for the funcs table. Next, whenever we encounter a closure instruction, we can replace that with a call to a function that takes care of adding the function into the funcs table.
To the start Previous 1 Next To the start
Log in to reply Scripts overviewCS2D overviewForums overview