hare

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

type.ha (4604B)


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