demo.odin 57 KB

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