# Actual compilation of the vector of tokens, ported from the "dirty tnsl" # that was originally written for the interpreter # CompData represents three vectors: # hsec - the heading of the output assembly # dsec - the data tied to the assembly # csec - the .text section that is the code of the assembly struct CompData { Vector hsec, dsec, csec } /; method CompData /; start self.hsec.start(1) self.dsec.start(1) self.csec.start(1) ;/ /; add (CompData c) self.hsec.add(c.hsec) self.dsec.add(c.dsec) self.csec.add(c.csec) ;/ /; _del self.hsec._del() self.dsec._del() self.csec._del() ;/ /; write_file(~void fd) /; loop (int i = 0; i < self.hsec.num_el) [i++] _write_byte(fd, self.hsec.get(i)) ;/ /; loop (int i = 0; i < self.dsec.num_el) [i++] _write_byte(fd, self.dsec.get(i)) ;/ /; loop (int i = 0; i < self.csec.num_el) [i++] _write_byte(fd, self.csec.get(i)) ;/ ;/ ;/ # Path represents the actual path of a file # that we are trying to tokenize # Assumes that the last item in the path array is a file name struct Path { int path_count, ~~uint8 split_path } /; method Path /; start (~uint8 path) self.split_path = _alloc(8) self.path_count = 0 self.relative_file(path) ;/ /; copy [Path] Path out ~uint8 f_pth = self.full_path() out.start(f_pth) _delete(f_pth) return out ;/ /; relative_file(~uint8 rel_path) # Assume the last string is the file name /; if (self.path_count > 0) int idx = self.path_count - 1 _delete(self.split_path{idx}) self.path_count-- ;/ ~uint8 n_ptr = _alloc(1) n_ptr{0} = 0 int idx = self.path_count /; loop (int i = 0; i < cstr_len(rel_path)) [i++] /; if (rel_path{i} == '\\' || rel_path{i} == '/') /; if (cstr_len(n_ptr) > 0) self.path_count++ idx = self.path_count self.split_path = _realloc(self.split_path, idx * 8) self.split_path{idx - 1} = n_ptr n_ptr = _alloc(1) n_ptr{0} = 0 ;/ ;; else idx = cstr_len(n_ptr) n_ptr = _realloc(n_ptr, idx + 2) n_ptr{idx} = rel_path{i} n_ptr{idx + 1} = 0 ;/ ;/ /; if (cstr_len(n_ptr) > 0) self.path_count++ idx = self.path_count self.split_path = _realloc(self.split_path, idx * 8) self.split_path{idx - 1} = n_ptr ;/ ;/ /; full_path [~uint8] ~uint8 pth = _alloc(1) pth{0} = 0 ~uint8 w_ptr = self.split_path{0} /; loop (int i = 0; i < self.path_count) [i++] w_ptr = self.split_path{i} int old_len = cstr_len(pth) int new_len = old_len + cstr_len(w_ptr) pth = _realloc(pth, new_len + 1) pth{new_len} = 0 /; loop (int j = 0; j < cstr_len(w_ptr)) [j++] pth{old_len + j} = w_ptr{j} ;/ /; if (i < self.path_count - 1) pth = _realloc(pth, new_len + 2) pth{new_len} = '/' pth{new_len + 1} = 0 ;/ ;/ return pth ;/ /; open_read [~void] ~uint8 path = self.full_path() ~void out = _open_file(path) _delete(path) return out ;/ /; open_write [~void] ~uint8 path = self.full_path() ~void out = _create_file(path) _delete(path) return out ;/ /; print_all /; loop (int i = 0; i < self.path_count) [i++] _printf(self.split_path{i}) ;/ ;/ /; _del /; loop (int i = 0; i < self.path_count) [i++] _delete(self.split_path{i}) ;/ _delete(self.split_path) ;/ ;/ ######################################## # Compiler functions - here be dragons # ######################################## enum POINTER_TYPE [uint8] { POINTER = 0, REFERENCE = 1, ARRAY = 2 } # 88 bytes long struct Type { int s, ~uint8 name, Vector ptr_chain, Vector members, ~Module mod } /; method Type /; start self.ptr_chain.start(1) # 136 is the size of one Variable struct self.members.start(136) ;/ /; _del self.ptr_chain._del() self.members._del() ;/ ;/ ############# # Variables # ############# # 136 bytes long struct Variable { Vector name, Type data_type, int location, loc_type } /; method Variable ;/ ########### # Modules # ########### struct Module { int i } /; method Module /; start ;/ /; _del ;/ ;/ /; base_loop_1 (Path in, Vector tokens, ~Module mod) ;/ /; base_loop_2 (Path in, Vector tokens, ~Module mod, ~CompData out) ;/ {}uint8 w_cstart = "Reading file: \0" {}uint8 w_nl = "\n\0" /; compile_file (Path in, ~Module mod) [CompData] ~uint8 pth = in.full_path() _printf(~w_cstart{0}) _printf(pth) _printf(~w_nl{0}) _delete(pth) ~void fd = in.open_read() Vector tokens = tokenize_file(fd) _close_file(fd) base_loop_1(in, tokens, mod) CompData out out.start() base_loop_2(in, tokens, mod, ~out) return out ;/ {}uint8 w_dsec = "\nsection .data\n\n\0" {}uint8 w_csec = "\nsection .text\n\n\0" {}uint8 w_compiled = "Compilation complete! Writing file.\n\0" /; compile (Path in, out) Module root root.start() CompData cd cd = compile_file(in, ~root) _printf(~w_compiled{0}) # Section headers for the asm ~uint8 shed = ~w_dsec{0} cd.hsec.add_str(shed) shed = ~w_csec{0} cd.dsec.add_str(shed) ~void fout = out.open_write() cd.write_file(fout) _close_file(fout) root._del() cd._del() ;/