summary refs log tree commit diff stats
path: root/doc/sets_fragment.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/sets_fragment.txt')
-rw-r--r--doc/sets_fragment.txt9
1 files changed, 6 insertions, 3 deletions
diff --git a/doc/sets_fragment.txt b/doc/sets_fragment.txt
index fba98db2d..6e0991a9e 100644
--- a/doc/sets_fragment.txt
+++ b/doc/sets_fragment.txt
@@ -5,10 +5,13 @@ only be an ordinal type of a certain size, namely:
 * `uint8`/`byte`-`uint16`
 * `char`
 * `enum`
+* Ordinal subrange types, i.e. `range[-10..10]`
 
-or equivalent. For signed integers the set's base type is defined to be in the
-range `0 .. MaxSetElements-1` where `MaxSetElements` is currently always
-2^16.
+or equivalent. When constructing a set with signed integer literals, the set's
+base type is defined to be in the range `0 .. DefaultSetElements-1` where
+`DefaultSetElements` is currently always 2^8. The maximum range length for the
+base type of a set is `MaxSetElements` which is currently always 2^16. Types
+with a bigger range length are coerced into the range `0 .. MaxSetElements-1`.
 
 The reason is that sets are implemented as high performance bit vectors.
 Attempting to declare a set with a larger type will result in an error:
2016-05-29 21:01:15 +0200 committer Andreas Rumpf <rumpf_a@web.de> 2016-05-29 21:01:15 +0200 fixes #3729' href='/ahoang/Nim/commit/tests/vm/tcomponent.nim?h=devel&id=552b13efe4d65c2381d74d4fcaf9237a8730db1c'>552b13efe ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132












                               
                  

























































                                                                                  
                                              



                                         
                                                











                                                                               
                                                                    








































                                                                         
discard """
  output: '''`:)` @ 0,0
FOO: blah'''
"""

#
# magic.nim
#

# bug #3729

import macros, sequtils, tables
import strutils
import sugar, meta

type
  Component = object
    fields: FieldSeq
    field_index: seq[string]
    procs: ProcSeq
    procs_index: seq[string]

  Registry = object
    field_index: seq[string]
    procs_index: seq[string]
    components: Table[string, Component]
    builtin: Component

proc newRegistry(): Registry =
  result.field_index = @[]
  result.procs_index = @[]
  result.components = initTable[string, Component]()

var registry {.compileTime.} = newRegistry()

proc validateComponent(r: var Registry, name: string, c: Component) =
  if r.components.hasKey(name):
    let msg = "`component` macro cannot consume duplicated identifier: " & name
    raise newException(ValueError, msg)

  for field_name in c.field_index:
    if r.field_index.contains(field_name):
      let msg = "`component` macro cannot delcare duplicated field: " & field_name
      raise newException(ValueError, msg)
    r.field_index.add(field_name)

  for proc_name in c.procs_index:
    if r.procs_index.contains(proc_name):
      let msg = "`component` macro cannot delcare duplicated proc: " & proc_name
      raise newException(ValueError, msg)
    r.procs_index.add(proc_name)

proc addComponent(r: var Registry, name: string, c: Component) =
  r.validateComponent(name, c)
  r.components.add(name, c)

proc parse_component(body: NimNode): Component =
  result.field_index = @[]
  result.procs_index = @[]
  for node in body:
    case node.kind:
      of nnkVarSection:
        result.fields = newFieldSeq(node)
        for field in result.fields:
          result.field_index.add(field.identifier.name)
      of nnkMethodDef, nnkProcDef:
        let new_proc = meta.newProc(node)
        result.procs = result.procs & @[new_proc]
        for procdef in result.procs:
          result.procs_index.add(procdef.identifier.name)
      else: discard

macro component*(name, body: untyped): typed =
  let component = parse_component(body)
  registry.addComponent($name, component)
  parseStmt("discard")

macro component_builtins(body: untyped): typed =
  let builtin = parse_component(body)
  registry.field_index = builtin.field_index
  registry.procs_index = builtin.procs_index
  registry.builtin = builtin

proc bind_methods*(component: var Component, identifier: Ident): seq[NimNode] =
  result = @[]
  for procdef in component.procs.mitems:
    let this_field = newField(newIdent("this"), identifier)
    procdef.params.insert(this_field, 0)
    result.add(procdef.render())

macro bind_components*(type_name, component_names: untyped): typed =
  result = newStmtList()
  let identifier = newIdent(type_name)
  let components = newBracket(component_names)
  var entity_type = newTypeDef(identifier, true, "object", "RootObj")
  entity_type.fields = registry.builtin.fields
  for component_name, component in registry.components:
    if components.contains(newIdent(component_name)):
      entity_type.fields = entity_type.fields & component.fields
  # TODO why doesn't the following snippet work instead of the one above?
  # for name in components:
  #   echo "Registering $1 to $2" % [name.name, identifier.name]
  #   let component = registry.components[name.name]
  #   entity_type.fields = entity_type.fields & component.fields
  let type_section: TypeDefSeq = @[entity_type]
  result.add type_section.render
  var builtin = registry.builtin
  let builtin_methods = bind_methods(builtin, identifier)
  for builtin_proc in builtin_methods:
    result.add(builtin_proc)
  echo "SIGSEV here"
  for component in registry.components.mvalues():
    for method_proc in bind_methods(component, identifier):
      result.add(method_proc)

component_builtins:
  proc foo(msg: string) =
    echo "FOO: $1" % msg

component position:
  var x*, y*: int

component name:
  var name*: string
  proc render*(x, y: int) = echo "`$1` @ $2,$3" % [this.name, $x, $y]

bind_components(Entity, [position, name])

var e = new(Entity)
e.name = ":)"
e.render(e.x, e.y)
e.foo("blah")