| 1 | @[has_globals] |
| 2 | module reflection |
| 3 | |
| 4 | import arrays |
| 5 | |
| 6 | __global g_reflection = Reflection{} |
| 7 | |
| 8 | @[heap; minify] |
| 9 | pub struct Reflection { |
| 10 | pub mut: |
| 11 | modules []Module |
| 12 | funcs []Function |
| 13 | types []Type |
| 14 | type_symbols []TypeSymbol |
| 15 | enums []Enum |
| 16 | interfaces []Interface |
| 17 | strings map[int]string |
| 18 | } |
| 19 | |
| 20 | pub enum VLanguage { |
| 21 | v |
| 22 | c |
| 23 | js |
| 24 | amd64 // aka x86_64 |
| 25 | i386 |
| 26 | arm64 // 64-bit arm |
| 27 | arm32 // 32-bit arm |
| 28 | rv64 // 64-bit risc-v |
| 29 | rv32 // 32-bit risc-v |
| 30 | wasm32 |
| 31 | } |
| 32 | |
| 33 | type VType = u32 |
| 34 | |
| 35 | // max of 8 |
| 36 | pub enum VTypeFlag { |
| 37 | option |
| 38 | result |
| 39 | variadic |
| 40 | generic |
| 41 | shared_f |
| 42 | atomic_f |
| 43 | } |
| 44 | |
| 45 | pub enum VKind { |
| 46 | placeholder |
| 47 | void |
| 48 | voidptr |
| 49 | byteptr |
| 50 | charptr |
| 51 | i8 |
| 52 | i16 |
| 53 | i32 |
| 54 | i64 |
| 55 | int |
| 56 | isize |
| 57 | u8 |
| 58 | u16 |
| 59 | u32 |
| 60 | u64 |
| 61 | usize |
| 62 | f32 |
| 63 | f64 |
| 64 | char |
| 65 | rune |
| 66 | bool |
| 67 | none |
| 68 | string |
| 69 | array |
| 70 | array_fixed |
| 71 | map |
| 72 | chan |
| 73 | any |
| 74 | struct |
| 75 | generic_inst |
| 76 | multi_return |
| 77 | sum_type |
| 78 | alias |
| 79 | enum |
| 80 | function |
| 81 | interface |
| 82 | float_literal |
| 83 | int_literal |
| 84 | aggregate |
| 85 | thread |
| 86 | } |
| 87 | |
| 88 | // return true if `flag` is set on `t` |
| 89 | @[inline] |
| 90 | pub fn (t VType) has_flag(flag VTypeFlag) bool { |
| 91 | return int(t) & (1 << (int(flag) + 24)) > 0 |
| 92 | } |
| 93 | |
| 94 | @[inline] |
| 95 | pub fn (t VType) idx() int { |
| 96 | return u16(t) & 0xffff |
| 97 | } |
| 98 | |
| 99 | pub fn (t VType) str() string { |
| 100 | return 'VType(0x${t.hex()} = ${u32(t)})' |
| 101 | } |
| 102 | |
| 103 | // return true if `t` is a pointer (nr_muls>0) |
| 104 | @[inline] |
| 105 | pub fn (t VType) is_ptr() bool { |
| 106 | // any normal pointer, i.e. &Type, &&Type etc; |
| 107 | // Note: voidptr, charptr and byteptr are NOT included! |
| 108 | return (int(t) >> 16) & 0xff > 0 |
| 109 | } |
| 110 | |
| 111 | pub struct ArrayFixed { |
| 112 | pub: |
| 113 | size int // array size |
| 114 | elem_type int // elem type idx |
| 115 | } |
| 116 | |
| 117 | pub struct Array { |
| 118 | pub: |
| 119 | nr_dims int // nr of dimensions |
| 120 | elem_type int // elem type idx |
| 121 | } |
| 122 | |
| 123 | pub struct Alias { |
| 124 | pub: |
| 125 | parent_idx int // parent type idx |
| 126 | language VLanguage // language |
| 127 | } |
| 128 | |
| 129 | pub struct Interface { |
| 130 | pub: |
| 131 | name string // interface name |
| 132 | methods []Function // methods |
| 133 | fields []StructField // fields |
| 134 | is_generic bool // is generic? |
| 135 | } |
| 136 | |
| 137 | pub struct None { |
| 138 | pub: |
| 139 | parent_idx int |
| 140 | } |
| 141 | |
| 142 | pub struct Enum { |
| 143 | pub: |
| 144 | vals []string // enum values |
| 145 | is_flag bool // is flag? |
| 146 | } |
| 147 | |
| 148 | pub struct StructField { |
| 149 | pub: |
| 150 | name string // field name |
| 151 | typ VType // type |
| 152 | attrs []VAttribute // field attrs |
| 153 | is_pub bool // is pub? |
| 154 | is_mut bool // is mut? |
| 155 | } |
| 156 | |
| 157 | pub struct Struct { |
| 158 | pub: |
| 159 | parent_idx int // parent type |
| 160 | attrs []VAttribute // struct attrs |
| 161 | fields []StructField // fields |
| 162 | } |
| 163 | |
| 164 | pub struct SumType { |
| 165 | pub: |
| 166 | parent_idx int // parent type |
| 167 | variants []VType // variant type |
| 168 | } |
| 169 | |
| 170 | pub struct Map { |
| 171 | pub: |
| 172 | key_type VType // key type |
| 173 | value_type VType // value type |
| 174 | } |
| 175 | |
| 176 | pub struct MultiReturn { |
| 177 | pub: |
| 178 | types []VType // types |
| 179 | } |
| 180 | |
| 181 | pub type TypeInfo = Alias |
| 182 | | Array |
| 183 | | ArrayFixed |
| 184 | | Enum |
| 185 | | Function |
| 186 | | Interface |
| 187 | | Map |
| 188 | | MultiReturn |
| 189 | | None |
| 190 | | Struct |
| 191 | | SumType |
| 192 | |
| 193 | pub struct TypeSymbol { |
| 194 | pub: |
| 195 | name string // symbol name |
| 196 | mod string // mod name |
| 197 | idx int // symbol idx |
| 198 | parent_idx int // symbol parent idx |
| 199 | language VLanguage // language |
| 200 | kind VKind // kind |
| 201 | info TypeInfo // info |
| 202 | methods []Function // methods |
| 203 | } |
| 204 | |
| 205 | pub struct Type { |
| 206 | pub: |
| 207 | name string // type name |
| 208 | idx int // type idx |
| 209 | sym TypeSymbol // type symbol |
| 210 | } |
| 211 | |
| 212 | pub struct Module { |
| 213 | pub: |
| 214 | name string // module name |
| 215 | } |
| 216 | |
| 217 | pub struct FunctionArg { |
| 218 | pub: |
| 219 | name string // argument name |
| 220 | typ VType // argument type idx |
| 221 | is_mut bool // is mut? |
| 222 | } |
| 223 | |
| 224 | pub struct Function { |
| 225 | pub: |
| 226 | mod_name string // module name |
| 227 | name string // function/method name |
| 228 | attrs []VAttribute // function/method attrs |
| 229 | args []FunctionArg // function/method args |
| 230 | file_idx int // source file name |
| 231 | line_start int // decl start line |
| 232 | line_end int // decl end line |
| 233 | is_variadic bool // is variadic? |
| 234 | return_typ VType // return type idx |
| 235 | receiver_typ VType // receiver type idx (is a method) |
| 236 | is_pub bool // is pub? |
| 237 | } |
| 238 | |
| 239 | // API module |
| 240 | |
| 241 | pub fn get_string_by_idx(idx int) string { |
| 242 | return g_reflection.strings[idx] |
| 243 | } |
| 244 | |
| 245 | // type_of returns the type info of the passed value |
| 246 | pub fn type_of[T](val T) Type { |
| 247 | return g_reflection.types.filter(it.idx == typeof[T]().idx & 0xff00ffff)[0] |
| 248 | } |
| 249 | |
| 250 | // get_modules returns the module name built with V source |
| 251 | pub fn get_modules() []Module { |
| 252 | return g_reflection.modules |
| 253 | } |
| 254 | |
| 255 | // get_functions returns the functions built with V source |
| 256 | pub fn get_funcs() []Function { |
| 257 | mut out := g_reflection.funcs.clone() |
| 258 | out << arrays.flatten[Function](get_types().map(it.sym.methods).filter(it.len != 0)) |
| 259 | return out |
| 260 | } |
| 261 | |
| 262 | pub fn get_structs() []Type { |
| 263 | struct_idxs := g_reflection.type_symbols.filter(it.kind == .struct).map(it.idx) |
| 264 | return g_reflection.types.filter(it.idx in struct_idxs) |
| 265 | } |
| 266 | |
| 267 | // get_types returns the registered types |
| 268 | pub fn get_types() []Type { |
| 269 | return g_reflection.types |
| 270 | } |
| 271 | |
| 272 | // get_enums returns the registered enums |
| 273 | pub fn get_enums() []Type { |
| 274 | enum_idxs := g_reflection.type_symbols.filter(it.kind == .enum).map(it.idx) |
| 275 | return g_reflection.types.filter(it.idx in enum_idxs) |
| 276 | } |
| 277 | |
| 278 | // get_aliases returns the registered aliases |
| 279 | pub fn get_aliases() []Type { |
| 280 | alias_idxs := g_reflection.type_symbols.filter(it.kind == .alias).map(it.idx) |
| 281 | return g_reflection.types.filter(it.idx in alias_idxs) |
| 282 | } |
| 283 | |
| 284 | // get_interfaces returns the registered aliases |
| 285 | pub fn get_interfaces() []Interface { |
| 286 | iface_idxs := g_reflection.type_symbols.filter(it.kind == .interface).map(it.idx) |
| 287 | return g_reflection.types.filter(it.idx in iface_idxs).map(it.sym.info as Interface) |
| 288 | } |
| 289 | |
| 290 | // get_sum_types returns the registered sum types |
| 291 | pub fn get_sum_types() []Type { |
| 292 | sumtype_idxs := g_reflection.type_symbols.filter(it.kind == .sum_type).map(it.idx) |
| 293 | return g_reflection.types.filter(it.idx in sumtype_idxs) |
| 294 | } |
| 295 | |
| 296 | // get_type_symbol returns the registered type symbols |
| 297 | pub fn get_type_symbols() []TypeSymbol { |
| 298 | return g_reflection.type_symbols |
| 299 | } |
| 300 | |
| 301 | // Type API |
| 302 | pub fn type_name(idx int) string { |
| 303 | t := g_reflection.types.filter(it.idx == idx) |
| 304 | return if t.len != 0 { t[0].name } else { '' } |
| 305 | } |
| 306 | |
| 307 | pub fn get_type(idx int) ?Type { |
| 308 | t := g_reflection.types.filter(it.idx == idx) |
| 309 | return if t.len != 0 { t[0] } else { none } |
| 310 | } |
| 311 | |
| 312 | // Type Symbol API |
| 313 | pub fn type_symbol_name(idx int) string { |
| 314 | t := g_reflection.type_symbols.filter(it.idx == idx) |
| 315 | return if t.len != 0 { t[0].name } else { '' } |
| 316 | } |
| 317 | |
| 318 | pub fn get_type_symbol(idx int) ?TypeSymbol { |
| 319 | t := g_reflection.type_symbols.filter(it.idx == idx) |
| 320 | return if t.len != 0 { t[0] } else { none } |
| 321 | } |
| 322 | |
| 323 | // V reflection metainfo API (called from backend to fill metadata info) |
| 324 | |
| 325 | @[markused] |
| 326 | fn add_module(mod_name string) { |
| 327 | g_reflection.modules << Module{mod_name} |
| 328 | } |
| 329 | |
| 330 | @[markused] |
| 331 | fn add_func(func Function) { |
| 332 | g_reflection.funcs << func |
| 333 | } |
| 334 | |
| 335 | @[markused] |
| 336 | fn add_type(type_ Type) { |
| 337 | g_reflection.types << Type{ |
| 338 | ...type_ |
| 339 | sym: g_reflection.type_symbols.filter(it.idx == type_.idx).first() |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | @[markused] |
| 344 | fn add_type_symbol(typesymbol TypeSymbol) { |
| 345 | g_reflection.type_symbols << typesymbol |
| 346 | } |
| 347 | |
| 348 | @[markused] |
| 349 | fn add_string(str string, idx int) { |
| 350 | g_reflection.strings[idx] = str |
| 351 | } |
| 352 | |