about summary refs log tree commit diff stats
path: root/src/html
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-03-04 17:28:37 +0100
committerbptato <nincsnevem662@gmail.com>2024-03-04 17:28:37 +0100
commita510b9494678edaa745e6662d649ef8eeb3f28a6 (patch)
treebcfe065361c3af4631cb4ee90f13640c230a0a66 /src/html
parentc5dc63741f0d3a876c88b86d3e0374148fb6b3d0 (diff)
downloadchawan-a510b9494678edaa745e6662d649ef8eeb3f28a6.tar.gz
catom: merge TagType with AttrType
it's inefficient and pointless to treat them differently, so just derive
a new enum from TagType with a macro
Diffstat (limited to 'src/html')
-rw-r--r--src/html/catom.nim128
-rw-r--r--src/html/dom.nim52
-rw-r--r--src/html/enums.nim61
3 files changed, 131 insertions, 110 deletions
diff --git a/src/html/catom.nim b/src/html/catom.nim
index e908a5f4..1bb6cc8c 100644
--- a/src/html/catom.nim
+++ b/src/html/catom.nim
@@ -1,25 +1,112 @@
 import std/hashes
-
-import html/enums
+import std/macros
+import std/sets
+import std/strutils
 
 import chame/tags
 
+# create a static enum compatible with chame/tags
+
+macro makeStaticAtom =
+  # declare inside the macro to avoid confusion with StaticAtom0
+  type
+    StaticAtom0 = enum
+      atAcceptCharset = "accept-charset"
+      atAction = "action"
+      atAlign = "align"
+      atAlt = "alt"
+      atAsync = "async"
+      atBgcolor = "bgcolor"
+      atBlocking = "blocking"
+      atCharset = "charset"
+      atChecked = "checked"
+      atClass = "class"
+      atClassList
+      atColor = "color"
+      atCols = "cols"
+      atColspan = "colspan"
+      atCrossorigin = "crossorigin"
+      atDefer = "defer"
+      atDirname = "dirname"
+      atDisabled = "disabled"
+      atEnctype = "enctype"
+      atEvent = "event"
+      atFor = "for"
+      atForm = "form"
+      atFormaction = "formaction"
+      atFormenctype = "formenctype"
+      atFormmethod = "formmethod"
+      atHeight = "height"
+      atHref = "href"
+      atId = "id"
+      atIntegrity = "integrity"
+      atIsmap = "ismap"
+      atLanguage = "language"
+      atMedia = "media"
+      atMethod = "method"
+      atMultiple = "multiple"
+      atName = "name"
+      atNomodule = "nomodule"
+      atOnload = "onload"
+      atReferrerpolicy = "referrerpolicy"
+      atRel = "rel"
+      atRequired = "required"
+      atRows = "rows"
+      atRowspan = "rowspan"
+      atSelected = "selected"
+      atSize = "size"
+      atSizes = "sizes"
+      atSlot = "slot"
+      atSrc = "src"
+      atSrcset = "srcset"
+      atStyle = "style"
+      atStylesheet = "stylesheet"
+      atTarget = "target"
+      atText = "text"
+      atTitle = "title"
+      atType = "type"
+      atUsemap = "usemap"
+      atValign = "valign"
+      atValue = "value"
+      atWidth = "width"
+  let decl = quote do:
+    type StaticAtom* {.inject.} = enum
+      atUnknown = ""
+  let decl0 = decl[0][2]
+  var seen: HashSet[string]
+  for t in TagType:
+    if t == TAG_UNKNOWN:
+      continue
+    let tn = $t
+    var name = "at"
+    name &= tn[0].toUpperAscii()
+    name &= tn.substr(1)
+    if name == "atTr":
+      # Nim cries about this overlapping with the attr() procs :/
+      name = "satTr"
+    seen.incl(tn)
+    decl0.add(newNimNode(nnkEnumFieldDef).add(ident(name), newStrLitNode(tn)))
+  for i, f in StaticAtom0.getType():
+    if i == 0:
+      continue
+    let tn = $StaticAtom0(i - 1)
+    if tn in seen:
+      continue
+    decl0.add(newNimNode(nnkEnumFieldDef).add(ident(f.strVal), newStrLitNode(tn)))
+  decl
+
+makeStaticAtom
+
 #TODO use a better hash map
 const CAtomFactoryStrMapLength = 1024 # must be a power of 2
 static:
   doAssert (CAtomFactoryStrMapLength and (CAtomFactoryStrMapLength - 1)) == 0
 
