| 1 | // Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | // [has_globals] |
| 5 | module types |
| 6 | |
| 7 | // primitives |
| 8 | pub const bool_ = Primitive{ |
| 9 | props: .boolean |
| 10 | } |
| 11 | const i8_ = Primitive{ |
| 12 | props: .integer |
| 13 | size: 8 |
| 14 | } |
| 15 | const i16_ = Primitive{ |
| 16 | props: .integer |
| 17 | size: 16 |
| 18 | } |
| 19 | const i32_ = Primitive{ |
| 20 | props: .integer |
| 21 | size: 32 |
| 22 | } |
| 23 | // TODO: represent platform specific size |
| 24 | // will this be calculated at compile time? |
| 25 | pub const int_ = Primitive{ |
| 26 | props: .integer |
| 27 | // size: 32 |
| 28 | } |
| 29 | const i64_ = Primitive{ |
| 30 | props: .integer |
| 31 | size: 64 |
| 32 | } |
| 33 | const u8_ = Primitive{ |
| 34 | props: .integer | .unsigned |
| 35 | size: 8 |
| 36 | } |
| 37 | // byte_ = Primitive{props: .integer | .unsigned, size: 8} |
| 38 | const byte_ = Alias{ |
| 39 | name: 'byte' |
| 40 | base_type: u8_ |
| 41 | } |
| 42 | const u16_ = Primitive{ |
| 43 | props: .integer | .unsigned |
| 44 | size: 16 |
| 45 | } |
| 46 | const u32_ = Primitive{ |
| 47 | props: .integer | .unsigned |
| 48 | size: 32 |
| 49 | } |
| 50 | const u64_ = Primitive{ |
| 51 | props: .integer | .unsigned |
| 52 | size: 64 |
| 53 | } |
| 54 | const f32_ = Primitive{ |
| 55 | props: .float |
| 56 | size: 32 |
| 57 | } |
| 58 | pub const f64_ = Primitive{ |
| 59 | props: .float |
| 60 | size: 64 |
| 61 | } |
| 62 | // complex / non primitives |
| 63 | // String struct is defined in cmd/v2/builtin/string.v: |
| 64 | // pub struct string { str &u8, len int, is_lit int } |
| 65 | pub const string_ = String(0) |
| 66 | const chan_ = Channel{ |
| 67 | elem_type: none |
| 68 | } |
| 69 | const char_ = Char(0) |
| 70 | const isize_ = ISize(0) |
| 71 | const usize_ = USize(0) |
| 72 | const rune_ = Rune(0) |
| 73 | pub const void_ = Void(0) |
| 74 | const nil_ = Nil(0) |
| 75 | const none_ = None(0) |
| 76 | const byteptr_ = Alias{ |
| 77 | name: 'byteptr' |
| 78 | base_type: Pointer{ |
| 79 | base_type: Type(byte_) |
| 80 | } |
| 81 | } |
| 82 | const charptr_ = Alias{ |
| 83 | name: 'charptr' |
| 84 | base_type: Pointer{ |
| 85 | base_type: Type(char_) |
| 86 | } |
| 87 | } |
| 88 | pub const voidptr_ = Alias{ |
| 89 | name: 'voidptr' |
| 90 | base_type: Pointer{ |
| 91 | base_type: Type(void_) |
| 92 | } |
| 93 | } |
| 94 | const int_literal_ = Primitive{ |
| 95 | props: .untyped | .integer |
| 96 | } |
| 97 | const float_literal_ = Primitive{ |
| 98 | props: .untyped | .float |
| 99 | } |
| 100 | // int_literal_ = IntLiteral(0) |
| 101 | // float_literal_ = FloatLiteral(0) |
| 102 | // TODO: is this what thread should be? |
| 103 | const thread_ = Thread{ |
| 104 | elem_type: none |
| 105 | } |
| 106 | |
| 107 | // NOTE: universe MUST be declared AFTER all primitive/alias/type constants above. |
| 108 | // For SSA-based backends (arm64, x64), struct literal consts need runtime init. |
| 109 | // init_universe() references bool_, int_, u8_, etc., so they must be initialized first. |
| 110 | const universe = init_universe() |
| 111 | |
| 112 | pub fn builtin_type(name string) ?Type { |
| 113 | return match name { |
| 114 | 'bool' { Type(bool_) } |
| 115 | 'i8' { Type(i8_) } |
| 116 | 'i16' { Type(i16_) } |
| 117 | 'i32' { Type(i32_) } |
| 118 | 'int' { Type(int_) } |
| 119 | 'i64' { Type(i64_) } |
| 120 | 'u8' { Type(u8_) } |
| 121 | 'byte' { Type(byte_) } |
| 122 | 'u16' { Type(u16_) } |
| 123 | 'u32' { Type(u32_) } |
| 124 | 'u64' { Type(u64_) } |
| 125 | 'f32' { Type(f32_) } |
| 126 | 'f64' { Type(f64_) } |
| 127 | 'string' { Type(string_) } |
| 128 | 'chan' { Type(chan_) } |
| 129 | 'char' { Type(char_) } |
| 130 | 'isize' { Type(isize_) } |
| 131 | 'usize' { Type(usize_) } |
| 132 | 'rune' { Type(rune_) } |
| 133 | 'void' { Type(void_) } |
| 134 | 'nil' { Type(nil_) } |
| 135 | 'none' { Type(none_) } |
| 136 | 'byteptr' { Type(byteptr_) } |
| 137 | 'charptr' { Type(charptr_) } |
| 138 | 'voidptr' { Type(voidptr_) } |
| 139 | 'int_literal' { Type(int_literal_) } |
| 140 | 'float_literal' { Type(float_literal_) } |
| 141 | 'thread' { Type(thread_) } |
| 142 | else { return none } |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | pub fn init_universe() &Scope { |
| 147 | mut universe_ := new_scope(unsafe { nil }) |
| 148 | universe_.insert('bool', Type(bool_)) |
| 149 | universe_.insert('i8', Type(i8_)) |
| 150 | universe_.insert('i16', Type(i16_)) |
| 151 | universe_.insert('i32', Type(i32_)) |
| 152 | universe_.insert('int', Type(int_)) |
| 153 | universe_.insert('i64', Type(i64_)) |
| 154 | universe_.insert('u8', Type(u8_)) |
| 155 | universe_.insert('byte', Type(byte_)) |
| 156 | universe_.insert('u16', Type(u16_)) |
| 157 | universe_.insert('u32', Type(u32_)) |
| 158 | universe_.insert('u64', Type(u64_)) |
| 159 | universe_.insert('f32', Type(f32_)) |
| 160 | universe_.insert('f64', Type(f64_)) |
| 161 | // TODO: |
| 162 | universe_.insert('string', Type(string_)) |
| 163 | universe_.insert('chan', Type(chan_)) |
| 164 | universe_.insert('char', Type(char_)) |
| 165 | universe_.insert('isize', Type(isize_)) |
| 166 | universe_.insert('usize', Type(usize_)) |
| 167 | universe_.insert('rune', Type(rune_)) |
| 168 | universe_.insert('void', Type(void_)) |
| 169 | universe_.insert('nil', Type(nil_)) |
| 170 | universe_.insert('none', Type(none_)) |
| 171 | universe_.insert('byteptr', Type(byteptr_)) |
| 172 | universe_.insert('charptr', Type(charptr_)) |
| 173 | universe_.insert('voidptr', Type(voidptr_)) |
| 174 | universe_.insert('int_literal', Type(int_literal_)) |
| 175 | universe_.insert('float_literal', Type(float_literal_)) |
| 176 | universe_.insert('float_literal', Type(float_literal_)) |
| 177 | universe_.insert('thread', Type(thread_)) |
| 178 | // Built-in marker interfaces consumed by the ownership checker |
| 179 | // (`-d ownership`): |
| 180 | // * `Copy` — explicit "always-copy" marker. Assignment of a value of |
| 181 | // this type never moves; the struct must not contain Owned |
| 182 | // fields. Useful to document intent and lock the type in. |
| 183 | // * `Owned` — explicit "move-on-assign" marker. A struct that |
| 184 | // implements `Owned` is tracked just like a `.to_owned()` |
| 185 | // string: assignment, struct-literal nesting, array/map |
| 186 | // literal nesting, and pass-by-value to a function all |
| 187 | // transfer ownership; reusing the source afterwards is a |
| 188 | // compile error. |
| 189 | // * `Drop` — explicit "needs cleanup" marker. A struct that implements |
| 190 | // `Drop` MUST provide a `drop(mut self)` method. The checker |
| 191 | // schedules `var.drop()` for every owned, non-moved binding |
| 192 | // of such a type at scope exit (the schedule is exposed for |
| 193 | // codegen via `drop_schedule`). |
| 194 | // All three are empty interfaces except `Drop`, which is satisfied by the |
| 195 | // presence of a `drop(mut self)` method. |
| 196 | universe_.insert('Copy', Type(Interface{ |
| 197 | name: 'Copy' |
| 198 | })) |
| 199 | universe_.insert('Owned', Type(Interface{ |
| 200 | name: 'Owned' |
| 201 | })) |
| 202 | universe_.insert('Drop', Type(Interface{ |
| 203 | name: 'Drop' |
| 204 | })) |
| 205 | return universe_ |
| 206 | } |
| 207 | |