Skip to content

Instantly share code, notes, and snippets.

@Varriount
Created May 22, 2017 23:14
import jsmn, streams, tables, hashes, strutils, macros, sequtils
# StringRef support
type
StringRef = ref string
StringCache = TableRef[Hash, StringRef]
converter stringToStringRef(s: string): StringRef =
new(result)
result[] = s
proc `$`(s: StringRef): string =
return s[]
type
ShapeKind = enum
skStructure
skBlob
skBoolean
skInteger
skList
skMap
skString
ShapeName = string
Shape = ref object
# An abstract data value accepted by the AWS api.
name: string
box: bool
documentation: string
case kind: ShapeKind
of skStructure:
members: OrderedTable[string, Shape]
of skBlob:
sensitive: bool
of skBoolean:
discard
of skInteger:
maxValue: int
minValue: int
of skList:
member: Shape
of skMap:
key: Shape
value: Shape
of skString:
maxLength: int
minLength: int
pattern: string
enums: seq[string]
macro genStructure(shape: static[Shape]): untyped =
assert(shape.kind == skStructure)
discard
macro genBlobShape(shape: static[Shape]): untyped =
assert(shape.kind == skBlob)
result = quote do:
type `shape.name` = ref object
blob: seq[int8]
sensitive: bool
proc isValid(value: `shape.name`): bool =
return true
macro genBooleanShape(shape: static[Shape]): untyped =
assert(shape.kind == skBoolean)
result = quote do:
type `shape.name` = string
proc isValid(value: `shape.name`): bool =
result = true
macro genIntegerShape(shape: static[Shape]): untyped =
assert(shape.kind == skInteger)
let doLengthCheck = (shape.maxLength > 0)
result = quote do:
type `shape.name` = string
proc isValid(value: `shape.name`): bool =
when `doLengthCheck`:
result = (
len(value) >= `shape.minValue` and
len(value) <= `shape.maxValue`
)
else:
result = true
macro genListShape(shape: static[Shape]): untyped =
assert(shape.kind == skList)
result = quote do:
type `shape.name` = seq[`shape.member.name`]
macro genStringShape(shape: static[Shape]): untyped =
# echo repr(shape.kind)
# assert(shape.kind == skString)
let
doLengthCheck = (shape.maxLength > 0)
isEnum = (len(shape.enums) == 0)
var enumIdents = mapIt(shape.enums, ident(it))
result = quote do:
when `isEnum`:
type `shape.name`* = enum
`enumIdents[0]`
else:
type `shape.name` = string
proc isValid(value: `shape.name`): bool =
when `doLengthCheck`:
result = (
len(value) >= `shape.minLength` and
len(value) <= `shape.maxLength`
)
else:
result = true
echo treeRepr(result)
macro smain(): untyped =
let s = Shape(kind: skString)
s.name = ""
s.box = false
s.documentation = ""
s.maxLength = 0
s.minLength = 0
s.pattern = ""
s.enums = @[]
result = genStringShape(s)
smain()
# proc expectString(tokens: JsonTokens, source: string, index: int,
# cache: StringCache = nil): StringRef =
# # First check if the token is a string
# let t = tokens[index]
# if t.kind != JSMN_STRING:
# raise newException(
# ValueError,
# "Error at character $1: Expected a string value." % [$t.start]
# )
# # Next, check if it's in the cache
# var h = hash(source, t.start, t.stop-1)
# if cache != nil and h in cache:
# result = cache[h]
# else:
# new(result)
# result[] = source[t.start .. (t.stop - 1)]
# if cache != nil:
# cache[h] = result
# let
# source = open("service-2.json").readAll()
# tokens = parseJson(source)
# proc generateShapes(tokens: seq[JsmnToken], source: string,
# var index): TableRef[ShapeName, Shape] =
# initTable(result)
# var prototypes = initTable[string, ProtoShape]
# for index, token in tokens[index .. high(tokens):
# # Get the shape name and object start
# let name = expectString(tokens,)
# # macro generateStructure(source: string, tokens: seq[JsmnToken], startIndex: int): untyped =
# # var index = startIndex
# # # First grab the name of the structure to generate
# # let
# # nameToken = tokens[index]
# # name = source[nameToken.start .. nameToken.stop]
import macros
dumpTree:
type foo = enum
a
b
c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment