hare

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

+test.ha (3945B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use fmt;
      5 use hare::ast;
      6 use hare::lex;
      7 use hare::unparse;
      8 use memio;
      9 use os;
     10 use strings;
     11 
     12 fn assert_doc_eq(a: doc, b: doc) void = {
     13 	assert(len(a) == len(b));
     14 	for (let i = 0z; i < len(a); i += 1) {
     15 		match (a[i]) {
     16 		case let a: paragraph =>
     17 			const b = b[i] as paragraph;
     18 			assert_paragraph_eq(a, b);
     19 		case let a: list =>
     20 			const b = b[i] as list;
     21 			assert(len(a) == len(b));
     22 			for (let i = 0z; i < len(a); i += 1) {
     23 				assert_paragraph_eq(a[i], b[i]);
     24 			};
     25 		case let a: code_sample =>
     26 			const b = b[i] as code_sample;
     27 			if (a != b) {
     28 				fmt::errorfln("=== wanted code sample\n{}", b)!;
     29 				fmt::errorfln("=== got code sample\n{}", a)!;
     30 				abort();
     31 			};
     32 		};
     33 	};
     34 };
     35 
     36 fn assert_paragraph_eq(a: paragraph, b: paragraph) void = {
     37 	fmt::errorln(len(a), len(b))!;
     38 	assert(len(a) == len(b));
     39 	for (let i = 0z; i < len(a); i += 1) {
     40 		match (a[i]) {
     41 		case let a: str =>
     42 			const b = b[i] as str;
     43 			if (a != b) {
     44 				fmt::errorfln("=== wanted text\n{}", b)!;
     45 				fmt::errorfln("=== got text\n{}", a)!;
     46 				abort();
     47 			};
     48 		case let a: decl_ref =>
     49 			const b = b[i] as decl_ref;
     50 			if (!ast::ident_eq(a, b)) {
     51 				fmt::error("=== wanted decl_ref ")!;
     52 				unparse::ident(os::stderr, b)!;
     53 				fmt::error("\n=== got decl_ref ")!;
     54 				unparse::ident(os::stderr, a)!;
     55 				fmt::errorln()!;
     56 				abort();
     57 			};
     58 		case let a: mod_ref =>
     59 			const b = b[i] as mod_ref;
     60 			if (!ast::ident_eq(a, b)) {
     61 				fmt::error("=== wanted mod_ref ")!;
     62 				unparse::ident(os::stderr, b)!;
     63 				fmt::error("\n=== got mod_ref ")!;
     64 				unparse::ident(os::stderr, a)!;
     65 				fmt::errorln()!;
     66 				abort();
     67 			};
     68 		};
     69 	};
     70 };
     71 
     72 @test fn doc() void = {
     73 	// if you have some way in your editor to distinguish tabs from spaces
     74 	// you're gonna want to use it here
     75 	let in = memio::fixed(strings::toutf8(
     76 ` Blablabla asdfghjkl
     77  qwerty[[uiop::]] zxcvbnm
     78 
     79  new paragraph
     80  - list starting immediately after paragraph
     81  - another list item
     82  - yet another
     83    but this one
     84    spans multiple lines
     85  -no leading space
     86 still multiple lines
     87 
     88  	code sample
     89  	line 2
     90 	no leading space
     91 
     92 
     93  	continuing the same code sample
     94  		  	indentation is preserved
     95  		  	as   well as multiple     spaces
     96   	this is now a paragraph because of the [[leading::spaces]]
     97 
     98  - list starting [[after]] [[empty::line::]]
     99 
    100  but with only [one item]]
    101  -
    102 	code sample starting immediately after list with one empty item`
    103 	));
    104 
    105 	const doc = parse(&in, lex::location { ... })!;
    106 	defer freeall(doc);
    107 
    108 	assert_doc_eq(doc, [
    109 		[
    110 			"Blablabla asdfghjkl qwerty",
    111 			["uiop"]: mod_ref,
    112 			" zxcvbnm",
    113 		]: paragraph,
    114 
    115 		["new paragraph"]: paragraph,
    116 
    117 		[
    118 			["list starting immediately after paragraph"],
    119 			["another list item"],
    120 			["yet another but this one spans multiple lines"],
    121 			["no leading space still multiple lines"],
    122 		]: list,
    123 
    124 		`code sample
    125 line 2
    126 no leading space
    127 
    128 
    129 continuing the same code sample
    130 	  	indentation is preserved
    131 	  	as   well as multiple     spaces`: code_sample,
    132 
    133 	  	[
    134 	  		" this is now a paragraph because of the ",
    135 	  		["leading", "spaces"]: decl_ref,
    136 		]: paragraph,
    137 
    138 		[
    139 			[
    140 				"list starting ",
    141 				["after"]: decl_ref,
    142 				" ",
    143 				["empty", "line"]: mod_ref,
    144 			],
    145 		]: list,
    146 
    147 		["but with only [one item]]"]: paragraph,
    148 
    149 		[[]]: list,
    150 
    151 		"code sample starting immediately after list with one empty item": code_sample,
    152 	]);
    153 };
    154 
    155 @test fn invalid_ref() void = {
    156 	const tests: [_](str, uint, uint) = [
    157 		("[[abort]]", 1, 3),
    158 		("[[::foo]]", 1, 3),
    159 		("[[]]", 1, 3),
    160 		("[[foo]", 1, 7),
    161 		("   \t\n a\n asdf\t [[]]", 3, 12),
    162 	];
    163 	for (let i = 0u; i < len(tests): uint; i += 1) {
    164 		let in = memio::fixed(strings::toutf8(tests[i].0));
    165 		fmt::errorln(tests[i].0)!;
    166 		const err = parse(&in, lex::location {
    167 			path = "<test>",
    168 			line = i + 1,
    169 			col = i + 1,
    170 		}) as lex::syntax;
    171 		assert(err.0.path == "<test>");
    172 		assert(err.0.line == i + tests[i].1);
    173 		assert(err.0.col == i + tests[i].2);
    174 	};
    175 };