Skip to content

Instantly share code, notes, and snippets.

@flaviut
Created May 2, 2014 23:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flaviut/880458a5d7ed23ddbd8e to your computer and use it in GitHub Desktop.
Save flaviut/880458a5d7ed23ddbd8e to your computer and use it in GitHub Desktop.
## Provides utility methods to make working with bit manipulations
## easier and less error prone
const
validBitfieldType = ["int", "int8", "int16", "int32", "int64", "uint",
"uint8", "uint16", "uint32", "uint64", "bool"]
macro bitfield(values: varargs[stmt]): stmt =
## Creates a bitfield with the given fields
# Validate and initial parameter processing
if values.len %% 3 != 0:
error("Each field requires three values")
var fields = newSeq[tuple[typ, name: string, size: int]](values.len div 3)
var numSize = 0
for i in 0..(values.len div 3 - 1):
let typ = values[i*3]
let name = values[i*3 + 1]
let size = values[i*3 + 2]
if typ.kind != nnkSym or not validBitfieldType.contains($typ):
error("Type `" & $typ & "` is either not a type or an invalid one")
if not (name.kind in {nnkStrLit, nnkRStrLit, nnkTripleStrLit}) or
(not validIdentifier(name.strVal) and name.strVal != ""):
error("Name `" & name.strVal & "` either not a literal string or an " &
"invalid identifier")
if not (size.kind in {nnkIntLit .. nnkUInt64Lit}):
error("The size of `" & name.strVal & "` is not an integer")
fields[i] = (typ: $typ, name: name.strVal, size: size.intVal.int)
numSize += size.intVal.int
if not (numSize in {8, 16, 32, 64}):
error($numSize & "can only be one of 8, 16, 32, or 64. " &
"Adding padding may help")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment