hare

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

type.ha (4647B)


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