# 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() ;/ ;/ # 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.split_path{0} = _alloc(1) self.path_count = 1 int i = 0 int j = cstr_len(path) /; loop (i < j) [i++] /; if (path{i} == '\\' || path{i} == '/') ;/ ;/ ;/ /; copy [Path] Path out out.start(self.full_path()) ;/ /; sub_folder (~uint8 sub) ~uint8 file_name ;/ /; relative_file(~uint8 rel_pth) [Path] ;/ /; full_path [~uint8] ~uint8 pth = _alloc(1) /; loop (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 ;/ /; _del /; loop (int i = 0; i < self.path_count) [i++] _delete(self.split_path{i}) ;/ _delete(self.split_path) ;/ ;/ # # Actual compiler code -- here be dragons # # Types of pointers the compiler may generate or work with enum PTR_TYPE [uint] { POINTER = 0, REFERENCE = 1, ARRAY = 2 } # Represents a type of a variable struct Type { int s, # size of type (bytes) p_ct, # ptr_chain count m_ct, # member count ~uint8 name, # name of the type ~uint ptr_chain, # for every pointer augment on the type, give it an extra PTR_TYPE in the chain ~Variable members, # member variables (their types and names) ~Module mod # the methods (if any) that are associated with this type } /; method Type /; start ;/ /; size [int] /; loop (int i = 0; i < self.p_ct) [i++] /; if (self.ptr_chain{i} == PTR_TYPE.REFERENCE) return 8 ;/ ;/ return self.s ;/ /; _del _delete(self.name) _delete(self.ptr_chain) _delete(self.members) _delete(self.mod) ;/ ;/ /; NO_TYPE [Type] Type t t.s = 0 t.name = 0 t.ptr_chain = 0 t.members = 0 t.mod = 0 return t ;/ /; is_primitive (~uint8 name) ;/ # Location type represents the type of memory # that the variable is stored in enum LOCATION [uint] { REGISTER = 0, STACK = 1, LABEL = 2, LITERAL = 3 } # The Big Kahuna struct Variable { ~uint8 name, Type _type, uint location, # Actual location. If literal, the literal value. # If register, corrosponds to a register name. # If stack, represents the offset from the base pointer # Ignore if label. loc_type } # I hate c-like strings. Hopefully once I'm done with this # language I'll have something that doesn't use them # This part sucks ass /; method Variable ;/ # Scopes struct Scope { int num, c, # Figure it out yourself tmp, ~Scope parent, ~uint8 name } /; method Scope ;/ struct Function { ~uint8 name, ~Type inputs, Type output, ~Module mod } /; method Function ;/ struct Module { ~Module parent, bool exp, # Export functions or not ~uint8 name, ~Type types, # Types defined in this module ~Variable defs, # Variables defined in this module ~Function functions, # Functions defined in this module ~Module sub # Sub modules } /; method Module ;/ # # Actual compiler functions # # Used in the first pass /; get_type_P1 ;/ /; get_type_P2 ;/ /; get_artifact [~~uint8] ;/ /; is_call [bool] ;/ /; is_definition ;/