Skip to content

Instantly share code, notes, and snippets.

@skrat
Created June 21, 2013 05:26
Show Gist options
  • Save skrat/5829066 to your computer and use it in GitHub Desktop.
Save skrat/5829066 to your computer and use it in GitHub Desktop.
Swizzling, dynamic instance methods
Function::property = (prop, desc) ->
Object.defineProperty @prototype, prop, desc
arrayExcept = (arr, idx) ->
res = arr[0..]
res.splice idx, 1
res
combine = (str) ->
fn = (active, rest, a) ->
if !active && !rest
return
if !rest
a.push active
else
fn(active + rest[0], rest.slice(1), a)
fn(active, rest.slice(1), a)
a
fn("", str, [])
permute = (arr) ->
arr = Array::slice.call arr, 0
return [[]] if arr.length == 0
permutations = (for value,idx in arr
[value].concat perm for perm in permute arrayExcept arr, idx)
[].concat permutations...
perm_comb = (input) ->
result = []
combine(input).map((c) -> permute(c))
.forEach (cp) ->
cp.forEach (accessor) ->
result.push accessor.join('')
result
typed_concat = (type, a, b) ->
alen = a.length
result = new type(alen + b.length)
result.set(a)
result.set(b, alen)
result
class vec2i
X = 0
Y = 1
SIZE = 2
PREALLOCATE = 50
TYPE = Int32Array
DATA = new TYPE()
NREF = 0
@ensure_capacity: ->
if DATA.length < NREF * SIZE
DATA = typed_concat(TYPE, DATA, new TYPE(PREALLOCATE * SIZE))
constructor: (x, y) ->
@offset = NREF * SIZE
NREF += 1
@constructor.ensure_capacity()
@x = x
@y = y
@property 'x',
get: -> DATA[@offset + X]
set: (x) -> DATA[@offset + X] = x
@property 'y',
get: -> DATA[@offset + Y]
set: (y) -> DATA[@offset + Y] = y
perm_comb('xy').forEach (els) ->
if els.length > 1
vec2i::constructor.property els,
get: -> new vec2i(
@__lookupGetter__(els[0])(),
@__lookupGetter__(els[1])())
toString: ->
"vec2i(" + @x + "," + @y + ")"
class vec3i
X = 0
Y = 1
Z = 2
SIZE = 3
PREALLOCATE = 50
TYPE = Int32Array
DATA = new TYPE()
NREF = 0
@ensure_capacity: ->
if DATA.length < NREF * SIZE
DATA = typed_concat(TYPE, DATA, new TYPE(PREALLOCATE * SIZE))
constructor: (x, y, z) ->
@offset = NREF * SIZE
NREF += 1
@constructor.ensure_capacity()
@x = x
@y = y
@z = z
@property 'x',
get: -> DATA[@offset + X]
set: (x) -> DATA[@offset + X] = x
@property 'y',
get: -> DATA[@offset + Y]
set: (y) -> DATA[@offset + Y] = y
@property 'z',
get: -> DATA[@offset + Z]
set: (z) -> DATA[@offset + Z] = z
perm_comb('xyz').forEach (els) ->
if els.length == 3
type = vec3i
else if els.length == 2
type = vec2i
else
return
vec3i::constructor.property els,
get: -> new type(els.split('').map((c) => @__lookupGetter__(c)())...)
toString: ->
"vec3i(" + @x + "," + @y + "," + @z + ")"
console.log(new vec3i(1,2,3).zyx + '')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment