From 61e1e5ce377719c8e9e437e5ba79ba06fc1de4ba Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Fri, 13 Dec 2024 16:10:14 -0500 Subject: Type generation for compile modules --- tnslc/README.md | 4 +- tnslc/build.sh | 2 +- tnslc/compile/compile.tnsl | 1 + tnslc/compile/generate.tnsl | 16 +++ tnslc/compile/outbuf.tnsl | 31 ++++++ tnslc/compile/type.tnsl | 250 ++++++++++++++++++++++++++++++++++++++++++-- tnslc/parse/ast.tnsl | 6 +- tnslc/utils/algo.tnsl | 7 ++ tnslc/utils/vector.tnsl | 35 +++++++ 9 files changed, 335 insertions(+), 17 deletions(-) create mode 100644 tnslc/compile/outbuf.tnsl (limited to 'tnslc') diff --git a/tnslc/README.md b/tnslc/README.md index 9a69f6b..88607eb 100644 --- a/tnslc/README.md +++ b/tnslc/README.md @@ -4,12 +4,12 @@ The reference compiler for the TNSL programming language. The compiler is writt ## Usage: -Place the [bootstrap compiler](https://git.cshift.net/CircleShift/ctc) `ctc` in this folder and execute `build.sh` +Place the [bootstrap compiler](https://git.cshift.net/CircleShift/ctc) `ctc` in this folder and execute `build.sh tnslc` The compiler outputs x86 NASM compatible assembly. Examples: - `./ctc dummy.tnsl dummy.asm` - Run the bootstrap compiler on the dummy file, output to dummy.asm -- `./build.sh` - Build the compiler +- `./build.sh tnslc` - Build the compiler ## License diff --git a/tnslc/build.sh b/tnslc/build.sh index 6bee3fc..537c7cc 100755 --- a/tnslc/build.sh +++ b/tnslc/build.sh @@ -5,7 +5,7 @@ ARTIFACT_DIR=$BUILD_DIR/artifacts mkdir -p $BUILD_DIR mkdir -p $ARTIFACT_DIR -filename=tnslc.tnsl +filename=$1 filename="${filename%.*}" ./ctc $filename.tnsl $ARTIFACT_DIR/$filename.asm nasm -g -f elf64 -o $ARTIFACT_DIR/$filename.o $ARTIFACT_DIR/$filename.asm diff --git a/tnslc/compile/compile.tnsl b/tnslc/compile/compile.tnsl index 3560f48..b980b62 100644 --- a/tnslc/compile/compile.tnsl +++ b/tnslc/compile/compile.tnsl @@ -1,4 +1,5 @@ /; module compile :import "type.tnsl" + :import "outbuf.tnsl" :import "generate.tnsl" ;/ diff --git a/tnslc/compile/generate.tnsl b/tnslc/compile/generate.tnsl index ef6a76c..c05a304 100644 --- a/tnslc/compile/generate.tnsl +++ b/tnslc/compile/generate.tnsl @@ -1,6 +1,22 @@ +/; generate_module (~OutBuf buf, ~Module mod) +;/ + /; generate (~utils.File fin, fout) parse.Node n = parse.generate_ast(fin) n.update_children() parse.print_ast(~n) + + OutBuf buf + buf.init() + + Module mod = transform_tree(~n, ~buf) + mod.print(0) + + + generate_module(~buf, ~mod) + buf.write_to_file(fout) + + mod.end() + buf.end() n.end() ;/ diff --git a/tnslc/compile/outbuf.tnsl b/tnslc/compile/outbuf.tnsl new file mode 100644 index 0000000..7394feb --- /dev/null +++ b/tnslc/compile/outbuf.tnsl @@ -0,0 +1,31 @@ +struct OutBuf { + utils.Vector + hsec, + dsec, + csec +} + +/; method OutBuf + /; init + self.hsec.init(1) + self.dsec.init(1) + self.csec.init(1) + ;/ + + /; write_to_file (~utils.File fout) + fout`.open() + fout`.write_cstr("bits 64\n\0") + fout`.write_cstr(self.hsec.as_cstr()) + fout`.write_cstr("\nsection .data\n\0") + fout`.write_cstr(self.dsec.as_cstr()) + fout`.write_cstr("\nsection .text\n\0") + fout`.write_cstr(self.csec.as_cstr()) + fout`.close() + ;/ + + /; end + self.hsec.end() + self.dsec.end() + self.csec.end() + ;/ +;/ diff --git a/tnslc/compile/type.tnsl b/tnslc/compile/type.tnsl index 474f705..28813ce 100644 --- a/tnslc/compile/type.tnsl +++ b/tnslc/compile/type.tnsl @@ -1,3 +1,9 @@ +/; _indent (int indent) + /; loop (int i = 0; i < indent) [i++] + _printf(" \0") + ;/ +;/ + struct Variable { ~uint8 name, ~Type _type, @@ -36,6 +42,27 @@ struct Variable { _delete(self.name) self.ptr.end() ;/ + + /; _prnt(int indent) + _printf(self.name) + + # todo: types and such + + _indent(indent) + _printf("}\n\0") + ;/ + + /; print (int indent) + _indent(indent) + _printf("{ Variable: \0") + _prnt(indent) + ;/ + + /; print_mem (int indent) + _indent(indent) + _printf("{ Member: \0") + _prnt(indent) + ;/ ;/ struct Type { @@ -64,6 +91,21 @@ struct Type { ;/ self.vars.end() ;/ + + /; print (int indent) + _indent(indent) + _printf("{ Type: \0") + _printf(self.name) + _print_num(" { size: %d }\n\0", self.size) + + /; loop (int i = 0; i < self.vars.count) [i++] + ~Variable v = self.vars.get(i) + v`.print_mem(indent + 1) + ;/ + + _indent(indent) + _printf("}\n\0") + ;/ ;/ struct Function { @@ -127,12 +169,27 @@ struct Enum { ;/ self.vals.end() ;/ + + /; print (int indent) + _indent(indent) + _printf("{ Enum: \0") + _printf(self.name) + _printf("\n\0") + + /; loop (int i = 0; i < self.vals.count) [i++] + ~Variable v = self.vals.get(i) + v`.print(indent + 1) + ;/ + + _indent(indent) + _printf("}\n\0") + ;/ ;/ struct Module { ~uint8 name, ~Module parent, - bool exp, + bool exp, mth, utils.Vector sub, vars, @@ -176,7 +233,9 @@ uint8 MOD_FIND_ENM = 4 ~Module s = self.sub.get(i) s`.update_children() ;/ - return self.sub.get(self.sub.count - 1) + ~Module out = self.sub.get(self.sub.count - 1) + out`.parent = ~self + return out ;/ /; add_var (~Variable v) @@ -201,7 +260,7 @@ uint8 MOD_FIND_ENM = 4 ;; else if ((sub + 1) < pth.count) /; loop (int i = 0; i < self.sub.count) [i++] ~Module m = self.sub.get(i) - /; if (utils.strcmp(pth.get(sub), m`.name) == true) + /; if (utils.strcmp(pth.get(sub), m`.name) == true && m`.mth == false) return _find_rec(pth, typ, sub + 1) ;/ ;/ @@ -209,7 +268,7 @@ uint8 MOD_FIND_ENM = 4 /; if (typ == MOD_FIND_SUB) /; loop (int i = 0; i < self.sub.count) [i++] ~Module m = self.sub.get(i) - /; if (utils.strcmp(pth.get(sub), m`.name) == true) + /; if (utils.strcmp(pth.get(sub), m`.name) == true && m`.mth == false) return self.sub.get(i) ;/ ;/ @@ -288,6 +347,36 @@ uint8 MOD_FIND_ENM = 4 ;/ self.enums.end() ;/ + + /; print (int indent) + _indent(indent) + /; if (self.mth == true) + _printf("{ Method: \0") + ;; else + _printf("{ Module: \0") + ;/ + _printf(self.name) + _printf("\n\0") + + + /; loop (int i = 0; i < self.sub.count) [i++] + ~Module s = self.sub.get(i) + s`.print(indent + 1) + ;/ + + /; loop (int i = 0; i < self.types.count) [i++] + ~Type s = self.types.get(i) + s`.print(indent + 1) + ;/ + + /; loop (int i = 0; i < self.enums.count) [i++] + ~Enum s = self.enums.get(i) + s`.print(indent + 1) + ;/ + + _indent(indent) + _printf("}\n\0") + ;/ ;/ {}~uint8 GEN_VAR_NAMES = { "int\0", "int8\0", "int16\0", "int32\0", "int64\0", "uint\0", "uint8\0", "uint16\0", "uint32\0", "uint64\0", "float\0", "float32\0", "float64\0", "vect\0", "bool\0", "void\0" } @@ -298,21 +387,26 @@ uint8 MOD_FIND_ENM = 4 return NULL ;/ -/; transform_struct(~parse.Node n, ~Module parent) +/; transform_struct(~parse.Node n, ~Module m) ;/ -/; _tfn_mod_loop (~parse.Node n, ~Module m) +/; transform_enum(~parse.Node n, ~OutBuf b, ~Module m) +;/ + +/; _tfn_mod_loop (~parse.Node n, ~OutBuf b, ~Module m) /; loop (int i = 0; i < n`.sub.count) [i++] ~parse.Node s = n`.sub.get(i) /; if (s`._type == parse.NTYPE_MODULE || s`._type == parse.NTYPE_EXPORT) - transform_module(s, m) + transform_module(s, b, m) ;; else if (s`._type == parse.NTYPE_STRUCT) transform_struct(s, m) + ;; else if (s`._type == parse.NTYPE_ENUM) + transform_enum(s, b, m) ;/ ;/ ;/ -/; transform_module (~parse.Node n, ~Module parent) +/; transform_module (~parse.Node n, ~OutBuf b, ~Module parent) ~Module s = NULL /; loop (int i = 0; i < parent`.sub.count) [i++] @@ -336,25 +430,159 @@ uint8 MOD_FIND_ENM = 4 s = parent`.add_sub(~out) ;/ - _tfn_mod_loop(n, s) + _tfn_mod_loop(n, b, s) ;/ +# +# GEN DEFAULT TYPES +# + /; _tfn_gen_default_types (~Module m) + Module d + d.init(utils.strcpy("#\0")) + ~Module dp = m`.add_sub(~d) /; loop (int i = 0; i < len GEN_VAR_NAMES) [i++] Type t t.init(utils.strcpy(GEN_VAR_NAMES{i})) t.size = GEN_VAR_SIZES{i} + t.methods = dp m`.add_type(~t) ;/ ;/ -/; transform_tree (~parse.Node n) [Module] +# +# GEN TYPES & ENUMS FIRST PASS +# + +/; _tfn_gen_types_mod(~parse.Node n, ~Module m) + ~Module s = NULL + + /; loop (int i = 0; i < m`.sub.count) [i++] + ~Module tmp = m`.sub.get(i) + /; if (utils.strcmp(n`.data, tmp`.name) == true) + s = tmp + ;/ + ;/ + + ~int cmp = s + /; if (cmp == NULL) + Module out + out.init(utils.strcpy(n`.data)) + + /; if (n`._type == parse.NTYPE_EXPORT) + out.exp = true + ;; else + out.exp = false + ;/ + + s = m`.add_sub(~out) + ;/ + + _tfn_gen_types(n, s) +;/ + +/; _tfn_gen_types (~parse.Node n, ~Module m) + /; loop (int i = 0; i < n`.sub.count) [i++] + ~parse.Node s = n`.sub.get(i) + /; if (s`._type == parse.NTYPE_MODULE || s`._type == parse.NTYPE_EXPORT) + _tfn_gen_types_mod(s, m) + ;; else if (s`._type == parse.NTYPE_STRUCT) + Module mth + mth.init(utils.stradd("_#\0", s`.data)) + ~Module mp = m`.add_sub(~mth) + + Type t + t.size = 0 + t.init(utils.strcpy(s`.data)) + t.methods = mp + m`.add_type(~t) + ;; else if (s`._type == parse.NTYPE_ENUM) + Enum e + e.init(utils.strcpy(s`.data)) + m`.add_enum(~e) + ;/ + ;/ +;/ + +# Main transform functions + +/; _td_rec(~parse.Node n, ~utils.Artifact a) + /; if (n`.eq(".\0") == true && n`.sub.count > 1) + ~parse.Node tmp = n`.sub.get(0) + _td_rec(tmp, a) + tmp = n`.sub.get(1) + _td_rec(tmp, a) + ;; else if (n`._type == parse.NTYPE_ID) + a`.push(utils.strcpy(n`.data)) + ;/ +;/ + +/; transform_dot(~parse.Node n) [utils.Artifact] + utils.Artifact out + out.init() + + _td_rec(n, ~out) + + return out +;/ + +/; art_from_type(~parse.Node n) [utils.Artifact] + utils.Artifact out + out.init() + + /; if (n`._type !== parse.NTYPE_TYPE) + return out + ;/ + + /; loop (int i = 0; i < n`.sub.count) [i++] + ~parse.Node s = n`.sub.get(i) + /; if (s`._type == parse.NTYPE_ID) + out.push(utils.strcpy(s`.data)) + ;/ + ;/ + + return out +;/ + +/; vec_from_type(~parse.Node n) [utils.Vector] + utils.Vector out + out.init(8) + + /; if (n`._type !== parse.NTYPE_TYPE) + return out + ;/ + + int nm + /; loop (int i = 0; i < n`.sub.count) [i++] + ~parse.Node s = n`.sub.get(i) + /; if (s`._type == parse.NTYPE_PRE_OP) + /; if (s`.eq("~\0") == true) + nm = 0 - 1 + ;; else if (s`.eq("{\0") == true) + # TODO: WHATEVER + nm = 0 - 2 + ;/ + out.push(~nm) + ;; else if (s`._type == parse.NTYPE_POST_OP) + /; if (s`.eq("`\0") == true) + nm = 0 + out.push(~nm) + ;/ + ;/ + ;/ + + return out +;/ + +/; transform_tree (~parse.Node n, ~OutBuf buf) [Module] Module out out.init(utils.strcpy(n`.data)) out.exp = true _tfn_gen_default_types(~out) - _tfn_mod_loop(n, ~out) + _tfn_gen_types(n, ~out) + out.update_children() + _tfn_mod_loop(n, buf, ~out) return out ;/ diff --git a/tnslc/parse/ast.tnsl b/tnslc/parse/ast.tnsl index 420f3d3..588f3fd 100644 --- a/tnslc/parse/ast.tnsl +++ b/tnslc/parse/ast.tnsl @@ -912,7 +912,7 @@ int errors_shown = 0 _ast_decl(fin, ~list, first) ;; else if (first`._type == TTYPE_USRWD || first`.eq("~\0") == true) _maybe_helper_fun(fin, ~list, first, true) - ;; else if (first`._type == TTYPE_LITRL || _op_prefix(first)) + ;; else if (first`._type == TTYPE_LITRL || first`.eq("(\0") == true || _op_prefix(first)) _ast_value(fin, ~list, first, true) ;; else if (first`._type == TTYPE_KEYWD) _ast_keyword_expr(fin, ~list, first) @@ -1054,7 +1054,7 @@ int errors_shown = 0 _ast_decl(fin, ~out, first) ;; else if (first`._type == TTYPE_USRWD || first`.eq("~\0") == true) _maybe_helper_fun(fin, ~out, first, false) - ;; else if (first`._type == TTYPE_LITRL || _op_prefix(first)) + ;; else if (first`._type == TTYPE_LITRL || first`.eq("(\0") == true || _op_prefix(first)) _ast_value(fin, ~out, first, false) ;; else if (first`._type == TTYPE_KEYWD) _ast_keyword_expr(fin, ~out, first) @@ -1815,7 +1815,7 @@ int errors_shown = 0 _ast_decl(fin, ~fn, first) ;; else if (first`._type == TTYPE_USRWD || first`.eq("~\0") == true) _maybe_helper_fun(fin, ~fn, first, false) - ;; else if (first`._type == TTYPE_LITRL || _op_prefix(first)) + ;; else if (first`._type == TTYPE_LITRL || first`.eq("(\0") == true || _op_prefix(first)) _ast_value(fin, ~fn, first, false) ;; else if (first`._type == TTYPE_KEYWD) _ast_keyword_expr(fin, ~fn, first) diff --git a/tnslc/utils/algo.tnsl b/tnslc/utils/algo.tnsl index 73cfb7f..35ac35c 100644 --- a/tnslc/utils/algo.tnsl +++ b/tnslc/utils/algo.tnsl @@ -200,6 +200,13 @@ return out.as_cstr() ;/ +/; stradd(~uint8 a, ~uint8 b) [~uint8] + Vector out + out.from_cstr(a) + out.push_cstr(b) + return out.as_cstr() +;/ + /; unquote_cha(~uint8 cha) [uint8] /; if (cha` !== '\\') return cha` diff --git a/tnslc/utils/vector.tnsl b/tnslc/utils/vector.tnsl index d00d698..38c45fc 100644 --- a/tnslc/utils/vector.tnsl +++ b/tnslc/utils/vector.tnsl @@ -67,6 +67,22 @@ uint VECTOR_MAX_GROW = 256 ;/ /; pop + self.remove(self.count - 1) + ;/ + + /; remove (int index) + /; if (index < 0 || index !< self.count) + return + ;/ + + /; if (self.count > 1) + /; loop (int i = index * self._elsz; i < (self.count - 1) * self._elsz) [i++] + ~uint8 to = self.data + i + ~uint8 from = self.data + i + self._elsz + to` = from` + ;/ + ;/ + self.count-- /; if (self.count < self.size / 2) @@ -96,6 +112,25 @@ uint VECTOR_MAX_GROW = 256 self._elsz = 0 _delete(self.data) ;/ + + /; copy [Vector] + Vector out + + out.init(self._elsz) + /; loop (int i = 0; i < self.count) [i++] + ~int tmp = self.get(i) + out.push(tmp) + ;/ + + return out + ;/ + + /; back [~void] + /; if (self.count > 0) + return self.get(self.count - 1) + ;/ + return NULL + ;/ ;/ -- cgit v1.2.3