harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

11-globals.ha (4111B)


      1 use rt::{compile, exited, EXIT_SUCCESS};
      2 
      3 // globals without type hint
      4 def NOHINT = 1234z;
      5 let nohint = 12z;
      6 const nohintconst = 123z;
      7 // with type defined afterwards
      8 const nhval = nh {
      9 	field = 1,
     10 };
     11 type nh = struct {
     12 	field: int,
     13 };
     14 
     15 let x: int = 42, y: int = 69;
     16 
     17 fn write() void = {
     18 	assert(x == 42 && y == 69);
     19 	x = 1337;
     20 	assert(x == 1337);
     21 	
     22 	assert(nohint == 12);
     23 	assert(nohintconst == 123);
     24 	assert(NOHINT == 1234);
     25 	assert(nhval.field == 1);	
     26 };
     27 
     28 let ar: [3]int = [1, 2, 3];
     29 let sl: []int = [1, 2, 3];
     30 let st: str = "Hello!";
     31 
     32 type coords = struct { x: int, y: int };
     33 let su: coords = coords { y = 10, x = 20};
     34 let su_autofill: coords = coords { y = 10, x = 20, ... };
     35 let au: coords = coords { ... };
     36 
     37 type coords3 = struct { coords: coords, z: int };
     38 let a3: coords3 = coords3 { ... };
     39 
     40 type embedded = struct { a: uint, b: u8 };
     41 
     42 type with_embedded = struct { embedded, c: int };
     43 let em: with_embedded = with_embedded { a = 3, b = 4, c = 18 };
     44 let em_autofill: with_embedded = with_embedded { ... };
     45 
     46 type with_embedded2 = struct { c: int, embedded };
     47 let em2: with_embedded2 = with_embedded2 { a = 3, b = 4, c = 18 };
     48 let em2_autofill: with_embedded2 = with_embedded2 { ... };
     49 
     50 type aenum = enum u64 {
     51 	BIG_VALUE = 0x1234567887654321,
     52 };
     53 const big_value: aenum = aenum::BIG_VALUE;
     54 
     55 type renum = enum rune {
     56 	R1 = 'a',
     57 	R2 = 'g',
     58 };
     59 let renum_val = renum::R1;
     60 
     61 const float: f32 = 1234.5678;
     62 const double: f64 = 1234.5678;
     63 
     64 fn storage() void = {
     65 	assert(len(ar) == 3);
     66 	assert(ar[0] == 1 && ar[1] == 2 && ar[2] == 3);
     67 	assert(len(sl) == 3);
     68 	assert(sl[0] == 1 && sl[1] == 2 && sl[2] == 3);
     69 	assert(len(st) == 6);
     70 	assert(su.x == 20 && su.y == 10);
     71 	assert(su_autofill.x == 20 && su_autofill.y == 10);
     72 	assert(au.x == 0 && au.y == 0);
     73 	assert(a3.coords.x == 0 && a3.coords.y == 0 && a3.z == 0);
     74 	assert(em.a == 3 && em.b == 4 && em.c == 18);
     75 	assert(em_autofill.a == 0 && em_autofill.b == 0 && em_autofill.c == 0);
     76 	assert(em2.a == 3 && em2.b == 4 && em2.c == 18);
     77 	assert(em2_autofill.a == 0 && em2_autofill.b == 0 && em2_autofill.c == 0);
     78 	assert(big_value == 0x1234567887654321: aenum);
     79 	assert(float == 1234.5678);
     80 	assert(double == 1234.5678);
     81 };
     82 
     83 fn invariants() void = {
     84 	assert(compile("fn test() int; let x: int = test();") as exited != EXIT_SUCCESS);
     85 	assert(compile("const a: u8 = 2; const b: u8 = a + 5;") as exited != EXIT_SUCCESS);
     86 };
     87 
     88 fn counter() int = {
     89 	static let x = 0;
     90 	x += 1;
     91 	return x;
     92 };
     93 
     94 fn static_binding() void = {
     95 	assert(counter() == 1);
     96 	assert(counter() == 2);
     97 	assert(counter() == 3);
     98 };
     99 
    100 const val: u32 = 42;
    101 const tup: (u8, str) = (2, "asdf");
    102 const ptr: *u32 = &val;
    103 const ptr_tup: *(u8, str) = &tup;
    104 // TODO const ptr_memb: *str = &tup.1;
    105 
    106 fn pointers() void = {
    107 	assert(ptr == &val && *ptr == val);
    108 };
    109 
    110 type foo = (int | uint);
    111 
    112 let subtype: foo = 10u;
    113 
    114 let arr_of_tagged_of_tuple: [3]((int, int)|void) = [(1, 2), (3, 4), (5, 6)];
    115 
    116 fn tagged() void = {
    117 	assert((arr_of_tagged_of_tuple[0] as (int, int)).0 == 1);
    118 	assert((arr_of_tagged_of_tuple[0] as (int, int)).1 == 2);
    119 	assert((arr_of_tagged_of_tuple[1] as (int, int)).0 == 3);
    120 	assert((arr_of_tagged_of_tuple[1] as (int, int)).1 == 4);
    121 	assert((arr_of_tagged_of_tuple[2] as (int, int)).0 == 5);
    122 	assert((arr_of_tagged_of_tuple[2] as (int, int)).1 == 6);
    123 	assert(subtype is uint);
    124 	// TODO: subset-compat
    125 };
    126 
    127 // Real-world sample
    128 
    129 type basic = enum {
    130 	FN,
    131 	FOR,
    132 	IF,
    133 	IN,
    134 	NOT,
    135 	SWITCH,
    136 	WHILE,
    137 };
    138 
    139 const keywords: [_](str, basic) = [
    140 	("fn", basic::FN),
    141 	("for", basic::FOR),
    142 	("if", basic::IF),
    143 	("in", basic::IN),
    144 	("not", basic::NOT),
    145 	("switch", basic::SWITCH),
    146 	("while", basic::WHILE),
    147 ];
    148 
    149 fn tuplearray() void = {
    150 	assert(keywords[0].0 == "fn");
    151 	assert(keywords[1].0 == "for");
    152 	assert(keywords[2].0 == "if");
    153 	assert(keywords[3].0 == "in");
    154 	assert(keywords[4].0 == "not");
    155 	assert(keywords[5].0 == "switch");
    156 	assert(keywords[6].0 == "while");
    157 };
    158 
    159 export fn main() void = {
    160 	// TODO: Expand this test:
    161 	// - Declare & validate globals of more types
    162 	// - Globals which are pointers to other globals
    163 	write();
    164 	storage();
    165 	invariants();
    166 	static_binding();
    167 	pointers();
    168 	tagged();
    169 	tuplearray();
    170 };