hare

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

loc.ha (4369B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 use bufio;
      5 use fmt;
      6 use hare::ast;
      7 use hare::lex;
      8 use io;
      9 use io::{mode};
     10 use memio;
     11 use strings;
     12 
     13 fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
     14 	let buf = memio::fixed(strings::toutf8(srcs[i]));
     15 	let sc = bufio::newscanner(&buf);
     16 	defer bufio::finish(&sc);
     17 	let lexer = lex::init(&sc, "<test>");
     18 	let exp = match (expr(&lexer)) {
     19 	case let exp: ast::expr =>
     20 		yield exp;
     21 	case let err: error =>
     22 		fmt::errorfln("{}: {}", srcs[i], strerror(err))!;
     23 		abort();
     24 	};
     25 	defer ast::expr_finish(&exp);
     26 	let runes = 0z;
     27 	let it = strings::iter(srcs[i]);
     28 	for (strings::next(&it) is rune) {
     29 		runes += 1;
     30 	};
     31 	assert(exp.start.line == 1 && exp.start.col == 1);
     32 	assert(exp.end.line == 1 && exp.end.col == runes);
     33 };
     34 
     35 @test fn expr_loc() void = {
     36 	expr_testloc("foo", "foo[bar]", "foo.bar", "foo.1");
     37 	expr_testloc("alloc(foo)");
     38 	expr_testloc("append(foo, bar)", "append(foo, bar, baz)");
     39 	expr_testloc("assert(foo)", `assert(foo, "bar")`, "abort()",
     40 		`abort("foo")`);
     41 	expr_testloc("foo is bar", "foo as bar");
     42 	expr_testloc("foo = bar");
     43 	expr_testloc("foo * bar", "foo && bar");
     44 	expr_testloc("break", "break :foo");
     45 	expr_testloc("foo(bar)");
     46 	expr_testloc("foo: bar");
     47 	expr_testloc("[foo, bar]", "[foo, bar...]");
     48 	expr_testloc("foo { bar = baz, ... }", "struct { foo: bar = baz, }");
     49 	expr_testloc("(foo, bar)");
     50 	expr_testloc("null", "void", "true", `"שלום"`, "'a'");
     51 	expr_testloc("[foo, bar]");
     52 	expr_testloc("123", "-123.456", "123z", "123e+3");
     53 	expr_testloc("continue", "continue :foo");
     54 	expr_testloc("delete(foo[bar])", "delete(foo[bar..baz])");
     55 	expr_testloc("for (let foo = 0; bar; baz) quux",
     56 		"for (let bar = 0; baz; quux) quuux");
     57 	expr_testloc("free(foo)");
     58 	expr_testloc("if (foo) bar", "if (foo) bar else baz");
     59 	expr_testloc("insert(foo[0], bar)", "insert(foo[0], bar, baz)");
     60 	expr_testloc("len(foo)");
     61 	expr_testloc("{ foo; bar; }", "{ defer foo; }",
     62 		"{ let foo: bar = baz; }", "{ let foo: bar = baz, quux = quuux; }",
     63 		"{ const foo: bar = baz; }", "{ const foo: bar = baz, quux = quuux; }");
     64 	expr_testloc("match (foo) { case => bar; }");
     65 	expr_testloc("offset(foo)");
     66 	expr_testloc("foo?", "foo!");
     67 	expr_testloc("return", "return foo");
     68 	expr_testloc("size(int)");
     69 	expr_testloc("switch (foo) { case => bar; }");
     70 	expr_testloc("foo[bar..baz]");
     71 	expr_testloc("&foo");
     72 	expr_testloc("vastart()", "vaarg(ap)", "vaend(ap)");
     73 	expr_testloc("yield", "yield foo", "yield :foo, bar");
     74 
     75 	// We want to check the location of nested expressions, so this can't
     76 	// use expr_testloc
     77 	let buf = memio::fixed(strings::toutf8("foo: bar: baz"));
     78 	let sc = bufio::newscanner(&buf);
     79 	defer bufio::finish(&sc);
     80 	let lexer = lex::init(&sc, "<test>");
     81 	let exp = match (expr(&lexer)) {
     82 	case let exp: ast::expr =>
     83 		yield exp;
     84 	case let err: error =>
     85 		fmt::errorln(strerror(err))!;
     86 		abort();
     87 	};
     88 	defer ast::expr_finish(&exp);
     89 	assert(exp.start.line == 1 && exp.start.col == 1);
     90 	assert(exp.end.line == 1 && exp.end.col == 13);
     91 	let c = exp.expr as ast::cast_expr;
     92 	exp = *c.value;
     93 	assert(exp.start.line == 1 && exp.start.col == 1);
     94 	assert(exp.end.line == 1 && exp.end.col == 8);
     95 	c = exp.expr as ast::cast_expr;
     96 	exp = *c.value;
     97 	assert(exp.start.line == 1 && exp.start.col == 1);
     98 	assert(exp.end.line == 1 && exp.end.col == 3);
     99 };
    100 
    101 fn type_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
    102 	let buf = memio::fixed(strings::toutf8(srcs[i]));
    103 	let sc = bufio::newscanner(&buf);
    104 	defer bufio::finish(&sc);
    105 	let lexer = lex::init(&sc, "<test>");
    106 	let typ = match (_type(&lexer)) {
    107 	case let typ: ast::_type =>
    108 		yield typ;
    109 	case let err: error =>
    110 		fmt::errorln(strerror(err))!;
    111 		abort();
    112 	};
    113 	defer ast::type_finish(&typ);
    114 	let runes = 0z;
    115 	let it = strings::iter(srcs[i]);
    116 	for (strings::next(&it) is rune) {
    117 		runes += 1;
    118 	};
    119 	assert(typ.start.line == 1 && typ.start.col == 1);
    120 	assert(typ.end.line == 1 && typ.end.col == runes);
    121 };
    122 
    123 @test fn type_loc() void = {
    124 	type_testloc("foo", "...foo");
    125 	type_testloc("int");
    126 	type_testloc("enum { FOO = bar }");
    127 	type_testloc("fn(foo: bar) baz");
    128 	type_testloc("[foo]bar", "[*]foo", "[]foo", "[_]int");
    129 	type_testloc("*foo", "nullable *int");
    130 	type_testloc("struct { foo: bar }");
    131 	type_testloc("union { foo: bar }");
    132 	type_testloc("(foo | bar)");
    133 	type_testloc("(foo, bar)");
    134 };