-# Null atom + mapped tag types + mapped attr types
-const AttrMapNum = 1 + ({TagType.low..TagType.high} - {TAG_UNKNOWN}).card +
-  ({AttrType.low..AttrType.high} - {atUnknown}).card
-
 type
   CAtom* = distinct int
 
   CAtomFactoryInit = object
     obj: CAtomFactoryObj
-    attrToAtom: array[AttrType, CAtom]
-    atomToAttr: array[AttrMapNum, AttrType]
 
   CAtomFactoryObj = object
     strMap: array[CAtomFactoryStrMapLength, seq[CAtom]]
@@ -53,14 +140,9 @@ const factoryInit = (func(): CAtomFactoryInit =
   var init = CAtomFactoryInit()
   # Null atom
   init.obj.atomMap.add("")
-  # TagType: 1..TagType.high
-  for tagType in TagType(1) .. TagType.high:
-    discard init.obj.toAtom($tagType)
-  # Attr: may overlap with TagType; exclude atUnknown
-  for attrType in AttrType(1) .. AttrType.high:
-    let atom = init.obj.toAtom($attrType)
-    init.attrToAtom[attrType] = atom
-    init.atomToAttr[int(atom)] = attrType
+  # StaticAtom includes TagType too.
+  for sa in StaticAtom(1) .. StaticAtom.high:
+    discard init.obj.toAtom($sa)
   return init
 )()
 
@@ -76,21 +158,21 @@ func toAtom*(factory: CAtomFactory, tagType: TagType): CAtom =
   assert tagType != TAG_UNKNOWN
   return CAtom(tagType)
 
-func toAtom*(factory: CAtomFactory, attrType: AttrType): CAtom =
+func toAtom*(factory: CAtomFactory, attrType: StaticAtom): CAtom =
   assert attrType != atUnknown
-  return factoryInit.attrToAtom[attrType]
+  return CAtom(attrType)
 
 func toStr*(factory: CAtomFactory, atom: CAtom): string =
   return factory.atomMap[int(atom)]
 
 func toTagType*(factory: CAtomFactory, atom: CAtom): TagType =
   let i = int(atom)
-  if i in 1 .. int(TagType.high):
-    return TagType(atom)
+  if i <= int(TagType.high):
+    return TagType(i)
   return TAG_UNKNOWN
 
-func toAttrType*(factory: CAtomFactory, atom: CAtom): AttrType =
+func toStaticAtom*(factory: CAtomFactory, atom: CAtom): StaticAtom =
   let i = int(atom)
-  if i < factoryInit.atomToAttr.len:
-    return factoryInit.atomToAttr[i]
+  if i <= int(StaticAtom.high):
+    return StaticAtom(i)
   return atUnknown
diff --git a/src/html/dom.nim b/src/html/dom.nim
index d4e368d5..7909a876 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -709,7 +709,7 @@ type
     REFLECT_STR, REFLECT_BOOL, REFLECT_LONG, REFLECT_ULONG_GZ, REFLECT_ULONG
 
   ReflectEntry = object
-    attrname: AttrType
+    attrname: StaticAtom
     funcname: string
     tags: set[TagType]
     case t: ReflectType
@@ -719,8 +719,8 @@ type
       u: uint32
     else: discard
 
-func attrType0(s: static string): AttrType =
-  return parseEnum[AttrType](s)
+func attrType0(s: static string): StaticAtom =
+  return parseEnum[StaticAtom](s)
 
 template toset(ts: openarray[TagType]): set[TagType] =
   var tags: system.set[TagType]
@@ -820,10 +820,10 @@ const ReflectTable0 = [
 ]
 
 # Forward declarations
-func attr*(element: Element, s: AttrType): string
+func attr*(element: Element, s: StaticAtom): string
 func attrb*(element: Element, s: CAtom): bool
 proc attr*(element: Element, name: CAtom, value: string)
-proc attr*(element: Element, name: AttrType, value: string)
+proc attr*(element: Element, name: StaticAtom, value: string)
 func baseURL*(document: Document): URL
 proc delAttr(element: Element, i: int, keep = false)
 proc reflectAttrs(element: Element, name: CAtom, value: string)
@@ -836,7 +836,7 @@ func document*(node: Node): Document =
 proc toAtom*(document: Document, s: string): CAtom =
   return document.factory.toAtom(s)
 
