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 = "\\"