codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
#! /usr/local/bin/lua -- Helper functions to encode VM operations local function int(value) -- convert value to a 32-bit unsigned little-endian integer local b1, b2, b3, b4 b1 = value % 0x100 value = (value - b1) / 0x100 b2 = value % 0x100 value = (value - b2) / 0x100 b3 = value % 0x100 value = (value - b3) / 0x100 b4 = value % 0x100 return string.char(b1, b2, b3, b4) end local function ABC(op, a, b, c) -- create an ABC VM instruction local value = op + a * 2^6 + c * 2^14 + b * 2^23 return int(value) end -- factory for count_raw local function make_count_raw() local sentinel = {} local nxt -- raw: function(count, test, ...) -- if type(test) ~= "none", returns raw(count + 1, ...) -- otherwise returns count local raw = function(...) local null, count, sent sent = sentinel null = {...} -- this line gets modified -- after modification, ... is loaded into count, sent, etc. and then setlisted into -- a nil value to correct L->top. If we had a vararg, then sent will no longer be -- sentinel. (also note that after modification, no tables are created) if sent == sentinel then return count else -- we cannot trim a value off the front of the varargs ourselves, so proxy it return nxt(...) end end -- nxt: helper for raw nxt = function(count, a, ...) return raw(count + 1, ...) end return raw end -- tweak the factory to work as intended do make_count_raw = string.dump(make_count_raw) local to_find = ABC(4 , 3, 0, 0) -- GETUPVAL sentinel .. ABC(10, 4, 0, 0) -- NEWTABLE .. ABC(37, 5, 0, 0) -- VARARG .. ABC(34, 4, 0, 1) -- SETLIST .. ABC(0 , 1, 4, 0) -- MOVE 1, 4 local to_rep = ABC(4 , 3, 0, 0) -- GETUPVAL sentinel .. ABC(0 , 0, 0, 0) -- NOP .. ABC(37, 2, 0, 0) -- VARARG (sets count, *may* overwrite sent) .. ABC(34, 1, 0, 1) -- SETLIST (into a nil, so it does nothing) .. ABC(0 , 0, 0, 0) -- NOP local first, last = make_count_raw:find(to_find, 1, true) make_count_raw = make_count_raw:sub(1, first - 1) .. to_rep .. make_count_raw:sub(last + 1) make_count_raw = assert(loadstring(make_count_raw)) end -- create count_raw and define count local count_raw = make_count_raw() function count(...) return count_raw(0, ...) end -- show it working print(count("a", "b", "c")) --> 3 print(count(nil, "d", nil, nil)) --> 4 print(count("e", nil, nil, "f", nil, nil, nil)) --> 7 print(count()) --> 0 print(count(nil)) --> 1
Private
[
?
]
Run code