-proc toAtom*(document: Document, at: AttrType): CAtom =
+proc toAtom*(document: Document, at: StaticAtom): CAtom =
   return document.factory.toAtom(at)
 
 proc toStr(document: Document, atom: CAtom): string =
@@ -845,8 +845,8 @@ proc toStr(document: Document, atom: CAtom): string =
 proc toTagType*(document: Document, atom: CAtom): TagType =
   return document.factory.toTagType(atom)
 
-proc toAttrType(document: Document, atom: CAtom): AttrType =
-  return document.factory.toAttrType(atom)
+proc toStaticAtom(document: Document, atom: CAtom): StaticAtom =
+  return document.factory.toStaticAtom(atom)
 
 proc toAtom*(document: Document, tagType: TagType): CAtom =
   return document.factory.toAtom(tagType)
@@ -878,7 +878,7 @@ func findAttr(element: Element, qualifiedName: CAtom): int =
       return i
   return -1
 
-func findAttr(element: Element, qualifiedName: AttrType): int =
+func findAttr(element: Element, qualifiedName: StaticAtom): int =
   return element.findAttr(element.document.toAtom(qualifiedName))
 
 func findAttrNS(element: Element, namespace, qualifiedName: CAtom): int =
@@ -1169,7 +1169,7 @@ func item(tokenList: DOMTokenList, i: int): Option[string] {.jsfunc.} =
 func contains*(tokenList: DOMTokenList, a: CAtom): bool =
   return a in tokenList.toks
 
-func contains(tokenList: DOMTokenList, a: AttrType): bool =
+func contains(tokenList: DOMTokenList, a: StaticAtom): bool =
   return tokenList.element.document.toAtom(a) in tokenList.toks
 
 func jsContains(tokenList: DOMTokenList, s: string): bool
@@ -1260,7 +1260,7 @@ const SupportedTokensMap = {
 
 func supports(tokenList: DOMTokenList, token: string):
     JSResult[bool] {.jsfunc.} =
-  let localName = tokenList.element.document.toAttrType(tokenList.localName)
+  let localName = tokenList.element.document.toStaticAtom(tokenList.localName)
   if localName in SupportedTokensMap:
     let lowercase = token.toLowerAscii()
     return ok(lowercase in SupportedTokensMap[localName])
@@ -2052,19 +2052,19 @@ func attr*(element: Element, s: CAtom): string =
     return element.attrs[i].value
   return ""
 
-func attr*(element: Element, s: AttrType): string =
+func attr*(element: Element, s: StaticAtom): string =
   return element.attr(element.document.toAtom(s))
 
-func attrl*(element: Element, s: AttrType): Option[int32] =
+func attrl*(element: Element, s: StaticAtom): Option[int32] =
   return parseInt32(element.attr(s))
 
-func attrulgz*(element: Element, s: AttrType): Option[uint32] =
+func attrulgz*(element: Element, s: StaticAtom): Option[uint32] =
   let x = parseUInt32(element.attr(s))
   if x.isSome and x.get > 0:
     return x
   return none(uint32)
 
-func attrul*(element: Element, s: AttrType): Option[uint32] =
+func attrul*(element: Element, s: StaticAtom): Option[uint32] =
   let x = parseUInt32(element.attr(s))
   if x.isSome and x.get >= 0:
     return x
@@ -2073,7 +2073,7 @@ func attrul*(element: Element, s: AttrType): Option[uint32] =
 func attrb*(element: Element, s: CAtom): bool =
   return element.findAttr(s) != -1
 
-func attrb*(element: Element, at: AttrType): bool =
+func attrb*(element: Element, at: StaticAtom): bool =
   let atom = element.document.toAtom(at)
   return element.attrb(atom)
 
@@ -2816,20 +2816,20 @@ proc loadResource(window: Window, image: HTMLImageElement) =
     window.loadingResourcePromises.add(p)
 
 proc reflectAttrs(element: Element, name: CAtom, value: string) =
-  let name = element.document.toAttrType(name)
-  template reflect_str(element: Element, n: AttrType, val: untyped) =
+  let name = element.document.toStaticAtom(name)
+  template reflect_str(element: Element, n: StaticAtom, val: untyped) =
     if name == n:
       element.val = value
       return
-  template reflect_atom(element: Element, n: AttrType, val: untyped) =
+  template reflect_atom(element: Element, n: StaticAtom, val: untyped) =
     if name == n:
       element.val = element.document.toAtom(value)
       return
-  template reflect_str(element: Element, n: AttrType, val, fun: untyped) =
+  template reflect_str(element: Element, n: StaticAtom, val, fun: untyped) =
     if name == n:
       element.val = fun(value)
       return
-  template reflect_bool(element: Element, n: AttrType, val: untyped) =
+  template reflect_bool(element: Element, n: StaticAtom, val: untyped) =
     if name == n:
       element.val = true
       return
@@ -2840,7 +2840,7 @@ proc reflectAttrs(element: Element, name: CAtom, value: string) =
         let a = element.document.toAtom(x)
         if a notin element.val:
           element.val.toks.add(a)
-  template reflect_domtoklist(element: Element, n: AttrType, val: untyped) =
+  template reflect_domtoklist(element: Element, n: StaticAtom, val: untyped) =
     if name == n:
       element.reflect_domtoklist0 val
       return
@@ -2931,7 +2931,7 @@ proc attr*(element: Element, name: CAtom, value: string) =
     ))
   element.reflectAttrs(name, value)
 
