Warning, /frameworks/syntax-highlighting/autotests/input/test.nim is written in an unsupported language. File is not indexed.
0001 # Nim Sample file
0002 # Obtained form: https://nim-by-example.github.io/
0003
0004 # Comment ALERT NOTE FIXME
0005 #[ Multi-line
0006 comment ]#
0007
0008 ## Documentation comment
0009 ##[ Multi-line
0010 documentation comment ]##
0011
0012 import strformat
0013
0014 type
0015 Person = object
0016 name: string
0017 age: Natural # Ensures the age is positive
0018
0019 let people = [
0020 Person(name: "John", age: 45),
0021 Person(name: "Kate", age: 30)
0022 ]
0023
0024 for person in people:
0025 # Type-safe string interpolation,
0026 # evaluated at compile time.
0027 echo(fmt"{person.name} is {person.age} years old")
0028
0029 # Thanks to Nim's 'iterator' and 'yield' constructs,
0030 # iterators are as easy to write as ordinary
0031 # functions. They are compiled to inline loops.
0032 iterator oddNumbers[Idx, T](a: array[Idx, T]): T =
0033 for x in a:
0034 if x mod 2 == 1:
0035 yield x
0036
0037 for odd in oddNumbers([3, 6, 9, 12, 15, 18]):
0038 echo odd
0039
0040 # Use Nim's macro system to transform a dense
0041 # data-centric description of x86 instructions
0042 # into lookup tables that are used by
0043 # assemblers and JITs.
0044 import macros, strutils
0045
0046 macro toLookupTable(data: static[string]): untyped =
0047 result = newTree(nnkBracket)
0048 for w in data.split(';'):
0049 result.add newLit(w)
0050
0051 const
0052 data = "mov;btc;cli;xor"
0053 opcodes = toLookupTable(data)
0054
0055 for o in opcodes:
0056 echo o
0057
0058 # Variables
0059 proc getAlphabet(): string =
0060 var accm = ""
0061 for letter in 'a'..'z': # see iterators
0062 accm.add(letter)
0063 return accm
0064
0065 # Computed at compilation time
0066 const alphabet = getAlphabet()
0067
0068 # Mutable variables
0069 var
0070 a = "foo"
0071 b = 0
0072 # Works fine, initialized to 0
0073 c: int
0074
0075 # Immutable variables
0076 let
0077 d = "foo"
0078 e = 5
0079 # Compile-time error, must be initialized at creation
0080 f: float
0081
0082 # Works fine, `a` is mutable
0083 a.add("bar")
0084 b += 1
0085 c = 3
0086
0087 # Compile-time error, const cannot be modified at run-time
0088 alphabet = "abc"
0089
0090 # Compile-time error, `d` and `e` are immutable
0091 d.add("bar")
0092 e += 1
0093
0094 # Const
0095 STRING_LITERAL(TMP129, "abcdefghijklmnopqrstuvwxyz", 26);
0096
0097 # Loops
0098 import strutils, random
0099
0100 randomize()
0101 let answer = random(10) + 1
0102 while true:
0103 echo "I have a number from 1 to 10, what is it? "
0104 let guess = parseInt(stdin.readLine)
0105
0106 if guess < answer:
0107 echo "Too low, try again"
0108 elif guess > answer:
0109 echo "Too high, try again"
0110 else:
0111 echo "Correct!"
0112 break
0113
0114 block busyloops:
0115 while true:
0116 while true:
0117 break busyloops
0118
0119 # Case Statements
0120 case "charlie":
0121 of "alfa":
0122 echo "A"
0123 of "bravo":
0124 echo "B"
0125 of "charlie":
0126 echo "C"
0127 else:
0128 echo "Unrecognized letter"
0129
0130 case 'h':
0131 of 'a', 'e', 'i', 'o', 'u':
0132 echo "Vowel"
0133 of '\127'..'\255':
0134 echo "Unknown"
0135 else:
0136 echo "Consonant"
0137
0138 proc positiveOrNegative(num: int): string =
0139 result = case num:
0140 of low(int).. -1:
0141 "negative"
0142 of 0:
0143 "zero"
0144 of 1..high(int):
0145 "positive"
0146 else:
0147 "impossible"
0148
0149 echo positiveOrNegative(-1)
0150
0151 # items and pairs
0152 type
0153 CustomRange = object
0154 low: int
0155 high: int
0156
0157 iterator items(range: CustomRange): int =
0158 var i = range.low
0159 while i <= range.high:
0160 yield i
0161 inc i
0162
0163 iterator pairs(range: CustomRange): tuple[a: int, b: char] =
0164 for i in range: # uses CustomRange.items
0165 yield (i, char(i + ord('a')))
0166
0167 for i, c in CustomRange(low: 1, high: 3):
0168 echo c
0169
0170 # Operators
0171 iterator `...`*[T](a: T, b: T): T =
0172 var res: T = T(a)
0173 while res <= b:
0174 yield res
0175 inc res
0176
0177 for i in 0...5:
0178 echo i
0179
0180 # Inline Iterators
0181 iterator countTo(n: int): int =
0182 var i = 0
0183 while i <= n:
0184 yield i
0185 inc i
0186
0187 for i in countTo(5):
0188 echo i
0189
0190 # Closure Iterators
0191 proc countTo(n: int): iterator(): int =
0192 return iterator(): int =
0193 var i = 0
0194 while i <= n:
0195 yield i
0196 inc i
0197
0198 let countTo20 = countTo(20)
0199
0200 echo countTo20()
0201
0202 var output = ""
0203 # Raw iterator usage:
0204 while true:
0205 # 1. grab an element
0206 let next = countTo20()
0207 # 2. Is the element bogus? It's the end of the loop, discard it
0208 if finished(countTo20):
0209 break
0210 # 3. Loop body goes here:
0211 output.add($next & " ")
0212
0213 echo output
0214
0215 output = ""
0216 let countTo9 = countTo(9)
0217 for i in countTo9():
0218 output.add($i)
0219 echo output
0220
0221 # Procs
0222 proc fibonacci(n: int): int =
0223 if n < 2:
0224 result = n
0225 else:
0226 result = fibonacci(n - 1) + (n - 2).fibonacci
0227
0228 # Operators
0229 proc `$`(a: array[2, array[2, int]]): string =
0230 result = ""
0231 for v in a:
0232 for vx in v:
0233 result.add($vx & ", ")
0234 result.add("\n")
0235
0236 echo([[1, 2], [3, 4]]) # See varargs for
0237 # how echo works
0238
0239 proc `^&*^@%`(a, b: string): string =
0240 ## A confusingly named useless operator
0241 result = a[0] & b[high(b)]
0242
0243 assert("foo" ^&*^@% "bar" == "fr")
0244
0245 # Generic Functions
0246 # Not really good idea for obvious reasons
0247 let zero = ""
0248 proc `+`(a, b: string): string =
0249 a & b
0250
0251 proc `*`[T](a: T, b: int): T =
0252 result = zero
0253 for i in 0..b-1:
0254 result = result + a # calls `+` from line 3
0255
0256 assert("a" * 10 == "aaaaaaaaaa")
0257
0258 # Blocks
0259 block outer:
0260 for i in 0..2000:
0261 for j in 0..2000:
0262 if i+j == 3145:
0263 echo i, ", ", j
0264 break outer
0265
0266 let b = 3
0267 block:
0268 let b = "3" # shadowing is probably a dumb idea
0269
0270 # Primitive types
0271 let
0272 a: int8 = 0x7F # Works
0273 b: uint8 = 0b1111_1111 # Works
0274 d = 0xFF # type is int
0275 c: uint8 = 256 # Compile time error
0276 let
0277 a: int = 2
0278 b: int = 4
0279 echo 4/2
0280
0281 # Types Aliases
0282 type
0283 MyInteger* = int
0284
0285 let a: int = 2
0286 discard a + MyInteger(4)
0287
0288 # Objects
0289 type
0290 Animal* = object
0291 name*, species*: string
0292 age: int
0293
0294 proc sleep*(a: var Animal) =
0295 a.age += 1
0296
0297 proc dead*(a: Animal): bool =
0298 result = a.age > 20
0299
0300 var carl: Animal
0301 carl = Animal(name : "Carl",
0302 species : "L. glama",
0303 age : 12)
0304
0305 let joe = Animal(name : "Joe",
0306 species : "H. sapiens",
0307 age : 23)
0308
0309 assert(not carl.dead)
0310 for i in 0..10:
0311 carl.sleep()
0312 assert carl.dead
0313
0314 # Enums
0315 type
0316 CompassDirections = enum
0317 cdNorth, cdEast, cdSouth, cdWest
0318
0319 Colors {.pure.} = enum
0320 Red = "FF0000", Green = (1, "00FF00"), Blue = "0000FF"
0321
0322 Signals = enum
0323 sigQuit = 3, sigAbort = 6, sigKill = 9
0324
0325 # Distinct Types
0326 type
0327 Dollars* = distinct float
0328
0329 var a = 20.Dollars
0330 a = 25 # Doesn't compile
0331 a = 25.Dollars # Works fine
0332
0333 # Strings
0334 echo "words words words ⚑"
0335 echo """
0336 <html>
0337 <head>
0338 </head>\n\n
0339
0340 <body>
0341 </body>
0342 </html> """
0343
0344 proc re(s: string): string = s
0345
0346 echo r"."".\s\" # Raw string
0347 echo re"\b[a-z]++\b" # Regular expression
0348 echo function"text" # Tagged string
0349
0350 # Arrays
0351 type
0352 ThreeStringAddress = array[3, string]
0353 let names: ThreeStringAddress = ["Jasmine", "Ktisztina", "Kristof"]
0354 let addresses: ThreeStringAddress = ["101 Betburweg", "66 Bellion Drive", "194 Laarderweg"]
0355
0356 type
0357 Matrix[W, H: static[int]] =
0358 array[1..W, array[1..H, int]]
0359
0360 let mat1: Matrix[2, 2] = [[1, 0],
0361 [0, 1]]
0362 let mat2: Matrix[2, 2] = [[0, 1],
0363 [1, 0]]
0364
0365 proc `+`[W, H](a, b: Matrix[W, H]):
0366 Matrix[W, H] =
0367 for i in 1..high(a):
0368 for j in 1..high(a[0]):
0369 result[i][j] = a[i][j] + b[i][j]
0370
0371 # Seqs
0372 var
0373 a = @[1, 2, 3]
0374 b = newSeq[int](3)
0375
0376 for i, v in a:
0377 b[i] = v*v
0378
0379 for i in 4..100:
0380 b.add(i * i)
0381
0382 b.delete(0) # takes O(n) time
0383 b = a[0] & b # Same as original b
0384
0385 # JSON
0386 import json
0387
0388 let element = "Hydrogen"
0389 let atomicNumber = 1
0390
0391 let jsonObject = %* {"element": element, "atomicNumber": atomicNumber}
0392 # This will print {"element":"Hydrogen", "atomicNumber": 1}
0393 echo $jsonObject
0394
0395 # We start with a string representation of a JSON object
0396 let jsonObject = """{"name": "Sky", "age": 32}"""
0397 let jsonArray = """[7, 8, 9]"""
0398
0399 let parsedObject = parseJson(jsonObject)
0400 let name = parsedObject["name"].getStr()
0401 # This will print Sky
0402 echo name
0403
0404 let parsedArray = parseJson(jsonArray)
0405 let eight = parsedArray[1].getInt()
0406 # This will print 8
0407 echo eight
0408
0409 # First we'll define our types
0410 type
0411 Element = object
0412 name: string
0413 atomicNumber: int
0414
0415 # Let's say this is the JSON we want to convert
0416 let jsonObject = parseJson("""{"name": "Carbon", "atomicNumber": 6}""")
0417
0418 let element = to(jsonObject, Element)
0419 # This will print Carbon
0420 echo element.name
0421 # This will print 6
0422 echo element.atomicNumber
0423
0424 # Object Oriented Programming
0425 type Animal = ref object of RootObj
0426 name: string
0427 age: int
0428 method vocalize(this: Animal): string {.base.} = "..."
0429 method ageHumanYrs(this: Animal): int {.base.} = this.age
0430
0431 type Dog = ref object of Animal
0432 method vocalize(this: Dog): string = "woof"
0433 method ageHumanYrs(this: Dog): int = this.age * 7
0434
0435 type Cat = ref object of Animal
0436 method vocalize(this: Cat): string = "meow"
0437
0438 var animals: seq[Animal] = @[]
0439 animals.add(Dog(name: "Sparky", age: 10))
0440 animals.add(Cat(name: "Mitten", age: 10))
0441
0442 for a in animals:
0443 echo a.vocalize()
0444 echo a.ageHumanYrs()
0445
0446 let slash = "\\"