demo.odin 58 KB

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