-proc attr*(element: Element, name: AttrType, value: string) =
+proc attr*(element: Element, name: StaticAtom, value: string) =
   element.attr(element.document.toAtom(name), value)
 
 proc attrns*(element: Element, localName: CAtom, prefix: NamespacePrefix,
@@ -2965,13 +2965,13 @@ proc attrns*(element: Element, localName: CAtom, prefix: NamespacePrefix,
     ))
   element.reflectAttrs(qualifiedName, value)
 
-proc attrl(element: Element, name: AttrType, value: int32) =
+proc attrl(element: Element, name: StaticAtom, value: int32) =
   element.attr(name, $value)
 
-proc attrul(element: Element, name: AttrType, value: uint32) =
+proc attrul(element: Element, name: StaticAtom, value: uint32) =
   element.attr(name, $value)
 
-proc attrulgz(element: Element, name: AttrType, value: uint32) =
+proc attrulgz(element: Element, name: StaticAtom, value: uint32) =
   if value > 0:
     element.attrul(name, value)
 
diff --git a/src/html/enums.nim b/src/html/enums.nim
index 389210ba..856b7813 100644
--- a/src/html/enums.nim
+++ b/src/html/enums.nim
@@ -30,67 +30,6 @@ type
     DOCUMENT_FRAGMENT_NODE = 11,
     NOTATION_NODE = 12
 
-  AttrType* = enum
-    atUnknown = ""
-    atAcceptCharset = "accept-charset"
-    atAction = "action"
-    atAlign = "align"
-    atAlt = "alt"
-    atAsync = "async"
-    atBgcolor = "bgcolor"
-    atBlocking = "blocking"
-    atCharset = "charset"
-    atChecked = "checked"
-    atClass = "class"
-    atClassList
-    atColor = "color"
-    atCols = "cols"
-    atColspan = "colspan"
-    atCrossorigin = "crossorigin"
-    atDefer = "defer"
-    atDirname = "dirname"
-    atDisabled = "disabled"
-    atEnctype = "enctype"
-    atEvent = "event"
-    atFor = "for"
-    atForm = "form"
-    atFormaction = "formaction"
-    atFormenctype = "formenctype"
-    atFormmethod = "formmethod"
-    atHeight = "height"
-    atHref = "href"
-    atId = "id"
-    atIntegrity = "integrity"
-    atIsmap = "ismap"
-    atLanguage = "language"
-    atMedia = "media"
-    atMethod = "method"
-    atMultiple = "multiple"
-    atName = "name"
-    atNomodule = "nomodule"
-    atOnload = "onload"
-    atReferrerpolicy = "referrerpolicy"
-    atRel = "rel"
-    atRequired = "required"
-    atRows = "rows"
-    atRowspan = "rowspan"
-    atSelected = "selected"
-    atSize = "size"
-    atSizes = "sizes"
-    atSlot = "slot"
-    atSrc = "src"
-    atSrcset = "srcset"
-    atStyle = "style"
-    atStylesheet = "stylesheet"
-    atTarget = "target"
-    atText = "text"
-    atTitle = "title"
-    atType = "type"
-    atUsemap = "usemap"
-    atValign = "valign"
-    atValue = "value"
-    atWidth = "width"
-
 const InputTypeWithSize* = {
   INPUT_SEARCH, INPUT_TEXT, INPUT_EMAIL, INPUT_PASSWORD, INPUT_URL, INPUT_TEL
 }