hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

type.ha (5020B)


      1 // License: MPL-2.0
      2 // (c) 2021 Alexey Yerin <yyp@disroot.org>
      3 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      4 // (c) 2021 Ember Sawady <ecs@d2evs.net>
      5 use hare::lex;
      6 
      7 // A type alias.
      8 export type alias_type = struct {
      9 	unwrap: bool,
     10 	ident: ident,
     11 };
     12 
     13 // A built-in primitive type (int, bool, str, etc).
     14 export type builtin_type = enum {
     15 	BOOL, F32, F64, FCONST, I16, I32, I64, I8, ICONST, INT, NULL,
     16 	RUNE, SIZE, STR, U16, U32, U64, U8, UINT, UINTPTR, VALIST, VOID,
     17 };
     18 
     19 // An enumeration field (and optional value).
     20 export type enum_field = struct {
     21 	name: str,
     22 	value: nullable *expr,
     23 	loc: lex::location,
     24 	docs: str,
     25 };
     26 
     27 // enum { FOO = 0, BAR, ... }
     28 export type enum_type = struct {
     29 	storage: builtin_type, // Must be an integer type
     30 	values: []enum_field,
     31 };
     32 
     33 // The variadism strategy for a function type.
     34 export type variadism = enum {
     35 	NONE,
     36 	C,
     37 	HARE,
     38 };
     39 
     40 // The attributes associated with a function type.
     41 export type func_attrs = enum uint {
     42 	NONE = 0,
     43 	NORETURN = 1 << 0,
     44 };
     45 
     46 // A parameter to a function type.
     47 export type func_param = struct {
     48 	loc: lex::location,
     49 	name: str,
     50 	_type: *_type,
     51 };
     52 
     53 // fn(foo: int, baz: int...) int
     54 export type func_type = struct {
     55 	result: *_type,
     56 	attrs: func_attrs,
     57 	variadism: variadism,
     58 	params: []func_param,
     59 };
     60 
     61 // The length for a list type which is a slice (e.g. []int).
     62 export type len_slice = void;
     63 
     64 // The length for a list type which is unbounded (e.g. [*]int).
     65 export type len_unbounded = void;
     66 
     67 // The length for a list type which is inferred from context (e.g. [_]int).
     68 export type len_contextual = void;
     69 
     70 // []int, [*]int, [_]int, [foo]int
     71 export type list_type = struct {
     72 	length: (*expr | len_slice | len_unbounded | len_contextual),
     73 	members: *_type,
     74 };
     75 
     76 // Flags which apply to a pointer type.
     77 export type pointer_flag = enum uint {
     78 	NONE = 0,
     79 	NULLABLE = 1 << 0,
     80 };
     81 
     82 // *int
     83 export type pointer_type = struct {
     84 	referent: *_type,
     85 	flags: pointer_flag,
     86 };
     87 
     88 // A single field of a struct type.
     89 export type struct_field = struct {
     90 	name: str,
     91 	_type: *_type,
     92 };
     93 
     94 // An embedded struct type.
     95 export type struct_embedded = *_type;
     96 
     97 // An embedded type alias.
     98 export type struct_alias = ident;
     99 
    100 // struct { @offset(10) foo: int, struct { bar: int }, baz::quux }
    101 export type struct_member = struct {
    102 	_offset: nullable *expr,
    103 	member: (struct_field | struct_embedded | struct_alias),
    104 
    105 	// Only valid if the lexer has comments enabled
    106 	docs: str,
    107 };
    108 
    109 // struct { ... }
    110 export type struct_type = struct {
    111 	packed: bool,
    112 	members: []struct_member,
    113 };
    114 
    115 // union { ... }
    116 export type union_type = []struct_member;
    117 
    118 export type struct_union_type = (struct_type | union_type);
    119 
    120 // (int | bool)
    121 export type tagged_type = []*_type;
    122 
    123 // (int, bool, ...)
    124 export type tuple_type = []*_type;
    125 
    126 // Flags which apply to types.
    127 export type type_flag = enum uint {
    128 	NONE = 0,
    129 	CONST = 1 << 0,
    130 	ERROR = 1 << 1,
    131 };
    132 
    133 // A Hare type.
    134 export type _type = struct {
    135 	start: lex::location,
    136 	end: lex::location,
    137 	flags: type_flag,
    138 	repr: (alias_type | builtin_type | enum_type | func_type |
    139 		list_type | pointer_type | struct_type | union_type |
    140 		tagged_type | tuple_type),
    141 };
    142 
    143 fn struct_type_finish(t: (struct_type | union_type)) void = {
    144 	let membs = match (t) {
    145 	case let s: struct_type =>
    146 		yield s.members: []struct_member;
    147 	case let u: union_type =>
    148 		yield u: []struct_member;
    149 	};
    150 	for (let i = 0z; i < len(membs); i += 1) {
    151 		free(membs[i].docs);
    152 		match (membs[i]._offset) {
    153 		case null => void;
    154 		case let e: *expr =>
    155 			expr_finish(e);
    156 		};
    157 		match (membs[i].member) {
    158 		case let f: struct_field =>
    159 			free(f.name);
    160 			type_finish(f._type);
    161 		case let e: struct_embedded =>
    162 			type_finish(e: *_type);
    163 		case let a: struct_alias =>
    164 			ident_free(a);
    165 		};
    166 	};
    167 	free(membs);
    168 };
    169 
    170 // Frees resources associated with a [[_type]].
    171 export fn type_finish(t: (_type | nullable *_type)) void = {
    172 	match (t) {
    173 	case let t: nullable *_type =>
    174 		match (t) {
    175 		case null => void;
    176 		case let t: *_type =>
    177 			type_finish(*t);
    178 			free(t);
    179 		};
    180 	case let t: _type =>
    181 		match (t.repr) {
    182 		case let a: alias_type =>
    183 			ident_free(a.ident);
    184 		case builtin_type => void;
    185 		case let e: enum_type =>
    186 			for (let i = 0z; i < len(e.values); i += 1) {
    187 				free(e.values[i].name);
    188 				match (e.values[i].value) {
    189 				case null => void;
    190 				case let v: *expr =>
    191 					expr_finish(v);
    192 				};
    193 			};
    194 			free(e.values);
    195 		case let f: func_type =>
    196 			type_finish(f.result);
    197 			for (let i = 0z; i < len(f.params); i += 1) {
    198 				free(f.params[i].name);
    199 				type_finish(f.params[i]._type);
    200 			};
    201 			free(f.params);
    202 		case let l: list_type =>
    203 			match (l.length) {
    204 			case let e: *expr =>
    205 				expr_finish(e);
    206 			case => void;
    207 			};
    208 			type_finish(l.members);
    209 		case let p: pointer_type =>
    210 			type_finish(p.referent);
    211 		case let s: (struct_type | union_type) =>
    212 			struct_type_finish(s);
    213 		case let t: tagged_type =>
    214 			for (let i = 0z; i < len(t); i += 1) {
    215 				type_finish(t[i]);
    216 			};
    217 			free(t);
    218 		case let t: tuple_type =>
    219 			for (let i = 0z; i < len(t); i += 1) {
    220 				type_finish(t[i]);
    221 			};
    222 			free(t);
    223 		};
    224 	};
    225 };