1
+ < h1 > Nim</ h1 >
2
+ < p > To use this language, use the class "language-nim".</ p >
3
+
4
+ < h2 > Comments</ h2 >
5
+ < pre > < code > # This is a comment</ code > </ pre >
6
+
7
+ < h2 > Strings</ h2 >
8
+ < pre > < code > "This is a string."
9
+ "This is a string with \"quotes\" in it."
10
+ """This is
11
+ a "multi-line"
12
+ string."""
13
+ """"A long string within quotes.""""
14
+ R"This is a raw string."
15
+ r"Some ""quotes"" inside a raw string."
16
+ r"""Raw strings
17
+ can also be multi-line."""
18
+ foo"This is a generalized raw string literal."
19
+ bar"""This is also
20
+ a generalized raw string literal."""</ code > </ pre >
21
+
22
+ < h2 > Characters</ h2 >
23
+ < pre > < code > 'a'
24
+ '\''
25
+ '\t'
26
+ '\15'
27
+ '\xFC'</ code > </ pre >
28
+
29
+ < h2 > Numbers</ h2 >
30
+ < pre > < code > 42
31
+ 0xaf
32
+ 0xf_2_c
33
+ 0o07
34
+ 0b1111_0000
35
+ 0B0_10001110100_0000101001000111101011101111111011000101001101001001'f64
36
+ 9_000'u
37
+ 32.
38
+ 32.1f32
39
+ 32.e-5
40
+ 32.2e+2
41
+ 2'i16
42
+ 2i16
43
+ 0xfe'f32</ code > </ pre >
44
+
45
+ < h2 > Full example</ h2 >
46
+ < pre > < code > # Example from http://nim-by-example.github.io/oop_macro/
47
+ import macros
48
+
49
+ macro class*(head: expr, body: stmt): stmt {.immediate.} =
50
+ # The macro is immediate so that it doesn't
51
+ # resolve identifiers passed to it
52
+
53
+ var typeName, baseName: NimNode
54
+
55
+ if head.kind == nnkIdent:
56
+ # `head` is expression `typeName`
57
+ # echo head.treeRepr
58
+ # --------------------
59
+ # Ident !"Animal"
60
+ typeName = head
61
+
62
+ elif head.kind == nnkInfix and $head[0] == "of":
63
+ # `head` is expression `typeName of baseClass`
64
+ # echo head.treeRepr
65
+ # --------------------
66
+ # Infix
67
+ # Ident !"of"
68
+ # Ident !"Animal"
69
+ # Ident !"RootObj"
70
+ typeName = head[1]
71
+ baseName = head[2]
72
+
73
+ else:
74
+ quit "Invalid node: " & head.lispRepr
75
+
76
+ # echo treeRepr(body)
77
+ # --------------------
78
+ # StmtList
79
+ # VarSection
80
+ # IdentDefs
81
+ # Ident !"name"
82
+ # Ident !"string"
83
+ # Empty
84
+ # IdentDefs
85
+ # Ident !"age"
86
+ # Ident !"int"
87
+ # Empty
88
+ # MethodDef
89
+ # Ident !"vocalize"
90
+ # Empty
91
+ # Empty
92
+ # FormalParams
93
+ # Ident !"string"
94
+ # Empty
95
+ # Empty
96
+ # StmtList
97
+ # StrLit ...
98
+ # MethodDef
99
+ # Ident !"age_human_yrs"
100
+ # Empty
101
+ # Empty
102
+ # FormalParams
103
+ # Ident !"int"
104
+ # Empty
105
+ # Empty
106
+ # StmtList
107
+ # DotExpr
108
+ # Ident !"this"
109
+ # Ident !"age"
110
+
111
+ # create a new stmtList for the result
112
+ result = newStmtList()
113
+
114
+ # var declarations will be turned into object fields
115
+ var recList = newNimNode(nnkRecList)
116
+
117
+ # Iterate over the statements, adding `this: T`
118
+ # to the parameters of functions
119
+ for node in body.children:
120
+ case node.kind:
121
+
122
+ of nnkMethodDef, nnkProcDef:
123
+ # inject `this: T` into the arguments
124
+ let p = copyNimTree(node.params)
125
+ p.insert(1, newIdentDefs(ident"this", typeName))
126
+ node.params = p
127
+ result.add(node)
128
+
129
+ of nnkVarSection:
130
+ # variables get turned into fields of the type.
131
+ for n in node.children:
132
+ recList.add(n)
133
+
134
+ else:
135
+ result.add(node)
136
+
137
+ # The following prints out the AST structure:
138
+ #
139
+ # import macros
140
+ # dumptree:
141
+ # type X = ref object of Y
142
+ # z: int
143
+ # --------------------
144
+ # TypeSection
145
+ # TypeDef
146
+ # Ident !"X"
147
+ # Empty
148
+ # RefTy
149
+ # ObjectTy
150
+ # Empty
151
+ # OfInherit
152
+ # Ident !"Y"
153
+ # RecList
154
+ # IdentDefs
155
+ # Ident !"z"
156
+ # Ident !"int"
157
+ # Empty
158
+
159
+ result.insert(0,
160
+ if baseName == nil:
161
+ quote do:
162
+ type `typeName` = ref object of RootObj
163
+ else:
164
+ quote do:
165
+ type `typeName` = ref object of `baseName`
166
+ )
167
+ # Inspect the tree structure:
168
+ #
169
+ # echo result.treeRepr
170
+ # --------------------
171
+ # StmtList
172
+ # StmtList
173
+ # TypeSection
174
+ # TypeDef
175
+ # Ident !"Animal"
176
+ # Empty
177
+ # RefTy
178
+ # ObjectTy
179
+ # Empty
180
+ # OfInherit
181
+ # Ident !"RootObj"
182
+ # Empty < = We want to replace this
183
+ # MethodDef
184
+ # ...
185
+
186
+ result[0][0][0][2][0][2] = recList
187
+
188
+ # Lets inspect the human-readable version of the output
189
+ # echo repr(result)
190
+ # Output:
191
+ # type
192
+ # Animal = ref object of RootObj
193
+ # name: string
194
+ # age: int
195
+ #
196
+ # method vocalize(this: Animal): string =
197
+ # "..."
198
+ #
199
+ # method age_human_yrs(this: Animal): int =
200
+ # this.age
201
+
202
+ # ---
203
+
204
+ class Animal of RootObj:
205
+ var name: string
206
+ var age: int
207
+ method vocalize: string = "..."
208
+ method age_human_yrs: int = this.age # `this` is injected
209
+
210
+ class Dog of Animal:
211
+ method vocalize: string = "woof"
212
+ method age_human_yrs: int = this.age * 7
213
+
214
+ class Cat of Animal:
215
+ method vocalize: string = "meow"
216
+
217
+ # ---
218
+
219
+ var animals: seq[Animal] = @[]
220
+ animals.add(Dog(name: "Sparky", age: 10))
221
+ animals.add(Cat(name: "Mitten", age: 10))
222
+
223
+ for a in animals:
224
+ echo a.vocalize()
225
+ echo a.age_human_yrs()</ code > </ pre >
226
+
227
+ < h2 > Known failures</ h2 >
228
+ < p > There are certain edge cases where Prism will fail.
229
+ There are always such cases in every regex-based syntax highlighter.
230
+ However, Prism dares to be open and honest about them.
231
+ If a failure is listed here, it doesn’t mean it will never be fixed. This is more of a “known bugs” list, just with a certain type of bug.
232
+ </ p >
233
+
234
+ < h3 > Comment-like substrings</ h3 >
235
+ < pre > < code > "This # is a broken string"</ code > </ pre >
0 commit comments