demo.odin 57 KB

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