demo.odin 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645
  1. //+vet !using-stmt !using-param
  2. package main
  3. import "core:fmt"
  4. import "core:mem"
  5. import "core:os"
  6. import "core:thread"
  7. import "core:time"
  8. import "core:reflect"
  9. import "base:runtime"
  10. import "base:intrinsics"
  11. import "core:math/big"
  12. /*
  13. Odin is a general-purpose programming language with distinct typing built
  14. for high performance, modern systems and data-oriented programming.
  15. Odin is the C alternative for the Joy of Programming.
  16. # Installing Odin
  17. Getting Started - https://odin-lang.org/docs/install/
  18. Instructions for downloading and install the Odin compiler and libraries.
  19. # Learning Odin
  20. Getting Started - https://odin-lang.org/docs/install/
  21. Getting Started with Odin. Downloading, installing, and getting your
  22. first program to compile and run.
  23. Overview of Odin - https://odin-lang.org/docs/overview/
  24. An overview of the Odin programming language and its features.
  25. Frequently Asked Questions (FAQ) - https://odin-lang.org/docs/faq/
  26. Answers to common questions about Odin.
  27. Packages - https://pkg.odin-lang.org/
  28. Documentation for all the official packages part of the
  29. core and vendor library collections.
  30. Nightly Builds - https://odin-lang.org/docs/nightly/
  31. Get the latest nightly builds of Odin.
  32. More Odin Examples - https://github.com/odin-lang/examples
  33. This repository contains examples of how certain things can be accomplished
  34. in idiomatic Odin, allowing you learn its semantics, as well as how to use
  35. parts of the core and vendor package collections.
  36. */
  37. the_basics :: proc() {
  38. fmt.println("\n# the basics")
  39. { // The Basics
  40. // os.args holds the path to the current executable and any arguments passed to it.
  41. if len(os.args) == 1 {
  42. fmt.printf("Hellope from %v.\n", os.args[0])
  43. } else if len(os.args) > 2 {
  44. fmt.printf("%v, %v! from %v.\n", os.args[1], os.args[2], os.args[0])
  45. }
  46. // Lexical elements and literals
  47. // A comment
  48. my_integer_variable: int // A comment for documentaton
  49. // Multi-line comments begin with /* and end with */. Multi-line comments can
  50. // also be nested (unlike in C):
  51. /*
  52. You can have any text or code here and
  53. have it be commented.
  54. /*
  55. NOTE: comments can be nested!
  56. */
  57. */
  58. // String literals are enclosed in double quotes and character literals in single quotes.
  59. // Special characters are escaped with a backslash \
  60. some_string := "This is a string"
  61. _ = 'A' // unicode codepoint literal
  62. _ = '\n'
  63. _ = "C:\\Windows\\notepad.exe"
  64. // Raw string literals are enclosed with single back ticks
  65. _ = `C:\Windows\notepad.exe`
  66. // The length of a string in bytes can be found using the built-in `len` procedure:
  67. _ = len("Foo")
  68. _ = len(some_string)
  69. // Numbers
  70. // Numerical literals are written similar to most other programming languages.
  71. // A useful feature in Odin is that underscores are allowed for better
  72. // readability: 1_000_000_000 (one billion). A number that contains a dot is a
  73. // floating point literal: 1.0e9 (one billion). If a number literal is suffixed
  74. // with i, is an imaginary number literal: 2i (2 multiply the square root of -1).
  75. // Binary literals are prefixed with 0b, octal literals with 0o, and hexadecimal
  76. // literals 0x. A leading zero does not produce an octal constant (unlike C).
  77. // In Odin, if a numeric constant can be represented by a type without
  78. // precision loss, it will automatically convert to that type.
  79. x: int = 1.0 // A float literal but it can be represented by an integer without precision loss
  80. // Constant literals are “untyped” which means that they can implicitly convert to a type.
  81. y: int // `y` is typed of type `int`
  82. y = 1 // `1` is an untyped integer literal which can implicitly convert to `int`
  83. z: f64 // `z` is typed of type `f64` (64-bit floating point number)
  84. z = 1 // `1` is an untyped integer literal which can be implicitly converted to `f64`
  85. // No need for any suffixes or decimal places like in other languages
  86. // (with the exception of negative zero, which must be given as `-0.0`)
  87. // CONSTANTS JUST WORK!!!
  88. // Assignment statements
  89. h: int = 123 // declares a new variable `h` with type `int` and assigns a value to it
  90. h = 637 // assigns a new value to `h`
  91. // `=` is the assignment operator
  92. // You can assign multiple variables with it:
  93. a, b := 1, "hello" // declares `a` and `b` and infers the types from the assignments
  94. b, a = "byte", 0
  95. // Note: `:=` is two tokens, `:` and `=`. The following are equivalent,
  96. /*
  97. i: int = 123
  98. i: = 123
  99. i := 123
  100. */
  101. // Constant declarations
  102. // Constants are entities (symbols) which have an assigned value.
  103. // The constant’s value cannot be changed.
  104. // The constant’s value must be able to be evaluated at compile time:
  105. X :: "what" // constant `X` has the untyped string value "what"
  106. // Constants can be explicitly typed like a variable declaration:
  107. Y : int : 123
  108. Z :: Y + 7 // constant computations are possible
  109. _ = my_integer_variable
  110. _ = x
  111. }
  112. }
  113. control_flow :: proc() {
  114. fmt.println("\n# control flow")
  115. { // Control flow
  116. // For loop
  117. // Odin has only one loop statement, the `for` loop
  118. // Basic for loop
  119. for i := 0; i < 10; i += 1 {
  120. fmt.println(i)
  121. }
  122. // NOTE: Unlike other languages like C, there are no parentheses `( )` surrounding the three components.
  123. // Braces `{ }` or a `do` are always required
  124. for i := 0; i < 10; i += 1 { }
  125. // for i := 0; i < 10; i += 1 do fmt.print()
  126. // The initial and post statements are optional
  127. i := 0
  128. for ; i < 10; {
  129. i += 1
  130. }
  131. // These semicolons can be dropped. This `for` loop is equivalent to C's `while` loop
  132. i = 0
  133. for i < 10 {
  134. i += 1
  135. }
  136. // If the condition is omitted, an infinite loop is produced:
  137. for {
  138. break
  139. }
  140. // Range-based for loop
  141. // The basic for loop
  142. for j := 0; j < 10; j += 1 {
  143. fmt.println(j)
  144. }
  145. // can also be written
  146. for j in 0..<10 {
  147. fmt.println(j)
  148. }
  149. for j in 0..=9 {
  150. fmt.println(j)
  151. }
  152. // Certain built-in types can be iterated over
  153. some_string := "Hello, 世界"
  154. for character in some_string { // Strings are assumed to be UTF-8
  155. fmt.println(character)
  156. }
  157. some_array := [3]int{1, 4, 9}
  158. for value in some_array {
  159. fmt.println(value)
  160. }
  161. some_slice := []int{1, 4, 9}
  162. for value in some_slice {
  163. fmt.println(value)
  164. }
  165. some_dynamic_array := [dynamic]int{1, 4, 9}
  166. defer delete(some_dynamic_array)
  167. for value in some_dynamic_array {
  168. fmt.println(value)
  169. }
  170. some_map := map[string]int{"A" = 1, "C" = 9, "B" = 4}
  171. defer delete(some_map)
  172. for key in some_map {
  173. fmt.println(key)
  174. }
  175. // Alternatively a second index value can be added
  176. for character, index in some_string {
  177. fmt.println(index, character)
  178. }
  179. for value, index in some_array {
  180. fmt.println(index, value)
  181. }
  182. for value, index in some_slice {
  183. fmt.println(index, value)
  184. }
  185. for value, index in some_dynamic_array {
  186. fmt.println(index, value)
  187. }
  188. for key, value in some_map {
  189. fmt.println(key, value)
  190. }
  191. // The iterated values are copies and cannot be written to.
  192. // The following idiom is useful for iterating over a container in a by-reference manner:
  193. for _, idx in some_slice {
  194. some_slice[idx] = (idx+1)*(idx+1)
  195. }
  196. // If statements
  197. x := 123
  198. if x >= 0 {
  199. fmt.println("x is positive")
  200. }
  201. if y := -34; y < 0 {
  202. fmt.println("y is negative")
  203. }
  204. if y := 123; y < 0 {
  205. fmt.println("y is negative")
  206. } else if y == 0 {
  207. fmt.println("y is zero")
  208. } else {
  209. fmt.println("y is positive")
  210. }
  211. // Switch statement
  212. // A switch statement is another way to write a sequence of if-else statements.
  213. // In Odin, the default case is denoted as a case without any expression.
  214. #partial switch arch := ODIN_ARCH; arch {
  215. case .i386:
  216. fmt.println("32-bit")
  217. case .amd64:
  218. fmt.println("64-bit")
  219. case: // default
  220. fmt.println("Unsupported architecture")
  221. }
  222. // Odin’s `switch` is like one in C or C++, except that Odin only runs the selected case.
  223. // This means that a `break` statement is not needed at the end of each case.
  224. // Another important difference is that the case values need not be integers nor constants.
  225. // To achieve a C-like fall through into the next case block, the keyword `fallthrough` can be used.
  226. one_angry_dwarf :: proc() -> int {
  227. fmt.println("one_angry_dwarf was called")
  228. return 1
  229. }
  230. switch j := 0; j {
  231. case 0:
  232. case one_angry_dwarf():
  233. }
  234. // A switch statement without a condition is the same as `switch true`.
  235. // This can be used to write a clean and long if-else chain and have the
  236. // ability to break if needed
  237. switch {
  238. case x < 0:
  239. fmt.println("x is negative")
  240. case x == 0:
  241. fmt.println("x is zero")
  242. case:
  243. fmt.println("x is positive")
  244. }
  245. // A `switch` statement can also use ranges like a range-based loop:
  246. switch c := 'j'; c {
  247. case 'A'..='Z', 'a'..='z', '0'..='9':
  248. fmt.println("c is alphanumeric")
  249. }
  250. switch x {
  251. case 0..<10:
  252. fmt.println("units")
  253. case 10..<13:
  254. fmt.println("pre-teens")
  255. case 13..<20:
  256. fmt.println("teens")
  257. case 20..<30:
  258. fmt.println("twenties")
  259. }
  260. }
  261. { // Defer statement
  262. // A defer statement defers the execution of a statement until the end of
  263. // the scope it is in.
  264. // The following will print 4 then 234:
  265. {
  266. x := 123
  267. defer fmt.println(x)
  268. {
  269. defer x = 4
  270. x = 2
  271. }
  272. fmt.println(x)
  273. x = 234
  274. }
  275. // You can defer an entire block too:
  276. {
  277. bar :: proc() {}
  278. defer {
  279. fmt.println("1")
  280. fmt.println("2")
  281. }
  282. cond := false
  283. defer if cond {
  284. bar()
  285. }
  286. }
  287. // Defer statements are executed in the reverse order that they were declared:
  288. {
  289. defer fmt.println("1")
  290. defer fmt.println("2")
  291. defer fmt.println("3")
  292. }
  293. // Will print 3, 2, and then 1.
  294. if false {
  295. f, err := os.open("my_file.txt")
  296. if err != nil {
  297. // handle error
  298. }
  299. defer os.close(f)
  300. // rest of code
  301. }
  302. }
  303. { // When statement
  304. /*
  305. The when statement is almost identical to the if statement but with some differences:
  306. * Each condition must be a constant expression as a when
  307. statement is evaluated at compile time.
  308. * The statements within a branch do not create a new scope
  309. * The compiler checks the semantics and code only for statements
  310. that belong to the first condition that is true
  311. * An initial statement is not allowed in a when statement
  312. * when statements are allowed at file scope
  313. */
  314. // Example
  315. when ODIN_ARCH == .i386 {
  316. fmt.println("32 bit")
  317. } else when ODIN_ARCH == .amd64 {
  318. fmt.println("64 bit")
  319. } else {
  320. fmt.println("Unknown architecture")
  321. }
  322. // The when statement is very useful for writing platform specific code.
  323. // This is akin to the #if construct in C’s preprocessor however, in Odin,
  324. // it is type checked.
  325. }
  326. { // Branch statements
  327. cond, cond1, cond2 := false, false, false
  328. one_step :: proc() { fmt.println("one_step") }
  329. beyond :: proc() { fmt.println("beyond") }
  330. // Break statement
  331. for cond {
  332. switch {
  333. case:
  334. if cond {
  335. break // break out of the `switch` statement
  336. }
  337. }
  338. break // break out of the `for` statement
  339. }
  340. loop: for cond1 {
  341. for cond2 {
  342. break loop // leaves both loops
  343. }
  344. }
  345. // Continue statement
  346. for cond {
  347. if cond2 {
  348. continue
  349. }
  350. fmt.println("Hellope")
  351. }
  352. // Fallthrough statement
  353. // Odin’s switch is like one in C or C++, except that Odin only runs the selected
  354. // case. This means that a break statement is not needed at the end of each case.
  355. // Another important difference is that the case values need not be integers nor
  356. // constants.
  357. // fallthrough can be used to explicitly fall through into the next case block:
  358. switch i := 0; i {
  359. case 0:
  360. one_step()
  361. fallthrough
  362. case 1:
  363. beyond()
  364. }
  365. }
  366. }
  367. named_proc_return_parameters :: proc() {
  368. fmt.println("\n# named proc return parameters")
  369. foo0 :: proc() -> int {
  370. return 123
  371. }
  372. foo1 :: proc() -> (a: int) {
  373. a = 123
  374. return
  375. }
  376. foo2 :: proc() -> (a, b: int) {
  377. // Named return values act like variables within the scope
  378. a = 321
  379. b = 567
  380. return b, a
  381. }
  382. fmt.println("foo0 =", foo0()) // 123
  383. fmt.println("foo1 =", foo1()) // 123
  384. fmt.println("foo2 =", foo2()) // 567 321
  385. }
  386. variadic_procedures :: proc() {
  387. fmt.println("\n# variadic procedures")
  388. sum :: proc(nums: ..int, init_value:= 0) -> (result: int) {
  389. result = init_value
  390. for n in nums {
  391. result += n
  392. }
  393. return
  394. }
  395. fmt.println("sum(()) =", sum())
  396. fmt.println("sum(1, 2) =", sum(1, 2))
  397. fmt.println("sum(1, 2, 3, 4, 5) =", sum(1, 2, 3, 4, 5))
  398. fmt.println("sum(1, 2, 3, 4, 5, init_value = 5) =", sum(1, 2, 3, 4, 5, init_value = 5))
  399. // pass a slice as varargs
  400. odds := []int{1, 3, 5}
  401. fmt.println("odds =", odds)
  402. fmt.println("sum(..odds) =", sum(..odds))
  403. fmt.println("sum(..odds, init_value = 5) =", sum(..odds, init_value = 5))
  404. }
  405. explicit_procedure_overloading :: proc() {
  406. fmt.println("\n# explicit procedure overloading")
  407. add_ints :: proc(a, b: int) -> int {
  408. x := a + b
  409. fmt.println("add_ints", x)
  410. return x
  411. }
  412. add_floats :: proc(a, b: f32) -> f32 {
  413. x := a + b
  414. fmt.println("add_floats", x)
  415. return x
  416. }
  417. add_numbers :: proc(a: int, b: f32, c: u8) -> int {
  418. x := int(a) + int(b) + int(c)
  419. fmt.println("add_numbers", x)
  420. return x
  421. }
  422. add :: proc{add_ints, add_floats, add_numbers}
  423. add(int(1), int(2))
  424. add(f32(1), f32(2))
  425. add(int(1), f32(2), u8(3))
  426. add(1, 2) // untyped ints coerce to int tighter than f32
  427. add(1.0, 2.0) // untyped floats coerce to f32 tighter than int
  428. add(1, 2, 3) // three parameters
  429. // Ambiguous answers
  430. // add(1.0, 2)
  431. // add(1, 2.0)
  432. }
  433. struct_type :: proc() {
  434. fmt.println("\n# struct type")
  435. // A struct is a record type in Odin. It is a collection of fields.
  436. // Struct fields are accessed by using a dot:
  437. {
  438. Vector2 :: struct {
  439. x: f32,
  440. y: f32,
  441. }
  442. v := Vector2{1, 2}
  443. v.x = 4
  444. fmt.println(v.x)
  445. // Struct fields can be accessed through a struct pointer:
  446. v = Vector2{1, 2}
  447. p := &v
  448. p.x = 1335
  449. fmt.println(v)
  450. // We could write p^.x, however, it is nice to abstract the ability
  451. // to not explicitly dereference the pointer. This is very useful when
  452. // refactoring code to use a pointer rather than a value, and vice versa.
  453. }
  454. {
  455. // A struct literal can be denoted by providing the struct’s type
  456. // followed by {}. A struct literal must either provide all the
  457. // arguments or none:
  458. Vector3 :: struct {
  459. x, y, z: f32,
  460. }
  461. v: Vector3
  462. v = Vector3{} // Zero value
  463. v = Vector3{1, 4, 9}
  464. // You can list just a subset of the fields if you specify the
  465. // field by name (the order of the named fields does not matter):
  466. v = Vector3{z=1, y=2}
  467. assert(v.x == 0)
  468. assert(v.y == 2)
  469. assert(v.z == 1)
  470. }
  471. {
  472. // Structs can tagged with different memory layout and alignment requirements:
  473. a :: struct #align(4) {} // align to 4 bytes
  474. b :: struct #packed {} // remove padding between fields
  475. c :: struct #raw_union {} // all fields share the same offset (0). This is the same as C's union
  476. }
  477. }
  478. union_type :: proc() {
  479. fmt.println("\n# union type")
  480. {
  481. val: union{int, bool}
  482. val = 137
  483. if i, ok := val.(int); ok {
  484. fmt.println(i)
  485. }
  486. val = true
  487. fmt.println(val)
  488. val = nil
  489. switch v in val {
  490. case int: fmt.println("int", v)
  491. case bool: fmt.println("bool", v)
  492. case: fmt.println("nil")
  493. }
  494. }
  495. {
  496. // There is a duality between `any` and `union`
  497. // An `any` has a pointer to the data and allows for any type (open)
  498. // A `union` has as binary blob to store the data and allows only certain types (closed)
  499. // The following code is with `any` but has the same syntax
  500. val: any
  501. val = 137
  502. if i, ok := val.(int); ok {
  503. fmt.println(i)
  504. }
  505. val = true
  506. fmt.println(val)
  507. val = nil
  508. switch v in val {
  509. case int: fmt.println("int", v)
  510. case bool: fmt.println("bool", v)
  511. case: fmt.println("nil")
  512. }
  513. }
  514. Vector3 :: distinct [3]f32
  515. Quaternion :: distinct quaternion128
  516. // More realistic examples
  517. {
  518. // NOTE(bill): For the above basic examples, you may not have any
  519. // particular use for it. However, my main use for them is not for these
  520. // simple cases. My main use is for hierarchical types. Many prefer
  521. // subtyping, embedding the base data into the derived types. Below is
  522. // an example of this for a basic game Entity.
  523. Entity :: struct {
  524. id: u64,
  525. name: string,
  526. position: Vector3,
  527. orientation: Quaternion,
  528. derived: any,
  529. }
  530. Frog :: struct {
  531. using entity: Entity,
  532. jump_height: f32,
  533. }
  534. Monster :: struct {
  535. using entity: Entity,
  536. is_robot: bool,
  537. is_zombie: bool,
  538. }
  539. // See `parametric_polymorphism` procedure for details
  540. new_entity :: proc($T: typeid) -> ^Entity {
  541. t := new(T)
  542. t.derived = t^
  543. return t
  544. }
  545. entity := new_entity(Monster)
  546. switch e in entity.derived {
  547. case Frog:
  548. fmt.println("Ribbit")
  549. case Monster:
  550. if e.is_robot { fmt.println("Robotic") }
  551. if e.is_zombie { fmt.println("Grrrr!") }
  552. fmt.println("I'm a monster")
  553. }
  554. }
  555. {
  556. // NOTE(bill): A union can be used to achieve something similar. Instead
  557. // of embedding the base data into the derived types, the derived data
  558. // in embedded into the base type. Below is the same example of the
  559. // basic game Entity but using an union.
  560. Entity :: struct {
  561. id: u64,
  562. name: string,
  563. position: Vector3,
  564. orientation: Quaternion,
  565. derived: union {Frog, Monster},
  566. }
  567. Frog :: struct {
  568. using entity: ^Entity,
  569. jump_height: f32,
  570. }
  571. Monster :: struct {
  572. using entity: ^Entity,
  573. is_robot: bool,
  574. is_zombie: bool,
  575. }
  576. // See `parametric_polymorphism` procedure for details
  577. new_entity :: proc($T: typeid) -> ^Entity {
  578. t := new(Entity)
  579. t.derived = T{entity = t}
  580. return t
  581. }
  582. entity := new_entity(Monster)
  583. switch e in entity.derived {
  584. case Frog:
  585. fmt.println("Ribbit")
  586. case Monster:
  587. if e.is_robot { fmt.println("Robotic") }
  588. if e.is_zombie { fmt.println("Grrrr!") }
  589. }
  590. // NOTE(bill): As you can see, the usage code has not changed, only its
  591. // memory layout. Both approaches have their own advantages but they can
  592. // be used together to achieve different results. The subtyping approach
  593. // can allow for a greater control of the memory layout and memory
  594. // allocation, e.g. storing the derivatives together. However, this is
  595. // also its disadvantage. You must either preallocate arrays for each
  596. // derivative separation (which can be easily missed) or preallocate a
  597. // bunch of "raw" memory; determining the maximum size of the derived
  598. // types would require the aid of metaprogramming. Unions solve this
  599. // particular problem as the data is stored with the base data.
  600. // Therefore, it is possible to preallocate, e.g. [100]Entity.
  601. // It should be noted that the union approach can have the same memory
  602. // layout as the any and with the same type restrictions by using a
  603. // pointer type for the derivatives.
  604. /*
  605. Entity :: struct {
  606. ...
  607. derived: union{^Frog, ^Monster},
  608. }
  609. Frog :: struct {
  610. using entity: Entity,
  611. ...
  612. }
  613. Monster :: struct {
  614. using entity: Entity,
  615. ...
  616. }
  617. new_entity :: proc(T: type) -> ^Entity {
  618. t := new(T)
  619. t.derived = t
  620. return t
  621. }
  622. */
  623. }
  624. }
  625. using_statement :: proc() {
  626. fmt.println("\n# using statement")
  627. // using can used to bring entities declared in a scope/namespace
  628. // into the current scope. This can be applied to import names, struct
  629. // fields, procedure fields, and struct values.
  630. Vector3 :: struct{x, y, z: f32}
  631. {
  632. Entity :: struct {
  633. position: Vector3,
  634. orientation: quaternion128,
  635. }
  636. // It can used like this:
  637. foo0 :: proc(entity: ^Entity) {
  638. fmt.println(entity.position.x, entity.position.y, entity.position.z)
  639. }
  640. // The entity members can be brought into the procedure scope by using it:
  641. foo1 :: proc(entity: ^Entity) {
  642. using entity
  643. fmt.println(position.x, position.y, position.z)
  644. }
  645. // The using can be applied to the parameter directly:
  646. foo2 :: proc(using entity: ^Entity) {
  647. fmt.println(position.x, position.y, position.z)
  648. }
  649. // It can also be applied to sub-fields:
  650. foo3 :: proc(entity: ^Entity) {
  651. using entity.position
  652. fmt.println(x, y, z)
  653. }
  654. }
  655. {
  656. // We can also apply the using statement to the struct fields directly,
  657. // making all the fields of position appear as if they on Entity itself:
  658. Entity :: struct {
  659. using position: Vector3,
  660. orientation: quaternion128,
  661. }
  662. foo :: proc(entity: ^Entity) {
  663. fmt.println(entity.x, entity.y, entity.z)
  664. }
  665. // Subtype polymorphism
  666. // It is possible to get subtype polymorphism, similar to inheritance-like
  667. // functionality in C++, but without the requirement of vtables or unknown
  668. // struct layout:
  669. Colour :: struct {r, g, b, a: u8}
  670. Frog :: struct {
  671. ribbit_volume: f32,
  672. using entity: Entity,
  673. colour: Colour,
  674. }
  675. frog: Frog
  676. // Both work
  677. foo(&frog.entity)
  678. foo(&frog)
  679. frog.x = 123
  680. // Note: using can be applied to arbitrarily many things, which allows
  681. // the ability to have multiple subtype polymorphism (but also its issues).
  682. // Note: using’d fields can still be referred by name.
  683. }
  684. }
  685. implicit_context_system :: proc() {
  686. fmt.println("\n# implicit context system")
  687. // In each scope, there is an implicit value named context. This
  688. // context variable is local to each scope and is implicitly passed
  689. // by pointer to any procedure call in that scope (if the procedure
  690. // has the Odin calling convention).
  691. // The main purpose of the implicit context system is for the ability
  692. // to intercept third-party code and libraries and modify their
  693. // functionality. One such case is modifying how a library allocates
  694. // something or logs something. In C, this was usually achieved with
  695. // the library defining macros which could be overridden so that the
  696. // user could define what he wanted. However, not many libraries
  697. // supported this in many languages by default which meant intercepting
  698. // third-party code to see what it does and to change how it does it is
  699. // not possible.
  700. c := context // copy the current scope's context
  701. context.user_index = 456
  702. {
  703. context.allocator = my_custom_allocator()
  704. context.user_index = 123
  705. what_a_fool_believes() // the `context` for this scope is implicitly passed to `what_a_fool_believes`
  706. }
  707. // `context` value is local to the scope it is in
  708. assert(context.user_index == 456)
  709. what_a_fool_believes :: proc() {
  710. c := context // this `context` is the same as the parent procedure that it was called from
  711. // From this example, context.user_index == 123
  712. // An context.allocator is assigned to the return value of `my_custom_allocator()`
  713. assert(context.user_index == 123)
  714. // The memory management procedure use the `context.allocator` by
  715. // default unless explicitly specified otherwise
  716. china_grove := new(int)
  717. free(china_grove)
  718. _ = c
  719. }
  720. my_custom_allocator :: mem.nil_allocator
  721. _ = c
  722. // By default, the context value has default values for its parameters which is
  723. // decided in the package runtime. What the defaults are are compiler specific.
  724. // To see what the implicit context value contains, please see the following
  725. // definition in package runtime.
  726. }
  727. parametric_polymorphism :: proc() {
  728. fmt.println("\n# parametric polymorphism")
  729. print_value :: proc(value: $T) {
  730. fmt.printf("print_value: %T %v\n", value, value)
  731. }
  732. v1: int = 1
  733. v2: f32 = 2.1
  734. v3: f64 = 3.14
  735. v4: string = "message"
  736. print_value(v1)
  737. print_value(v2)
  738. print_value(v3)
  739. print_value(v4)
  740. fmt.println()
  741. add :: proc(p, q: $T) -> T {
  742. x: T = p + q
  743. return x
  744. }
  745. a := add(3, 4)
  746. fmt.printf("a: %T = %v\n", a, a)
  747. b := add(3.2, 4.3)
  748. fmt.printf("b: %T = %v\n", b, b)
  749. // This is how `new` is implemented
  750. alloc_type :: proc($T: typeid) -> ^T {
  751. t := cast(^T)alloc(size_of(T), align_of(T))
  752. t^ = T{} // Use default initialization value
  753. return t
  754. }
  755. copy_slice :: proc(dst, src: []$T) -> int {
  756. n := min(len(dst), len(src))
  757. if n > 0 {
  758. mem.copy(&dst[0], &src[0], n*size_of(T))
  759. }
  760. return n
  761. }
  762. double_params :: proc(a: $A, b: $B) -> A {
  763. return a + A(b)
  764. }
  765. fmt.println(double_params(12, 1.345))
  766. { // Polymorphic Types and Type Specialization
  767. Table_Slot :: struct($Key, $Value: typeid) {
  768. occupied: bool,
  769. hash: u32,
  770. key: Key,
  771. value: Value,
  772. }
  773. TABLE_SIZE_MIN :: 32
  774. Table :: struct($Key, $Value: typeid) {
  775. count: int,
  776. allocator: mem.Allocator,
  777. slots: []Table_Slot(Key, Value),
  778. }
  779. // Only allow types that are specializations of a (polymorphic) slice
  780. make_slice :: proc($T: typeid/[]$E, len: int) -> T {
  781. return make(T, len)
  782. }
  783. // Only allow types that are specializations of `Table`
  784. allocate :: proc(table: ^$T/Table, capacity: int) {
  785. c := context
  786. if table.allocator.procedure != nil {
  787. c.allocator = table.allocator
  788. }
  789. context = c
  790. table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN))
  791. }
  792. expand :: proc(table: ^$T/Table) {
  793. c := context
  794. if table.allocator.procedure != nil {
  795. c.allocator = table.allocator
  796. }
  797. context = c
  798. old_slots := table.slots
  799. defer delete(old_slots)
  800. cap := max(2*len(table.slots), TABLE_SIZE_MIN)
  801. allocate(table, cap)
  802. for s in old_slots {
  803. if s.occupied {
  804. put(table, s.key, s.value)
  805. }
  806. }
  807. }
  808. // Polymorphic determination of a polymorphic struct
  809. // put :: proc(table: ^$T/Table, key: T.Key, value: T.Value) {
  810. put :: proc(table: ^Table($Key, $Value), key: Key, value: Value) {
  811. hash := get_hash(key) // Ad-hoc method which would fail in a different scope
  812. index := find_index(table, key, hash)
  813. if index < 0 {
  814. if f64(table.count) >= 0.75*f64(len(table.slots)) {
  815. expand(table)
  816. }
  817. assert(table.count <= len(table.slots))
  818. index = int(hash % u32(len(table.slots)))
  819. for table.slots[index].occupied {
  820. if index += 1; index >= len(table.slots) {
  821. index = 0
  822. }
  823. }
  824. table.count += 1
  825. }
  826. slot := &table.slots[index]
  827. slot.occupied = true
  828. slot.hash = hash
  829. slot.key = key
  830. slot.value = value
  831. }
  832. // find :: proc(table: ^$T/Table, key: T.Key) -> (T.Value, bool) {
  833. find :: proc(table: ^Table($Key, $Value), key: Key) -> (Value, bool) {
  834. hash := get_hash(key)
  835. index := find_index(table, key, hash)
  836. if index < 0 {
  837. return Value{}, false
  838. }
  839. return table.slots[index].value, true
  840. }
  841. find_index :: proc(table: ^Table($Key, $Value), key: Key, hash: u32) -> int {
  842. if len(table.slots) <= 0 {
  843. return -1
  844. }
  845. index := int(hash % u32(len(table.slots)))
  846. for table.slots[index].occupied {
  847. if table.slots[index].hash == hash {
  848. if table.slots[index].key == key {
  849. return index
  850. }
  851. }
  852. if index += 1; index >= len(table.slots) {
  853. index = 0
  854. }
  855. }
  856. return -1
  857. }
  858. get_hash :: proc(s: string) -> u32 { // fnv32a
  859. h: u32 = 0x811c9dc5
  860. for i in 0..<len(s) {
  861. h = (h ~ u32(s[i])) * 0x01000193
  862. }
  863. return h
  864. }
  865. table: Table(string, int)
  866. for i in 0..=36 { put(&table, "Hellope", i) }
  867. for i in 0..=42 { put(&table, "World!", i) }
  868. found, _ := find(&table, "Hellope")
  869. fmt.printf("`found` is %v\n", found)
  870. found, _ = find(&table, "World!")
  871. fmt.printf("`found` is %v\n", found)
  872. // I would not personally design a hash table like this in production
  873. // but this is a nice basic example
  874. // A better approach would either use a `u64` or equivalent for the key
  875. // and let the user specify the hashing function or make the user store
  876. // the hashing procedure with the table
  877. }
  878. { // Parametric polymorphic union
  879. Error :: enum {
  880. Foo0,
  881. Foo1,
  882. Foo2,
  883. Foo3,
  884. }
  885. Para_Union :: union($T: typeid) {T, Error}
  886. r: Para_Union(int)
  887. fmt.println(typeid_of(type_of(r)))
  888. fmt.println(r)
  889. r = 123
  890. fmt.println(r)
  891. r = Error.Foo0 // r = .Foo0 is allow too, see implicit selector expressions below
  892. fmt.println(r)
  893. }
  894. { // Polymorphic names
  895. foo :: proc($N: $I, $T: typeid) -> (res: [N]T) {
  896. // `N` is the constant value passed
  897. // `I` is the type of N
  898. // `T` is the type passed
  899. fmt.printf("Generating an array of type %v from the value %v of type %v\n",
  900. typeid_of(type_of(res)), N, typeid_of(I))
  901. for i in 0..<N {
  902. res[i] = T(i*i)
  903. }
  904. return
  905. }
  906. T :: int
  907. array := foo(4, T)
  908. for v, i in array {
  909. assert(v == T(i*i))
  910. }
  911. // Matrix multiplication
  912. mul :: proc(a: [$M][$N]$T, b: [N][$P]T) -> (c: [M][P]T) {
  913. for i in 0..<M {
  914. for j in 0..<P {
  915. for k in 0..<N {
  916. c[i][j] += a[i][k] * b[k][j]
  917. }
  918. }
  919. }
  920. return
  921. }
  922. x := [2][3]f32{
  923. {1, 2, 3},
  924. {3, 2, 1},
  925. }
  926. y := [3][2]f32{
  927. {0, 8},
  928. {6, 2},
  929. {8, 4},
  930. }
  931. z := mul(x, y)
  932. assert(z == {{36, 24}, {20, 32}})
  933. }
  934. }
  935. prefix_table := [?]string{
  936. "White",
  937. "Red",
  938. "Green",
  939. "Blue",
  940. "Octarine",
  941. "Black",
  942. }
  943. print_mutex := b64(false)
  944. @(disabled=!thread.IS_SUPPORTED)
  945. threading_example :: proc() {
  946. fmt.println("\n# threading_example")
  947. did_acquire :: proc(m: ^b64) -> (acquired: bool) {
  948. res, ok := intrinsics.atomic_compare_exchange_strong(m, false, true)
  949. return ok && res == false
  950. }
  951. { // Basic Threads
  952. fmt.println("\n## Basic Threads")
  953. worker_proc :: proc(t: ^thread.Thread) {
  954. for iteration in 1..=5 {
  955. fmt.printf("Thread %d is on iteration %d\n", t.user_index, iteration)
  956. fmt.printf("`%s`: iteration %d\n", prefix_table[t.user_index], iteration)
  957. time.sleep(1 * time.Millisecond)
  958. }
  959. }
  960. threads := make([dynamic]^thread.Thread, 0, len(prefix_table))
  961. defer delete(threads)
  962. for _ in prefix_table {
  963. if t := thread.create(worker_proc); t != nil {
  964. t.init_context = context
  965. t.user_index = len(threads)
  966. append(&threads, t)
  967. thread.start(t)
  968. }
  969. }
  970. for len(threads) > 0 {
  971. for i := 0; i < len(threads); /**/ {
  972. if t := threads[i]; thread.is_done(t) {
  973. fmt.printf("Thread %d is done\n", t.user_index)
  974. thread.destroy(t)
  975. ordered_remove(&threads, i)
  976. } else {
  977. i += 1
  978. }
  979. }
  980. }
  981. }
  982. { // Thread Pool
  983. fmt.println("\n## Thread Pool")
  984. task_proc :: proc(t: thread.Task) {
  985. index := t.user_index % len(prefix_table)
  986. for iteration in 1..=5 {
  987. for !did_acquire(&print_mutex) { thread.yield() } // Allow one thread to print at a time.
  988. fmt.printf("Worker Task %d is on iteration %d\n", t.user_index, iteration)
  989. fmt.printf("`%s`: iteration %d\n", prefix_table[index], iteration)
  990. print_mutex = false
  991. time.sleep(1 * time.Millisecond)
  992. }
  993. }
  994. N :: 3
  995. pool: thread.Pool
  996. thread.pool_init(&pool, allocator=context.allocator, thread_count=N)
  997. defer thread.pool_destroy(&pool)
  998. for i in 0..<30 {
  999. // be mindful of the allocator used for tasks. The allocator needs to be thread safe, or be owned by the task for exclusive use
  1000. thread.pool_add_task(&pool, allocator=context.allocator, procedure=task_proc, data=nil, user_index=i)
  1001. }
  1002. thread.pool_start(&pool)
  1003. {
  1004. // Wait a moment before we cancel a thread
  1005. time.sleep(5 * time.Millisecond)
  1006. // Allow one thread to print at a time.
  1007. for !did_acquire(&print_mutex) { thread.yield() }
  1008. thread.terminate(pool.threads[N - 1], 0)
  1009. fmt.println("Canceled last thread")
  1010. print_mutex = false
  1011. }
  1012. thread.pool_finish(&pool)
  1013. }
  1014. }
  1015. array_programming :: proc() {
  1016. fmt.println("\n# array programming")
  1017. {
  1018. a := [3]f32{1, 2, 3}
  1019. b := [3]f32{5, 6, 7}
  1020. c := a * b
  1021. d := a + b
  1022. e := 1 + (c - d) / 2
  1023. fmt.printf("%.1f\n", e) // [0.5, 3.0, 6.5]
  1024. }
  1025. {
  1026. a := [3]f32{1, 2, 3}
  1027. b := swizzle(a, 2, 1, 0)
  1028. assert(b == [3]f32{3, 2, 1})
  1029. c := swizzle(a, 0, 0)
  1030. assert(c == [2]f32{1, 1})
  1031. assert(c == 1)
  1032. }
  1033. {
  1034. Vector3 :: distinct [3]f32
  1035. a := Vector3{1, 2, 3}
  1036. b := Vector3{5, 6, 7}
  1037. c := (a * b)/2 + 1
  1038. d := c.x + c.y + c.z
  1039. fmt.printf("%.1f\n", d) // 22.0
  1040. cross :: proc(a, b: Vector3) -> Vector3 {
  1041. i := swizzle(a, 1, 2, 0) * swizzle(b, 2, 0, 1)
  1042. j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0)
  1043. return i - j
  1044. }
  1045. cross_shorter :: proc(a, b: Vector3) -> Vector3 {
  1046. i := a.yzx * b.zxy
  1047. j := a.zxy * b.yzx
  1048. return i - j
  1049. }
  1050. blah :: proc(a: Vector3) -> f32 {
  1051. return a.x + a.y + a.z
  1052. }
  1053. x := cross(a, b)
  1054. fmt.println(x)
  1055. fmt.println(blah(x))
  1056. }
  1057. }
  1058. map_type :: proc() {
  1059. fmt.println("\n# map type")
  1060. m := make(map[string]int)
  1061. defer delete(m)
  1062. m["Bob"] = 2
  1063. m["Ted"] = 5
  1064. fmt.println(m["Bob"])
  1065. delete_key(&m, "Ted")
  1066. // If an element of a key does not exist, the zero value of the
  1067. // element will be returned. To check to see if an element exists
  1068. // can be done in two ways:
  1069. elem, ok := m["Bob"]
  1070. exists := "Bob" in m
  1071. _, _ = elem, ok
  1072. _ = exists
  1073. }
  1074. implicit_selector_expression :: proc() {
  1075. fmt.println("\n# implicit selector expression")
  1076. Foo :: enum {A, B, C}
  1077. f: Foo
  1078. f = Foo.A
  1079. f = .A
  1080. BAR :: bit_set[Foo]{.B, .C}
  1081. switch f {
  1082. case .A:
  1083. fmt.println("HITHER")
  1084. case .B:
  1085. fmt.println("NEVER")
  1086. case .C:
  1087. fmt.println("FOREVER")
  1088. }
  1089. my_map := make(map[Foo]int)
  1090. defer delete(my_map)
  1091. my_map[.A] = 123
  1092. my_map[Foo.B] = 345
  1093. fmt.println(my_map[.A] + my_map[Foo.B] + my_map[.C])
  1094. }
  1095. partial_switch :: proc() {
  1096. fmt.println("\n# partial_switch")
  1097. { // enum
  1098. Foo :: enum {
  1099. A,
  1100. B,
  1101. C,
  1102. D,
  1103. }
  1104. f := Foo.A
  1105. switch f {
  1106. case .A: fmt.println("A")
  1107. case .B: fmt.println("B")
  1108. case .C: fmt.println("C")
  1109. case .D: fmt.println("D")
  1110. case: fmt.println("?")
  1111. }
  1112. #partial switch f {
  1113. case .A: fmt.println("A")
  1114. case .D: fmt.println("D")
  1115. }
  1116. }
  1117. { // union
  1118. Foo :: union {int, bool}
  1119. f: Foo = 123
  1120. switch _ in f {
  1121. case int: fmt.println("int")
  1122. case bool: fmt.println("bool")
  1123. case:
  1124. }
  1125. #partial switch _ in f {
  1126. case bool: fmt.println("bool")
  1127. }
  1128. }
  1129. }
  1130. cstring_example :: proc() {
  1131. fmt.println("\n# cstring_example")
  1132. W :: "Hellope"
  1133. X :: cstring(W)
  1134. Y :: string(X)
  1135. w := W
  1136. _ = w
  1137. x: cstring = X
  1138. y: string = Y
  1139. z := string(x)
  1140. fmt.println(x, y, z)
  1141. fmt.println(len(x), len(y), len(z))
  1142. fmt.println(len(W), len(X), len(Y))
  1143. // IMPORTANT NOTE for cstring variables
  1144. // len(cstring) is O(N)
  1145. // cast(string)cstring is O(N)
  1146. }
  1147. bit_set_type :: proc() {
  1148. fmt.println("\n# bit_set type")
  1149. {
  1150. Day :: enum {
  1151. Sunday,
  1152. Monday,
  1153. Tuesday,
  1154. Wednesday,
  1155. Thursday,
  1156. Friday,
  1157. Saturday,
  1158. }
  1159. Days :: distinct bit_set[Day]
  1160. WEEKEND :: Days{.Sunday, .Saturday}
  1161. d: Days
  1162. d = {.Sunday, .Monday}
  1163. e := d + WEEKEND
  1164. e += {.Monday}
  1165. fmt.println(d, e)
  1166. ok := .Saturday in e // `in` is only allowed for `map` and `bit_set` types
  1167. fmt.println(ok)
  1168. if .Saturday in e {
  1169. fmt.println("Saturday in", e)
  1170. }
  1171. X :: .Saturday in WEEKEND // Constant evaluation
  1172. fmt.println(X)
  1173. fmt.println("Cardinality:", card(e))
  1174. }
  1175. {
  1176. x: bit_set['A'..='Z']
  1177. #assert(size_of(x) == size_of(u32))
  1178. y: bit_set[0..=8; u16]
  1179. fmt.println(typeid_of(type_of(x))) // bit_set[A..=Z]
  1180. fmt.println(typeid_of(type_of(y))) // bit_set[0..=8; u16]
  1181. x += {'F'}
  1182. assert('F' in x)
  1183. x -= {'F'}
  1184. assert('F' not_in x)
  1185. y += {1, 4, 2}
  1186. assert(2 in y)
  1187. }
  1188. {
  1189. Letters :: bit_set['A'..='Z']
  1190. a := Letters{'A', 'B'}
  1191. b := Letters{'A', 'B', 'C', 'D', 'F'}
  1192. c := Letters{'A', 'B'}
  1193. assert(a <= b) // 'a' is a subset of 'b'
  1194. assert(b >= a) // 'b' is a superset of 'a'
  1195. assert(a < b) // 'a' is a strict subset of 'b'
  1196. assert(b > a) // 'b' is a strict superset of 'a'
  1197. assert(!(a < c)) // 'a' is a not strict subset of 'c'
  1198. assert(!(c > a)) // 'c' is a not strict superset of 'a'
  1199. }
  1200. }
  1201. deferred_procedure_associations :: proc() {
  1202. fmt.println("\n# deferred procedure associations")
  1203. @(deferred_out=closure)
  1204. open :: proc(s: string) -> bool {
  1205. fmt.println(s)
  1206. return true
  1207. }
  1208. closure :: proc(ok: bool) {
  1209. fmt.println("Goodbye?", ok)
  1210. }
  1211. if open("Welcome") {
  1212. fmt.println("Something in the middle, mate.")
  1213. }
  1214. }
  1215. reflection :: proc() {
  1216. fmt.println("\n# reflection")
  1217. Foo :: struct {
  1218. x: int `tag1`,
  1219. y: string `json:"y_field"`,
  1220. z: bool, // no tag
  1221. }
  1222. id := typeid_of(Foo)
  1223. names := reflect.struct_field_names(id)
  1224. types := reflect.struct_field_types(id)
  1225. tags := reflect.struct_field_tags(id)
  1226. assert(len(names) == len(types) && len(names) == len(tags))
  1227. fmt.println("Foo :: struct {")
  1228. for tag, i in tags {
  1229. name, type := names[i], types[i]
  1230. if tag != "" {
  1231. fmt.printf("\t%s: %T `%s`,\n", name, type, tag)
  1232. } else {
  1233. fmt.printf("\t%s: %T,\n", name, type)
  1234. }
  1235. }
  1236. fmt.println("}")
  1237. for tag, i in tags {
  1238. if val, ok := reflect.struct_tag_lookup(tag, "json"); ok {
  1239. fmt.printf("json: %s -> %s\n", names[i], val)
  1240. }
  1241. }
  1242. }
  1243. quaternions :: proc() {
  1244. // Not just an April Fool's Joke any more, but a fully working thing!
  1245. fmt.println("\n# quaternions")
  1246. { // Quaternion operations
  1247. q := 1 + 2i + 3j + 4k
  1248. r := quaternion(real=5, imag=6, jmag=7, kmag=8)
  1249. t := q * r
  1250. fmt.printf("(%v) * (%v) = %v\n", q, r, t)
  1251. v := q / r
  1252. fmt.printf("(%v) / (%v) = %v\n", q, r, v)
  1253. u := q + r
  1254. fmt.printf("(%v) + (%v) = %v\n", q, r, u)
  1255. s := q - r
  1256. fmt.printf("(%v) - (%v) = %v\n", q, r, s)
  1257. }
  1258. { // The quaternion types
  1259. q128: quaternion128 // 4xf32
  1260. q256: quaternion256 // 4xf64
  1261. q128 = quaternion(w=1, x=0, y=0, z=0)
  1262. q256 = 1 // quaternion(x=0, y=0, z=0, w=1)
  1263. // NOTE: The internal memory layout of a quaternion is xyzw
  1264. }
  1265. { // Built-in procedures
  1266. q := 1 + 2i + 3j + 4k
  1267. fmt.println("q =", q)
  1268. fmt.println("real(q) =", real(q))
  1269. fmt.println("imag(q) =", imag(q))
  1270. fmt.println("jmag(q) =", jmag(q))
  1271. fmt.println("kmag(q) =", kmag(q))
  1272. fmt.println("conj(q) =", conj(q))
  1273. fmt.println("abs(q) =", abs(q))
  1274. }
  1275. { // Conversion of a complex type to a quaternion type
  1276. c := 1 + 2i
  1277. q := quaternion256(c)
  1278. fmt.println(c)
  1279. fmt.println(q)
  1280. }
  1281. { // Memory layout of Quaternions
  1282. q := 1 + 2i + 3j + 4k
  1283. a := transmute([4]f64)q
  1284. fmt.println("Quaternion memory layout: xyzw/(ijkr)")
  1285. fmt.println(q) // 1.000+2.000i+3.000j+4.000k
  1286. fmt.println(a) // [2.000, 3.000, 4.000, 1.000]
  1287. }
  1288. }
  1289. unroll_for_statement :: proc() {
  1290. fmt.println("\n#'#unroll for' statements")
  1291. // '#unroll for' works the same as if the 'inline' prefix did not
  1292. // exist but these ranged loops are explicitly unrolled which can
  1293. // be very very useful for certain optimizations
  1294. fmt.println("Ranges")
  1295. #unroll for x, i in 1..<4 {
  1296. fmt.println(x, i)
  1297. }
  1298. fmt.println("Strings")
  1299. #unroll for r, i in "Hello, 世界" {
  1300. fmt.println(r, i)
  1301. }
  1302. fmt.println("Arrays")
  1303. #unroll for elem, idx in ([4]int{1, 4, 9, 16}) {
  1304. fmt.println(elem, idx)
  1305. }
  1306. Foo_Enum :: enum {
  1307. A = 1,
  1308. B,
  1309. C = 6,
  1310. D,
  1311. }
  1312. fmt.println("Enum types")
  1313. #unroll for elem, idx in Foo_Enum {
  1314. fmt.println(elem, idx)
  1315. }
  1316. }
  1317. where_clauses :: proc() {
  1318. fmt.println("\n#procedure 'where' clauses")
  1319. { // Sanity checks
  1320. simple_sanity_check :: proc(x: [2]int)
  1321. where len(x) > 1,
  1322. type_of(x) == [2]int {
  1323. fmt.println(x)
  1324. }
  1325. }
  1326. { // Parametric polymorphism checks
  1327. cross_2d :: proc(a, b: $T/[2]$E) -> E
  1328. where intrinsics.type_is_numeric(E) {
  1329. return a.x*b.y - a.y*b.x
  1330. }
  1331. cross_3d :: proc(a, b: $T/[3]$E) -> T
  1332. where intrinsics.type_is_numeric(E) {
  1333. x := a.y*b.z - a.z*b.y
  1334. y := a.z*b.x - a.x*b.z
  1335. z := a.x*b.y - a.y*b.z
  1336. return T{x, y, z}
  1337. }
  1338. a := [2]int{1, 2}
  1339. b := [2]int{5, -3}
  1340. fmt.println(cross_2d(a, b))
  1341. x := [3]f32{1, 4, 9}
  1342. y := [3]f32{-5, 0, 3}
  1343. fmt.println(cross_3d(x, y))
  1344. // Failure case
  1345. // i := [2]bool{true, false}
  1346. // j := [2]bool{false, true}
  1347. // fmt.println(cross_2d(i, j))
  1348. }
  1349. { // Procedure groups usage
  1350. foo :: proc(x: [$N]int) -> bool
  1351. where N > 2 {
  1352. fmt.println(#procedure, "was called with the parameter", x)
  1353. return true
  1354. }
  1355. bar :: proc(x: [$N]int) -> bool
  1356. where 0 < N,
  1357. N <= 2 {
  1358. fmt.println(#procedure, "was called with the parameter", x)
  1359. return false
  1360. }
  1361. baz :: proc{foo, bar}
  1362. x := [3]int{1, 2, 3}
  1363. y := [2]int{4, 9}
  1364. ok_x := baz(x)
  1365. ok_y := baz(y)
  1366. assert(ok_x == true)
  1367. assert(ok_y == false)
  1368. }
  1369. { // Record types
  1370. Foo :: struct($T: typeid, $N: int)
  1371. where intrinsics.type_is_integer(T),
  1372. N > 2 {
  1373. x: [N]T,
  1374. y: [N-2]T,
  1375. }
  1376. T :: i32
  1377. N :: 5
  1378. f: Foo(T, N)
  1379. #assert(size_of(f) == (N+N-2)*size_of(T))
  1380. }
  1381. }
  1382. when ODIN_OS == .Windows {
  1383. foreign import kernel32 "system:kernel32.lib"
  1384. }
  1385. foreign_system :: proc() {
  1386. fmt.println("\n#foreign system")
  1387. when ODIN_OS == .Windows {
  1388. // It is sometimes necessarily to interface with foreign code,
  1389. // such as a C library. In Odin, this is achieved through the
  1390. // foreign system. You can “import” a library into the code
  1391. // using the same semantics as a normal import declaration.
  1392. // This foreign import declaration will create a
  1393. // “foreign import name” which can then be used to associate
  1394. // entities within a foreign block.
  1395. foreign kernel32 {
  1396. ExitProcess :: proc "stdcall" (exit_code: u32) ---
  1397. }
  1398. // Foreign procedure declarations have the cdecl/c calling
  1399. // convention by default unless specified otherwise. Due to
  1400. // foreign procedures do not have a body declared within this
  1401. // code, you need append the --- symbol to the end to distinguish
  1402. // it as a procedure literal without a body and not a procedure type.
  1403. // The attributes system can be used to change specific properties
  1404. // of entities declared within a block:
  1405. @(default_calling_convention = "std")
  1406. foreign kernel32 {
  1407. @(link_name="GetLastError") get_last_error :: proc() -> i32 ---
  1408. }
  1409. // Example using the link_prefix attribute
  1410. @(default_calling_convention = "std")
  1411. @(link_prefix = "Get")
  1412. foreign kernel32 {
  1413. LastError :: proc() -> i32 ---
  1414. }
  1415. }
  1416. }
  1417. ranged_fields_for_array_compound_literals :: proc() {
  1418. fmt.println("\n#ranged fields for array compound literals")
  1419. { // Normal Array Literal
  1420. foo := [?]int{1, 4, 9, 16}
  1421. fmt.println(foo)
  1422. }
  1423. { // Indexed
  1424. foo := [?]int{
  1425. 3 = 16,
  1426. 1 = 4,
  1427. 2 = 9,
  1428. 0 = 1,
  1429. }
  1430. fmt.println(foo)
  1431. }
  1432. { // Ranges
  1433. i := 2
  1434. foo := [?]int {
  1435. 0 = 123,
  1436. 5..=9 = 54,
  1437. 10..<16 = i*3 + (i-1)*2,
  1438. }
  1439. #assert(len(foo) == 16)
  1440. fmt.println(foo) // [123, 0, 0, 0, 0, 54, 54, 54, 54, 54, 8, 8, 8, 8, 8]
  1441. }
  1442. { // Slice and Dynamic Array support
  1443. i := 2
  1444. foo_slice := []int {
  1445. 0 = 123,
  1446. 5..=9 = 54,
  1447. 10..<16 = i*3 + (i-1)*2,
  1448. }
  1449. assert(len(foo_slice) == 16)
  1450. fmt.println(foo_slice) // [123, 0, 0, 0, 0, 54, 54, 54, 54, 54, 8, 8, 8, 8, 8]
  1451. foo_dynamic_array := [dynamic]int {
  1452. 0 = 123,
  1453. 5..=9 = 54,
  1454. 10..<16 = i*3 + (i-1)*2,
  1455. }
  1456. assert(len(foo_dynamic_array) == 16)
  1457. fmt.println(foo_dynamic_array) // [123, 0, 0, 0, 0, 54, 54, 54, 54, 54, 8, 8, 8, 8, 8]
  1458. }
  1459. }
  1460. deprecated_attribute :: proc() {
  1461. @(deprecated="Use foo_v2 instead")
  1462. foo_v1 :: proc(x: int) {
  1463. fmt.println("foo_v1")
  1464. }
  1465. foo_v2 :: proc(x: int) {
  1466. fmt.println("foo_v2")
  1467. }
  1468. // NOTE: Uncomment to see the warning messages
  1469. // foo_v1(1)
  1470. }
  1471. range_statements_with_multiple_return_values :: proc() {
  1472. fmt.println("\n#range statements with multiple return values")
  1473. My_Iterator :: struct {
  1474. index: int,
  1475. data: []i32,
  1476. }
  1477. make_my_iterator :: proc(data: []i32) -> My_Iterator {
  1478. return My_Iterator{data = data}
  1479. }
  1480. my_iterator :: proc(it: ^My_Iterator) -> (val: i32, idx: int, cond: bool) {
  1481. if cond = it.index < len(it.data); cond {
  1482. val = it.data[it.index]
  1483. idx = it.index
  1484. it.index += 1
  1485. }
  1486. return
  1487. }
  1488. data := make([]i32, 6)
  1489. for _, i in data {
  1490. data[i] = i32(i*i)
  1491. }
  1492. { // Manual Style
  1493. it := make_my_iterator(data)
  1494. for {
  1495. val, _, cond := my_iterator(&it)
  1496. if !cond {
  1497. break
  1498. }
  1499. fmt.println(val)
  1500. }
  1501. }
  1502. { // or_break
  1503. it := make_my_iterator(data)
  1504. loop: for {
  1505. val, _ := my_iterator(&it) or_break loop
  1506. fmt.println(val)
  1507. }
  1508. }
  1509. { // first value
  1510. it := make_my_iterator(data)
  1511. for val in my_iterator(&it) {
  1512. fmt.println(val)
  1513. }
  1514. }
  1515. { // first and second value
  1516. it := make_my_iterator(data)
  1517. for val, idx in my_iterator(&it) {
  1518. fmt.println(val, idx)
  1519. }
  1520. }
  1521. }
  1522. soa_struct_layout :: proc() {
  1523. fmt.println("\n#SOA Struct Layout")
  1524. {
  1525. Vector3 :: struct {x, y, z: f32}
  1526. N :: 2
  1527. v_aos: [N]Vector3
  1528. v_aos[0].x = 1
  1529. v_aos[0].y = 4
  1530. v_aos[0].z = 9
  1531. fmt.println(len(v_aos))
  1532. fmt.println(v_aos[0])
  1533. fmt.println(v_aos[0].x)
  1534. fmt.println(&v_aos[0].x)
  1535. v_aos[1] = {0, 3, 4}
  1536. v_aos[1].x = 2
  1537. fmt.println(v_aos[1])
  1538. fmt.println(v_aos)
  1539. v_soa: #soa[N]Vector3
  1540. v_soa[0].x = 1
  1541. v_soa[0].y = 4
  1542. v_soa[0].z = 9
  1543. // Same syntax as AOS and treat as if it was an array
  1544. fmt.println(len(v_soa))
  1545. fmt.println(v_soa[0])
  1546. fmt.println(v_soa[0].x)
  1547. fmt.println(&v_soa[0].x)
  1548. v_soa[1] = {0, 3, 4}
  1549. v_soa[1].x = 2
  1550. fmt.println(v_soa[1])
  1551. // Can use SOA syntax if necessary
  1552. v_soa.x[0] = 1
  1553. v_soa.y[0] = 4
  1554. v_soa.z[0] = 9
  1555. fmt.println(v_soa.x[0])
  1556. // Same pointer addresses with both syntaxes
  1557. assert(&v_soa[0].x == &v_soa.x[0])
  1558. // Same fmt printing
  1559. fmt.println(v_aos)
  1560. fmt.println(v_soa)
  1561. }
  1562. {
  1563. // Works with arrays of length <= 4 which have the implicit fields xyzw/rgba
  1564. Vector3 :: distinct [3]f32
  1565. N :: 2
  1566. v_aos: [N]Vector3
  1567. v_aos[0].x = 1
  1568. v_aos[0].y = 4
  1569. v_aos[0].z = 9
  1570. v_soa: #soa[N]Vector3
  1571. v_soa[0].x = 1
  1572. v_soa[0].y = 4
  1573. v_soa[0].z = 9
  1574. }
  1575. {
  1576. // SOA Slices
  1577. // Vector3 :: struct {x, y, z: f32}
  1578. Vector3 :: struct {x: i8, y: i16, z: f32}
  1579. N :: 3
  1580. v: #soa[N]Vector3
  1581. v[0].x = 1
  1582. v[0].y = 4
  1583. v[0].z = 9
  1584. s: #soa[]Vector3
  1585. s = v[:]
  1586. assert(len(s) == N)
  1587. fmt.println(s)
  1588. fmt.println(s[0].x)
  1589. a := s[1:2]
  1590. assert(len(a) == 1)
  1591. fmt.println(a)
  1592. d: #soa[dynamic]Vector3
  1593. append_soa(&d, Vector3{1, 2, 3}, Vector3{4, 5, 9}, Vector3{-4, -4, 3})
  1594. fmt.println(d)
  1595. fmt.println(len(d))
  1596. fmt.println(cap(d))
  1597. fmt.println(d[:])
  1598. }
  1599. { // soa_zip and soa_unzip
  1600. fmt.println("\nsoa_zip and soa_unzip")
  1601. x := []i32{1, 3, 9}
  1602. y := []f32{2, 4, 16}
  1603. z := []b32{true, false, true}
  1604. // produce an #soa slice the normal slices passed
  1605. s := soa_zip(a=x, b=y, c=z)
  1606. // iterate over the #soa slice
  1607. for v, i in s {
  1608. fmt.println(v, i) // exactly the same as s[i]
  1609. // NOTE: 'v' is NOT a temporary value but has a specialized addressing mode
  1610. // which means that when accessing v.a etc, it does the correct transformation
  1611. // internally:
  1612. // s[i].a === s.a[i]
  1613. fmt.println(v.a, v.b, v.c)
  1614. }
  1615. // Recover the slices from the #soa slice
  1616. a, b, c := soa_unzip(s)
  1617. fmt.println(a, b, c)
  1618. }
  1619. }
  1620. constant_literal_expressions :: proc() {
  1621. fmt.println("\n#constant literal expressions")
  1622. Bar :: struct {x, y: f32}
  1623. Foo :: struct {a, b: int, using c: Bar}
  1624. FOO_CONST :: Foo{b = 2, a = 1, c = {3, 4}}
  1625. fmt.println(FOO_CONST.a)
  1626. fmt.println(FOO_CONST.b)
  1627. fmt.println(FOO_CONST.c)
  1628. fmt.println(FOO_CONST.c.x)
  1629. fmt.println(FOO_CONST.c.y)
  1630. fmt.println(FOO_CONST.x) // using works as expected
  1631. fmt.println(FOO_CONST.y)
  1632. fmt.println("-------")
  1633. ARRAY_CONST :: [3]int{1 = 4, 2 = 9, 0 = 1}
  1634. fmt.println(ARRAY_CONST[0])
  1635. fmt.println(ARRAY_CONST[1])
  1636. fmt.println(ARRAY_CONST[2])
  1637. fmt.println("-------")
  1638. FOO_ARRAY_DEFAULTS :: [3]Foo{{}, {}, {}}
  1639. fmt.println(FOO_ARRAY_DEFAULTS[2].x)
  1640. fmt.println("-------")
  1641. Baz :: enum{A=5, B, C, D}
  1642. ENUM_ARRAY_CONST :: [Baz]int{.A ..= .C = 1, .D = 16}
  1643. fmt.println(ENUM_ARRAY_CONST[.A])
  1644. fmt.println(ENUM_ARRAY_CONST[.B])
  1645. fmt.println(ENUM_ARRAY_CONST[.C])
  1646. fmt.println(ENUM_ARRAY_CONST[.D])
  1647. fmt.println("-------")
  1648. Sparse_Baz :: enum{A=5, B, C, D=16}
  1649. #assert(len(Sparse_Baz) < len(#sparse[Sparse_Baz]int))
  1650. SPARSE_ENUM_ARRAY_CONST :: #sparse[Sparse_Baz]int{.A ..= .C = 1, .D = 16}
  1651. fmt.println(SPARSE_ENUM_ARRAY_CONST[.A])
  1652. fmt.println(SPARSE_ENUM_ARRAY_CONST[.B])
  1653. fmt.println(SPARSE_ENUM_ARRAY_CONST[.C])
  1654. fmt.println(SPARSE_ENUM_ARRAY_CONST[.D])
  1655. fmt.println("-------")
  1656. STRING_CONST :: "Hellope!"
  1657. fmt.println(STRING_CONST[0])
  1658. fmt.println(STRING_CONST[2])
  1659. fmt.println(STRING_CONST[3])
  1660. fmt.println(STRING_CONST[0:5])
  1661. fmt.println(STRING_CONST[3:][:4])
  1662. }
  1663. union_maybe :: proc() {
  1664. fmt.println("\n#union based maybe")
  1665. // NOTE: This is already built-in, and this is just a reimplementation to explain the behaviour
  1666. Maybe :: union($T: typeid) {T}
  1667. i: Maybe(u8)
  1668. p: Maybe(^u8) // No tag is stored for pointers, nil is the sentinel value
  1669. // Tag size will be as small as needed for the number of variants
  1670. #assert(size_of(i) == size_of(u8) + size_of(u8))
  1671. // No need to store a tag here, the `nil` state is shared with the variant's `nil`
  1672. #assert(size_of(p) == size_of(^u8))
  1673. i = 123
  1674. x := i.?
  1675. y, y_ok := p.?
  1676. p = &x
  1677. z, z_ok := p.?
  1678. fmt.println(i, p)
  1679. fmt.println(x, &x)
  1680. fmt.println(y, y_ok)
  1681. fmt.println(z, z_ok)
  1682. }
  1683. dummy_procedure :: proc() {
  1684. fmt.println("dummy_procedure")
  1685. }
  1686. explicit_context_definition :: proc "c" () {
  1687. // Try commenting the following statement out below
  1688. context = runtime.default_context()
  1689. fmt.println("\n#explicit context definition")
  1690. dummy_procedure()
  1691. }
  1692. relative_data_types :: proc() {
  1693. fmt.println("\n#relative data types")
  1694. x: int = 123
  1695. ptr: #relative(i16) ^int
  1696. ptr = &x
  1697. fmt.println(ptr^)
  1698. arr := [3]int{1, 2, 3}
  1699. multi_ptr: #relative(i16) [^]int
  1700. multi_ptr = &arr[0]
  1701. fmt.println(multi_ptr)
  1702. fmt.println(multi_ptr[:3])
  1703. fmt.println(multi_ptr[1])
  1704. }
  1705. or_else_operator :: proc() {
  1706. fmt.println("\n#'or_else'")
  1707. {
  1708. m: map[string]int
  1709. i: int
  1710. ok: bool
  1711. if i, ok = m["hellope"]; !ok {
  1712. i = 123
  1713. }
  1714. // The above can be mapped to 'or_else'
  1715. i = m["hellope"] or_else 123
  1716. assert(i == 123)
  1717. }
  1718. {
  1719. // 'or_else' can be used with type assertions too, as they
  1720. // have optional ok semantics
  1721. v: union{int, f64}
  1722. i: int
  1723. i = v.(int) or_else 123
  1724. i = v.? or_else 123 // Type inference magic
  1725. assert(i == 123)
  1726. m: Maybe(int)
  1727. i = m.? or_else 456
  1728. assert(i == 456)
  1729. }
  1730. }
  1731. or_return_operator :: proc() {
  1732. fmt.println("\n#'or_return'")
  1733. // The concept of 'or_return' will work by popping off the end value in a multiple
  1734. // valued expression and checking whether it was not 'nil' or 'false', and if so,
  1735. // set the end return value to value if possible. If the procedure only has one
  1736. // return value, it will do a simple return. If the procedure had multiple return
  1737. // values, 'or_return' will require that all parameters be named so that the end
  1738. // value could be assigned to by name and then an empty return could be called.
  1739. Error :: enum {
  1740. None,
  1741. Something_Bad,
  1742. Something_Worse,
  1743. The_Worst,
  1744. Your_Mum,
  1745. }
  1746. caller_1 :: proc() -> Error {
  1747. return .None
  1748. }
  1749. caller_2 :: proc() -> (int, Error) {
  1750. return 123, .None
  1751. }
  1752. caller_3 :: proc() -> (int, int, Error) {
  1753. return 123, 345, .None
  1754. }
  1755. foo_1 :: proc() -> Error {
  1756. // This can be a common idiom in many code bases
  1757. n0, err := caller_2()
  1758. if err != nil {
  1759. return err
  1760. }
  1761. // The above idiom can be transformed into the following
  1762. n1 := caller_2() or_return
  1763. // And if the expression is 1-valued, it can be used like this
  1764. caller_1() or_return
  1765. // which is functionally equivalent to
  1766. if err1 := caller_1(); err1 != nil {
  1767. return err1
  1768. }
  1769. // Multiple return values still work with 'or_return' as it only
  1770. // pops off the end value in the multi-valued expression
  1771. n0, n1 = caller_3() or_return
  1772. return .None
  1773. }
  1774. foo_2 :: proc() -> (n: int, err: Error) {
  1775. // It is more common that your procedure turns multiple values
  1776. // If 'or_return' is used within a procedure multiple parameters (2+),
  1777. // then all the parameters must be named so that the remaining parameters
  1778. // so that a bare 'return' statement can be used
  1779. // This can be a common idiom in many code bases
  1780. x: int
  1781. x, err = caller_2()
  1782. if err != nil {
  1783. return
  1784. }
  1785. // The above idiom can be transformed into the following
  1786. y := caller_2() or_return
  1787. _ = y
  1788. // And if the expression is 1-valued, it can be used like this
  1789. caller_1() or_return
  1790. // which is functionally equivalent to
  1791. if err1 := caller_1(); err1 != nil {
  1792. err = err1
  1793. return
  1794. }
  1795. // If using a non-bare 'return' statement is required, setting the return values
  1796. // using the normal idiom is a better choice and clearer to read.
  1797. if z, zerr := caller_2(); zerr != nil {
  1798. return -345 * z, zerr
  1799. }
  1800. defer if err != nil {
  1801. fmt.println("Error in", #procedure, ":" , err)
  1802. }
  1803. n = 123
  1804. return
  1805. }
  1806. foo_1()
  1807. foo_2()
  1808. }
  1809. or_break_and_or_continue_operators :: proc() {
  1810. fmt.println("\n#'or_break' and 'or_continue'")
  1811. // The concept of 'or_break' and 'or_continue' is very similar to that of 'or_return'.
  1812. // The difference is that unlike 'or_return', the value does not get returned from
  1813. // the current procedure but rather discarded if it is 'false' or not 'nil', and then
  1814. // the specified branch (i.e. break or_continue).
  1815. // The or branch expression can be labelled if a specific statement needs to be used.
  1816. Error :: enum {
  1817. None,
  1818. Something_Bad,
  1819. Something_Worse,
  1820. The_Worst,
  1821. Your_Mum,
  1822. }
  1823. caller_1 :: proc() -> Error {
  1824. return .Something_Bad
  1825. }
  1826. caller_2 :: proc() -> (int, Error) {
  1827. return 123, .Something_Worse
  1828. }
  1829. caller_3 :: proc() -> (int, int, Error) {
  1830. return 123, 345, .None
  1831. }
  1832. for { // common approach
  1833. err := caller_1()
  1834. if err != nil {
  1835. break
  1836. }
  1837. }
  1838. for { // or_break approach
  1839. caller_1() or_break
  1840. }
  1841. for { // or_break approach with multiple values
  1842. n := caller_2() or_break
  1843. _ = n
  1844. }
  1845. loop: for { // or_break approach with named label
  1846. n := caller_2() or_break loop
  1847. _ = n
  1848. }
  1849. for { // or_continue
  1850. x, y := caller_3() or_continue
  1851. _, _ = x, y
  1852. break
  1853. }
  1854. continue_loop: for { // or_continue with named label
  1855. x, y := caller_3() or_continue continue_loop
  1856. _, _ = x, y
  1857. break
  1858. }
  1859. }
  1860. arbitrary_precision_mathematics :: proc() {
  1861. fmt.println("\n# core:math/big")
  1862. print_bigint :: proc(name: string, a: ^big.Int, base := i8(10), print_name := true, newline := true, print_extra_info := true) {
  1863. big.assert_if_nil(a)
  1864. as, err := big.itoa(a, base)
  1865. defer delete(as)
  1866. cb := big.internal_count_bits(a)
  1867. if print_name {
  1868. fmt.printf(name)
  1869. }
  1870. if err != nil {
  1871. fmt.printf(" (Error: %v) ", err)
  1872. }
  1873. fmt.printf(as)
  1874. if print_extra_info {
  1875. fmt.printf(" (base: %v, bits: %v, digits: %v)", base, cb, a.used)
  1876. }
  1877. if newline {
  1878. fmt.println()
  1879. }
  1880. }
  1881. a, b, c, d, e, f, res := &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}, &big.Int{}
  1882. defer big.destroy(a, b, c, d, e, f, res)
  1883. // How many bits should the random prime be?
  1884. bits := 64
  1885. // Number of Rabin-Miller trials, -1 for automatic.
  1886. trials := -1
  1887. // Default prime generation flags
  1888. flags := big.Primality_Flags{}
  1889. err := big.internal_random_prime(a, bits, trials, flags)
  1890. if err != nil {
  1891. fmt.printf("Error %v while generating random prime.\n", err)
  1892. } else {
  1893. print_bigint("Random Prime A: ", a, 10)
  1894. fmt.printf("Random number iterations until prime found: %v\n", big.RANDOM_PRIME_ITERATIONS_USED)
  1895. }
  1896. // If we want to pack this Int into a buffer of u32, how many do we need?
  1897. count := big.internal_int_pack_count(a, u32)
  1898. buf := make([]u32, count)
  1899. defer delete(buf)
  1900. written: int
  1901. written, err = big.internal_int_pack(a, buf)
  1902. fmt.printf("\nPacked into u32 buf: %v | err: %v | written: %v\n", buf, err, written)
  1903. // If we want to pack this Int into a buffer of bytes of which only the bottom 6 bits are used, how many do we need?
  1904. nails := 2
  1905. count = big.internal_int_pack_count(a, u8, nails)
  1906. byte_buf := make([]u8, count)
  1907. defer delete(byte_buf)
  1908. written, err = big.internal_int_pack(a, byte_buf, nails)
  1909. fmt.printf("\nPacked into buf of 6-bit bytes: %v | err: %v | written: %v\n", byte_buf, err, written)
  1910. // Pick another random big Int, not necesssarily prime.
  1911. err = big.random(b, 2048)
  1912. print_bigint("\n2048 bit random number: ", b)
  1913. // Calculate GCD + LCM in one fell swoop
  1914. big.gcd_lcm(c, d, a, b)
  1915. print_bigint("\nGCD of random prime A and random number B: ", c)
  1916. print_bigint("\nLCM of random prime A and random number B (in base 36): ", d, 36)
  1917. }
  1918. matrix_type :: proc() {
  1919. fmt.println("\n# matrix type")
  1920. // A matrix is a mathematical type built into Odin. It is a regular array of numbers,
  1921. // arranged in rows and columns
  1922. {
  1923. // The following represents a matrix that has 2 rows and 3 columns
  1924. m: matrix[2, 3]f32
  1925. m = matrix[2, 3]f32{
  1926. 1, 9, -13,
  1927. 20, 5, -6,
  1928. }
  1929. // Element types of integers, float, and complex numbers are supported by matrices.
  1930. // There is no support for booleans, quaternions, or any compound type.
  1931. // Indexing a matrix can be used with the matrix indexing syntax
  1932. // This mirrors othe type usages: type on the left, usage on the right
  1933. elem := m[1, 2] // row 1, column 2
  1934. assert(elem == -6)
  1935. // Scalars act as if they are scaled identity matrices
  1936. // and can be assigned to matrices as them
  1937. b := matrix[2, 2]f32{}
  1938. f := f32(3)
  1939. b = f
  1940. fmt.println("b", b)
  1941. fmt.println("b == f", b == f)
  1942. }
  1943. { // Matrices support multiplication between matrices
  1944. a := matrix[2, 3]f32{
  1945. 2, 3, 1,
  1946. 4, 5, 0,
  1947. }
  1948. b := matrix[3, 2]f32{
  1949. 1, 2,
  1950. 3, 4,
  1951. 5, 6,
  1952. }
  1953. fmt.println("a", a)
  1954. fmt.println("b", b)
  1955. c := a * b
  1956. #assert(type_of(c) == matrix[2, 2]f32)
  1957. fmt.println("c = a * b", c)
  1958. }
  1959. { // Matrices support multiplication between matrices and arrays
  1960. m := matrix[4, 4]f32{
  1961. 1, 2, 3, 4,
  1962. 5, 5, 4, 2,
  1963. 0, 1, 3, 0,
  1964. 0, 1, 4, 1,
  1965. }
  1966. v := [4]f32{1, 5, 4, 3}
  1967. // treating 'v' as a column vector
  1968. fmt.println("m * v", m * v)
  1969. // treating 'v' as a row vector
  1970. fmt.println("v * m", v * m)
  1971. // Support with non-square matrices
  1972. s := matrix[2, 4]f32{ // [4][2]f32
  1973. 2, 4, 3, 1,
  1974. 7, 8, 6, 5,
  1975. }
  1976. w := [2]f32{1, 2}
  1977. r: [4]f32 = w * s
  1978. fmt.println("r", r)
  1979. }
  1980. { // Component-wise operations
  1981. // if the element type supports it
  1982. // Not support for '/', '%', or '%%' operations
  1983. a := matrix[2, 2]i32{
  1984. 1, 2,
  1985. 3, 4,
  1986. }
  1987. b := matrix[2, 2]i32{
  1988. -5, 1,
  1989. 9, -7,
  1990. }
  1991. c0 := a + b
  1992. c1 := a - b
  1993. c2 := a & b
  1994. c3 := a | b
  1995. c4 := a ~ b
  1996. c5 := a &~ b
  1997. // component-wise multiplication
  1998. // since a * b would be a standard matrix multiplication
  1999. c6 := intrinsics.hadamard_product(a, b)
  2000. fmt.println("a + b", c0)
  2001. fmt.println("a - b", c1)
  2002. fmt.println("a & b", c2)
  2003. fmt.println("a | b", c3)
  2004. fmt.println("a ~ b", c4)
  2005. fmt.println("a &~ b", c5)
  2006. fmt.println("hadamard_product(a, b)", c6)
  2007. }
  2008. { // Submatrix casting square matrices
  2009. // Casting a square matrix to another square matrix with same element type
  2010. // is supported.
  2011. // If the cast is to a smaller matrix type, the top-left submatrix is taken.
  2012. // If the cast is to a larger matrix type, the matrix is extended with zeros
  2013. // everywhere and ones in the diagonal for the unfilled elements of the
  2014. // extended matrix.
  2015. mat2 :: distinct matrix[2, 2]f32
  2016. mat4 :: distinct matrix[4, 4]f32
  2017. m2 := mat2{
  2018. 1, 3,
  2019. 2, 4,
  2020. }
  2021. m4 := mat4(m2)
  2022. assert(m4[2, 2] == 1)
  2023. assert(m4[3, 3] == 1)
  2024. fmt.printf("m2 %#v\n", m2)
  2025. fmt.println("m4", m4)
  2026. fmt.println("mat2(m4)", mat2(m4))
  2027. assert(mat2(m4) == m2)
  2028. b4 := mat4{
  2029. 1, 2, 0, 0,
  2030. 3, 4, 0, 0,
  2031. 5, 0, 6, 0,
  2032. 0, 7, 0, 8,
  2033. }
  2034. fmt.println("b4", intrinsics.matrix_flatten(b4))
  2035. }
  2036. { // Casting non-square matrices
  2037. // Casting a matrix to another matrix is allowed as long as they share
  2038. // the same element type and the number of elements (rows*columns).
  2039. // Matrices in Odin are stored in column-major order, which means
  2040. // the casts will preserve this element order.
  2041. mat2x4 :: distinct matrix[2, 4]f32
  2042. mat4x2 :: distinct matrix[4, 2]f32
  2043. x := mat2x4{
  2044. 1, 3, 5, 7,
  2045. 2, 4, 6, 8,
  2046. }
  2047. y := mat4x2(x)
  2048. fmt.println("x", x)
  2049. fmt.println("y", y)
  2050. }
  2051. // TECHNICAL INFORMATION: the internal representation of a matrix in Odin is stored
  2052. // in column-major format
  2053. // e.g. matrix[2, 3]f32 is internally [3][2]f32 (with different a alignment requirement)
  2054. // Column-major is used in order to utilize (SIMD) vector instructions effectively on
  2055. // modern hardware, if possible.
  2056. //
  2057. // Unlike normal arrays, matrices try to maximize alignment to allow for the (SIMD) vectorization
  2058. // properties whilst keeping zero padding (either between columns or at the end of the type).
  2059. //
  2060. // Zero padding is a compromise for use with third-party libraries, instead of optimizing for performance.
  2061. // Padding between columns was not taken even if that would have allowed each column to be loaded
  2062. // individually into a SIMD register with the correct alignment properties.
  2063. //
  2064. // Currently, matrices are limited to a maximum of 16 elements (rows*columns), and a minimum of 1 element.
  2065. // This is because matrices are stored as values (not a reference type), and thus operations on them will
  2066. // be stored on the stack. Restricting the maximum element count minimizing the possibility of stack overflows.
  2067. // 'intrinsics' Procedures (Compiler Level)
  2068. // transpose(m)
  2069. // transposes a matrix
  2070. // outer_product(a, b)
  2071. // takes two array-like data types and returns the outer product
  2072. // of the values in a matrix
  2073. // hadamard_product(a, b)
  2074. // component-wise multiplication of two matrices of the same type
  2075. // matrix_flatten(m)
  2076. // converts the matrix into a flatten array of elements
  2077. // in column-major order
  2078. // Example:
  2079. // m := matrix[2, 2]f32{
  2080. // x0, x1,
  2081. // y0, y1,
  2082. // }
  2083. // array: [4]f32 = matrix_flatten(m)
  2084. // assert(array == {x0, y0, x1, y1})
  2085. // conj(x)
  2086. // conjugates the elements of a matrix for complex element types only
  2087. // Procedures in "core:math/linalg" and related (Runtime Level) (all square matrix procedures)
  2088. // determinant(m)
  2089. // adjugate(m)
  2090. // inverse(m)
  2091. // inverse_transpose(m)
  2092. // hermitian_adjoint(m)
  2093. // trace(m)
  2094. // matrix_minor(m)
  2095. }
  2096. bit_field_type :: proc() {
  2097. fmt.println("\n# bit_field type")
  2098. // A `bit_field` is a record type in Odin that is akin to a bit-packed struct.
  2099. // IMPORTNAT NOTE: `bit_field` is NOT equivalent to `bit_set` as it has different sematics and use cases.
  2100. {
  2101. // `bit_field` fields are accessed by using a dot:
  2102. Foo :: bit_field u16 { // backing type must be an integer or array of integers
  2103. x: i32 | 3, // signed integers will be signed extended on use
  2104. y: u16 | 2 + 3, // general expressions
  2105. z: My_Enum | SOME_CONSTANT, // ability to define the bit-width elsewhere
  2106. w: bool | 2 when SOME_CONSTANT > 10 else 1,
  2107. }
  2108. v := Foo{}
  2109. v.x = 3 // truncates the value to fit into 3 bits
  2110. fmt.println(v.x) // accessing will convert `v.x` to an `i32` and do an appropriate sign extension
  2111. My_Enum :: enum u8 {A, B, C, D}
  2112. SOME_CONSTANT :: 7
  2113. }
  2114. {
  2115. // A `bit_field` is different from a struct in that you must specify the backing type.
  2116. // This backing type must be an integer or a fixed-length array of integers.
  2117. // This is useful if there needs to be a specific alignment or access pattern for the record.
  2118. Bar :: bit_field u32 {}
  2119. Baz :: bit_field [4]u8 {}
  2120. }
  2121. // IMPORTANT NOTES:
  2122. // * If _all_ of the fields in a bit_field are 1-bit in size and they are all booleans,
  2123. // please consider using a `bit_set` instead.
  2124. // * Odin's `bit_field` and C's bit-fields might not be compatible
  2125. // * Odin's `bit_field`s have a well defined layout (Least-Significant-Bit)
  2126. // * C's bit-fields on `struct`s are undefined and are not portable across targets and compilers
  2127. // * A `bit_field`'s field type can only be one of the following:
  2128. // * Integer
  2129. // * Boolean
  2130. // * Enum
  2131. }
  2132. main :: proc() {
  2133. /*
  2134. For More Odin Examples - https://github.com/odin-lang/examples
  2135. This repository contains examples of how certain things can be accomplished
  2136. in idiomatic Odin, allowing you learn its semantics, as well as how to use
  2137. parts of the core and vendor package collections.
  2138. */
  2139. when true {
  2140. the_basics()
  2141. control_flow()
  2142. named_proc_return_parameters()
  2143. variadic_procedures()
  2144. explicit_procedure_overloading()
  2145. struct_type()
  2146. union_type()
  2147. using_statement()
  2148. implicit_context_system()
  2149. parametric_polymorphism()
  2150. array_programming()
  2151. map_type()
  2152. implicit_selector_expression()
  2153. partial_switch()
  2154. cstring_example()
  2155. bit_set_type()
  2156. deferred_procedure_associations()
  2157. reflection()
  2158. quaternions()
  2159. unroll_for_statement()
  2160. where_clauses()
  2161. foreign_system()
  2162. ranged_fields_for_array_compound_literals()
  2163. deprecated_attribute()
  2164. range_statements_with_multiple_return_values()
  2165. threading_example()
  2166. soa_struct_layout()
  2167. constant_literal_expressions()
  2168. union_maybe()
  2169. explicit_context_definition()
  2170. relative_data_types()
  2171. or_else_operator()
  2172. or_return_operator()
  2173. or_break_and_or_continue_operators()
  2174. arbitrary_precision_mathematics()
  2175. matrix_type()
  2176. bit_field_type()
  2177. }
  2178. }