Created
May 22, 2017 23:14
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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