hare

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

sort.ha (2767B)


      1 // License: GPL-3.0
      2 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      3 // (c) 2021 Ember Sawady <ecs@d2evs.net>
      4 use hare::ast;
      5 use sort;
      6 use strings;
      7 
      8 type summary = struct {
      9 	constants: []ast::decl,
     10 	errors: []ast::decl,
     11 	types: []ast::decl,
     12 	globals: []ast::decl,
     13 	funcs: []ast::decl,
     14 };
     15 
     16 // Sorts declarations by removing unexported declarations, moving undocumented
     17 // declarations to the end, sorting by identifier, and ensuring that only one
     18 // member is present in each declaration (so that "let x: int = 10, y: int = 20"
     19 // becomes two declarations: "let x: int = 10; let y: int = 20;").
     20 fn sort_decls(decls: []ast::decl) summary = {
     21 	let sorted = summary { ... };
     22 
     23 	for (let i = 0z; i < len(decls); i += 1) {
     24 		let decl = decls[i];
     25 		if (!decl.exported) {
     26 			continue;
     27 		};
     28 
     29 		match (decl.decl) {
     30 		case let f: ast::decl_func =>
     31 			append(sorted.funcs, decl);
     32 		case let t: []ast::decl_type =>
     33 			for (let j = 0z; j < len(t); j += 1) {
     34 				let bucket = &sorted.types;
     35 				if (t[j]._type.flags & ast::type_flag::ERROR == ast::type_flag::ERROR) {
     36 					bucket = &sorted.errors;
     37 				};
     38 				append(bucket, ast::decl {
     39 					exported = true,
     40 					start = decl.start,
     41 					end = decl.end,
     42 					decl = alloc([t[j]]),
     43 					docs = decl.docs,
     44 				});
     45 			};
     46 		case let c: []ast::decl_const =>
     47 			for (let j = 0z; j < len(c); j += 1) {
     48 				append(sorted.constants, ast::decl {
     49 					exported = true,
     50 					start = decl.start,
     51 					end = decl.end,
     52 					decl = alloc([c[j]]),
     53 					docs = decl.docs,
     54 				});
     55 			};
     56 		case let g: []ast::decl_global =>
     57 			for (let j = 0z; j < len(g); j += 1) {
     58 				append(sorted.globals, ast::decl {
     59 					exported = true,
     60 					start = decl.start,
     61 					end = decl.end,
     62 					decl = alloc([g[j]]),
     63 					docs = decl.docs,
     64 				});
     65 			};
     66 		};
     67 	};
     68 
     69 	sort::sort(sorted.constants, size(ast::decl), &decl_cmp);
     70 	sort::sort(sorted.errors, size(ast::decl), &decl_cmp);
     71 	sort::sort(sorted.types, size(ast::decl), &decl_cmp);
     72 	sort::sort(sorted.globals, size(ast::decl), &decl_cmp);
     73 	sort::sort(sorted.funcs, size(ast::decl), &decl_cmp);
     74 	return sorted;
     75 };
     76 
     77 fn decl_cmp(a: const *void, b: const *void) int = {
     78 	const a = *(a: const *ast::decl);
     79 	const b = *(b: const *ast::decl);
     80 	if (a.docs == "" && b.docs != "") {
     81 		return 1;
     82 	} else if (a.docs != "" && b.docs == "") {
     83 		return -1;
     84 	};
     85 	const id_a = decl_ident(a), id_b = decl_ident(b);
     86 	return strings::compare(id_a[len(id_a) - 1], id_b[len(id_b) - 1]);
     87 };
     88 
     89 fn decl_ident(decl: ast::decl) ast::ident = {
     90 	match (decl.decl) {
     91 	case let f: ast::decl_func =>
     92 		return f.ident;
     93 	case let t: []ast::decl_type =>
     94 		assert(len(t) == 1);
     95 		return t[0].ident;
     96 	case let c: []ast::decl_const =>
     97 		assert(len(c) == 1);
     98 		return c[0].ident;
     99 	case let g: []ast::decl_global =>
    100 		assert(len(g) == 1);
    101 		return g[0].ident;
    102 	};
    103 };