Skip to content

Instantly share code, notes, and snippets.

@mflamer
Created October 7, 2013 05:25
Show Gist options
  • Save mflamer/6862918 to your computer and use it in GitHub Desktop.
Save mflamer/6862918 to your computer and use it in GitHub Desktop.
This code crashes the Nimrod compiler and leaves no stack trace
const NULL* = 0
type
TagPtr = distinct int
Sum2[T1,T2] = TagPtr
proc copyHeap*[T](x: var T): ptr T =
var
size = sizeof(T)
mem = allocShared(size)
copyMem(mem, x.addr, size)
result = cast[ptr T](mem)
proc popPtr(x: TagPtr): int {.inline.} =
result = cast[int](x) and 0xFFFFFFFC'i32
proc pack[T](p: pointer, f: range[0..3]): T {.inline.} =
result = cast[T](cast[int](p) or f)
proc typ(x: TagPtr): range[0..3] {.inline.} =
cast[int](x) and 3
proc val[T](x: TagPtr): T {.inline.} = cast[ptr T](popPtr(x))[]
proc `==`*(x: TagPtr, y: enum): bool {.inline.} =
x.typ == ord(y)
proc `==`*(x: enum, y: TagPtr): bool {.inline.} =
ord(x) == y.typ
##-------------------------------------------------------------
## Maybe
##-------------------------------------------------------------
type
Maybe[T] = Sum2[T,void]
EMaybe* = enum
TNone,
TSome
## Constructors
##-------------------------------------------------------------
proc some*[T](x: T): Maybe[T] =
var y = x
result = pack[Maybe[T]](copyHeap(y), ord(TSome))
proc none*[T](): Maybe[T] =
result = cast[Maybe[T]](NULL)
## Accessors
##-------------------------------------------------------------
proc typ*(x: Maybe): range[0..3] {.inline.} = cast[int](x) and 3
proc val*[T](x: Maybe[T]): T {.inline.} =
cast[ptr T](popPtr(cast[int](x)))[]
## stringify
##-------------------------------------------------------------
proc `$`*[T](m: Maybe[T]): string =
if m == TNone: return "None"
else: return "Some " & $val[T](m)
proc map[T,S](f: proc(a:T):S, m: Maybe[T]): Maybe[S] =
if m == TNone: return none[S]()
if m == TSome: return some(f(val[T](m)))
var
test = some(5)
echo(test)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment