From 12752c062bbffda762ef8129ee3db851b8e7aee4 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 17:31:32 +0300 Subject: [PATCH 01/17] compiler: remove code generation --- src/julec/obj/cxx/derive.jule | 22 - src/julec/obj/cxx/expr.jule | 1283 -------------------------------- src/julec/obj/cxx/ident.jule | 211 ------ src/julec/obj/cxx/object.jule | 1205 ------------------------------ src/julec/obj/cxx/scope.jule | 791 -------------------- src/julec/obj/cxx/testing.jule | 156 ---- src/julec/obj/cxx/type.jule | 330 -------- 7 files changed, 3998 deletions(-) delete mode 100644 src/julec/obj/cxx/derive.jule delete mode 100644 src/julec/obj/cxx/expr.jule delete mode 100644 src/julec/obj/cxx/ident.jule delete mode 100644 src/julec/obj/cxx/object.jule delete mode 100644 src/julec/obj/cxx/scope.jule delete mode 100644 src/julec/obj/cxx/testing.jule delete mode 100644 src/julec/obj/cxx/type.jule diff --git a/src/julec/obj/cxx/derive.jule b/src/julec/obj/cxx/derive.jule deleted file mode 100644 index 64fd72fe1..000000000 --- a/src/julec/obj/cxx/derive.jule +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use std::jule::sema::{Struct} - -struct DeriveCoder {} - -impl DeriveCoder { - static fn clone_func_decl(&s: &Struct): str { - let mut obj = TypeCoder.structure(s) - obj += " clone(void) const " - ret obj - } - - static fn clone_func_def(&s: &Struct): str { - let mut obj = TypeCoder.structure(s) - obj += " " + obj - obj += "::clone(void) const " - ret obj - } -} \ No newline at end of file diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule deleted file mode 100644 index 24e2792f0..000000000 --- a/src/julec/obj/cxx/expr.jule +++ /dev/null @@ -1,1283 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use env -use optimizing::{ - UnsafeBinopExprModel, - UnsafeIndexingExprModel, - PushToSliceExprModel, - MutSlicingExprModel, - StrInsertBeginExprModel, -} -use conv for std::conv -use std::env::{ARCH} -use fmt for std::fmt -use std::jule::build::{Directive, is_64bit} -use std::jule::constant::{Const} -use std::jule::lex::{Token, TokenKind} -use std::jule::sema::{ - Var, - Struct, - FnIns, - Trait, - StructIns, - TypeKind, - Data, - Value, - ExprModel, - BinopExprModel, - UnaryExprModel, - StructLitExprModel, - AllocStructLitExprModel, - CastingExprModel, - FnCallExprModel, - SliceExprModel, - IndexingExprModel, - AnonFnExprModel, - MapExprModel, - SlicingExprModel, - TraitSubIdentExprModel, - StructSubIdentExprModel, - ArrayExprModel, - CommonIdentExprModel, - CommonSubIdentExprModel, - TupleExprModel, - BuiltinOutCallExprModel, - BuiltinOutlnCallExprModel, - BuiltinCloneCallExprModel, - BuiltinNewCallExprModel, - BuiltinPanicCallExprModel, - BuiltinAssertCallExprModel, - BuiltinMakeCallExprModel, - BuiltinAppendCallExprModel, - BuiltinErrorCallExprModel, - SizeofExprModel, - AlignofExprModel, - RuneExprModel, - StructStaticIdentExprModel, - IntegratedToStrExprModel, - BackendEmitExprModel, - FreeExprModel, - OperandExprModel, - Scope, -} -use types for std::jule::types::{ - MAX_F32, - MAX_F64, - MIN_F32, - MIN_F64, - MAX_I64, - MIN_I64, - MAX_U64, -} -use math for std::math -use strings for std::strings -use utf8 for std::unicode::utf8 - -// Ignore expression for std::tie function. -const CPP_IGNORE = "std::ignore" - -// Represents default expression for type. -const CPP_DEFAULT_EXPR = "{}" - -struct ExprCoder { - oc: &ObjectCoder -} - -impl ExprCoder { - static fn new(mut &oc: &ObjectCoder): &ExprCoder { - ret &ExprCoder{ - oc: oc, - } - } - - fn string(self, &c: &Const): str { - let content = c.read_str() - if content.len == 0 { // Empty. - ret TypeCoder.Str + "()" - } - let bytes = []byte(content) - let len = conv::fmt_int(i64(bytes.len), 10) - let lit = cstr_lit(bytes) - ret TypeCoder.Str + "(" + lit + ", " + len + ")" - } - - fn boolean(self, &c: &Const): str { - if c.read_bool() { - ret "true" - } - ret "false" - } - - fn nil_lit(self): str { - ret "nullptr" - } - - fn ftoa_special_cases(self, &x: f64): str { - match { - | math::is_nan(x): - ret "NAN" - | math::is_inf(x, 1): - ret "INFINITY" - | math::is_inf(x, -1): - ret "-INFINITY" - |: - ret "" - } - } - - fn float32(self, &c: &Const): str { - let x = c.as_f64() - - // Special cases. - let f = self.ftoa_special_cases(x) - if f != "" { - ret f - } - - match { - | x == MAX_F32: - ret "jule::MAX_F32" - | x == MIN_F32: - ret "jule::MIN_F32" - |: - ret ftoa(x, 32) + "f" - } - } - - fn float64(self, &c: &Const): str { - let x = c.as_f64() - - // Special cases. - let f = self.ftoa_special_cases(x) - if f != "" { - ret f - } - - match { - | x == MAX_F64: - ret "jule::MAX_F64" - | x == MIN_F64: - ret "jule::MIN_F64" - |: - ret ftoa(x, 64) - } - } - - // fx32: 32-bit floating-point - fn constant(self, mut c: &Const, fx32: bool): str { - match { - | c.is_str(): - ret self.string(c) - | c.is_bool(): - ret self.boolean(c) - | c.is_f64(): - match { - | fx32: - ret self.float32(c) - |: - ret self.float64(c) - } - | c.is_i64(): - ret itoa(c.read_i64()) - | c.is_u64(): - ret utoa(c.read_u64()) - | c.is_nil(): - ret self.nil_lit() - |: - ret "" - } - } - - fn div_by_zero_binary(mut self, &op: &Token, mut &l: &OperandExprModel, mut &r: &OperandExprModel): str { - let mut op_func = "" - match op.kind { - | TokenKind.Solidus - | TokenKind.SolidusEq: - op_func = "div" - | TokenKind.Percent - | TokenKind.PercentEq: - op_func = "mod" - } - - let mut obj = "jule::" - obj += op_func - obj += "(" - if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(op) - obj += "\"," - } - obj += self.expr(l.model) - obj += "," - obj += self.expr(r.model) - obj += ")" - ret obj - } - - fn unsafe_binary(mut self, mut m: &BinopExprModel): str { - let mut obj = "(" - obj += self.model(m.left.model) - obj += " " - obj += m.op.kind - obj += " " - obj += self.model(m.right.model) - obj += ")" - ret obj - } - - fn binary(mut self, mut m: &BinopExprModel): str { - match m.op.kind { - | TokenKind.Solidus | TokenKind.Percent: - // Do not check division of structures safety. - if m.left.kind.strct() == nil { - ret self.div_by_zero_binary(m.op, m.left, m.right) - } - } - ret self.unsafe_binary(m) - } - - fn var(self, mut m: &Var): str { - if m.cpp_linked { - let d = find_directive(m.directives, Directive.Namespace) - if d != nil { - let mut obj = concat_all_parts(d.args...) - obj += "::" - obj += IdentCoder.var(m) - ret obj - } - } - ret IdentCoder.var(m) - } - - fn structure(self, m: &Struct): str { - ret TypeCoder.structure(m) - } - - fn structure_ins(self, mut m: &StructIns): str { - ret TypeCoder.structure_ins(m) - } - - fn unary(mut self, mut m: &UnaryExprModel): str { - match m.op.kind { - | TokenKind.Caret: - let mut obj = "(~(" - obj += self.expr(m.expr.model) - obj += "))" - ret obj - | TokenKind.Star: - if env::PRODUCTION || m.expr.kind.sptr() == nil { - break - } - let mut obj = self.expr(m.expr.model) - obj += ".get(\"" - obj += self.oc.loc_info(m.op) - obj += "\")" - ret obj - } - - let mut obj = "(" - obj += m.op.kind - obj += "(" - obj += self.expr(m.expr.model) - obj += "))" - ret obj - } - - fn cpp_structure_lit(mut self, mut m: &StructLitExprModel): str { - let mut obj = "(" + TypeCoder.structure_ins(m.strct) - obj += "){" - if m.args.len > 0 { - iter: - for (_, mut f) in m.strct.fields { - if m.strct.decl.cpp_linked { - for (_, mut arg) in m.args { - if arg.field == f { - obj += "." - obj += IdentCoder.field(f.decl) - obj += "=" - obj += self.expr(arg.expr) - obj += "," - continue iter - } - } - continue - } - obj += IdentCoder.field(f.decl) - obj += ": " - for (_, mut arg) in m.args { - if arg.field == f { - obj += self.expr(arg.expr) - obj += "," - continue iter - } - } - obj += self.init_expr(f.kind) - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - } - obj += "}" - ret obj - } - - fn structure_lit(mut self, mut m: &StructLitExprModel): str { - if m.strct.decl.cpp_linked { - ret self.cpp_structure_lit(m) - } - - let mut obj = IdentCoder.structure_ins(m.strct) - obj += "(" - if m.args.len > 0 { - iter: - for (_, mut f) in m.strct.fields { - for (_, mut arg) in m.args { - if arg.field == f { - obj += self.expr(arg.expr) - obj += "," - continue iter - } - } - obj += self.init_expr(f.kind) - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - } - obj += ")" - ret obj - } - - fn alloc_structure(mut self, mut m: &AllocStructLitExprModel): str { - let mut obj = "jule::new_ptr<" - obj += IdentCoder.structure_ins(m.lit.strct) - obj += ">(" - obj += self.structure_lit(m.lit) - obj += ")" - ret obj - } - - fn casting(mut self, mut m: &CastingExprModel): str { - let mut obj = "" - match { - | m.kind.prim() != nil && m.kind.prim().is_any(): - obj += TypeCoder.kind(m.kind) - obj += "(" - obj += self.model(m.expr) - obj += ")" - | m.expr_kind.ptr() != nil - | m.kind.ptr() != nil: - obj += "((" - obj += TypeCoder.kind(m.kind) - obj += ")(" - obj += self.expr(m.expr) - obj += "))" - | m.expr_kind.trt() != nil - | m.expr_kind.prim() != nil && m.expr_kind.prim().is_any(): - obj += self.model(m.expr) - obj += "." - if env::PRODUCTION { - obj += "operator " - obj += TypeCoder.kind(m.kind) - obj += "()" - } else { - if m.expr_kind.trt() != nil && m.kind.sptr() != nil { - obj += "cast_ptr<" - obj += TypeCoder.kind(m.kind.sptr().elem) - } else { - obj += "cast<" - obj += TypeCoder.kind(m.kind) - } - obj += ">(\"" - obj += self.oc.loc_info(m.token) - obj += "\")" - } - | m.kind.trt() != nil: - obj += TypeCoder.kind(m.kind) - obj += "(" - obj += self.expr(m.expr) - obj += ", " - obj += conv::itoa(self.oc.find_type_offset(m.kind.trt(), m.expr_kind)) - obj += ")" - |: - obj += "static_cast<" - obj += TypeCoder.kind(m.kind) - obj += ">(" - obj += self.expr(m.expr) - obj += ")" - } - ret obj - } - - fn args(mut self, mut args: []ExprModel): str { - if args.len == 0 { - ret "" - } - let mut obj = "" - for (_, mut a) in args { - obj += self.expr(a) - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - ret obj - } - - fn model_for_call(mut self, mut expr: ExprModel): str { - match type expr { - | &FnIns: - ret self.func_ins((&FnIns)(expr)) - | &StructSubIdentExprModel: - let mut ssie = (&StructSubIdentExprModel)(expr) - if ssie.method != nil { - ret self.func_ins(ssie.method) - } - } - ret self.model(expr) - } - - fn push_call_inf(mut self, mut &obj: str, &m: &FnCallExprModel) { - if env::PRODUCTION || (!m.func.anon && !is_builtin_call_has_debuginf(m)) { - obj += "(" - ret - } - if m.func.anon { - match type m.expr { - | &StructSubIdentExprModel: - if (&StructSubIdentExprModel)(m.expr).field.decl.owner.cpp_linked { - obj += "(" - ret - } - fall - |: - obj += ".call" - } - } - obj += "(\"" - obj += self.oc.loc_info(m.token) - obj += "\"" - if m.args.len != 0 { - obj += "," - } - } - - fn pure_func_call(mut self, mut &m: &FnCallExprModel): str { - let mut obj = self.model_for_call(m.expr) - if !m.func.is_builtin() { - if m.func.decl.cpp_linked && m.func.generics.len > 0 { - if !has_directive(m.func.decl.directives, Directive.Cdef) { - obj += "<" - for (_, mut g) in m.func.generics { - obj += TypeCoder.kind(g) - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - obj += ">" - } - } - } - self.push_call_inf(obj, m) - let mut locinfo = false - let mut wrap_receiver = "" - if !m.func.is_builtin() && m.func.decl.params.len > 0 && m.func.decl.params[0].is_self() { - match type m.expr { - | &StructSubIdentExprModel: - let mut ssie = (&StructSubIdentExprModel)(m.expr) - match { - | m.func.decl.params[0].is_ref(): - obj += self.model(ssie.expr) - | ssie.expr_kind.sptr() != nil: - obj += self.model(ssie.expr) - obj += ".ptr(" - if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"" - } - obj += ")" - |: - if ssie.expr.kind.strct() != nil { - // Add address taking operation for non-pointers. - obj += "&" - if !ssie.expr.lvalue { - wrap_receiver = self.model(ssie.expr) - } - } - if wrap_receiver != "" { - obj += "_wrap_copy" - } else { - obj += self.model(ssie.expr) - } - } - if m.args.len > 0 { - obj += ", " - } - | &TraitSubIdentExprModel: - obj += self.model((&TraitSubIdentExprModel)(m.expr).expr) - if !env::PRODUCTION { - locinfo = true - } - if m.args.len > 0 { - obj += ", " - } - } - } - obj += self.args(m.args) - if locinfo { - obj += ", \"" - obj += self.oc.loc_info(m.token) - obj += "\"" - } - obj += ")" - - if wrap_receiver != "" { - obj = "({ auto _wrap_copy = " + wrap_receiver + "; " + obj - obj += "; })" - } - - if m.is_co { - obj = "__JULE_CO(" + obj - obj += ")" - } - - ret obj - } - - fn func_call(mut self, mut m: &FnCallExprModel): str { - if m.func.is_builtin() || - !m.func.decl.exceptional || - m.except != nil && m.except.stmts.len == 0 { - ret self.pure_func_call(m) - } - - // Generate code for exceptional. - let mut obj = "({\n" - self.oc.add_indent() - obj += self.oc.indent() - obj += "auto except = " - obj += self.pure_func_call(m) - obj += ";\n" - obj += self.oc.indent() - if m.except != nil { - if m.func.result == nil || !m.assigned { - obj += "if (!except.ok()) " - obj += self.oc.sc.scope(m.except) - obj += "\n" - } else { - let forwarded = is_forwarded(m.except) - obj += "(except.ok()) ? (except.result) : (" - if forwarded { - obj += "{" - } - obj += self.oc.sc.scope(m.except) - if forwarded { - obj += " " - obj += self.init_expr(m.func.result) - obj += ";}" - } - obj += ");\n" - } - self.oc.done_indent() - } else { - obj += `if (!except.ok()) jule::panic(jule::Str("` - obj += `unhandled exceptional: ") + except.error.type->to_str(except.error.data) + jule::Str("\nlocation: ` - obj += self.oc.loc_info(m.token) - obj += "\"));\n" - if !m.func.decl.is_void() { - obj += self.oc.indent() - obj += "(except.result);\n" - } - self.oc.done_indent() - } - - obj += self.oc.indent() - obj += "})" - ret obj - } - - fn slice(mut self, mut m: &SliceExprModel): str { - if m.elems.len == 0 { - ret TypeCoder.as_slice(m.elem_kind) + "()" - } - let mut obj = TypeCoder.as_slice(m.elem_kind) - obj += "({" - obj += self.args(m.elems) - obj += "})" - ret obj - } - - fn indexing(mut self, mut m: &IndexingExprModel): str { - let mut obj = self.model(m.expr.model) - // Index access with safety measures. - match { - | env::PRODUCTION - | m.expr.kind.ptr() != nil - | m.expr.kind.map() != nil: - obj += "[" - obj += self.expr(m.index.model) - obj += "]" - |: - obj += ".at(\"" - obj += self.oc.loc_info(m.token) - obj += "\"," - obj += self.expr(m.index.model) - obj += ")" - } - ret obj - } - - fn unsafe_indexing(mut self, mut m: &UnsafeIndexingExprModel): str { - let mut obj = self.model(m.node.expr.model) - // Index access with safety measures. - match { - | env::PRODUCTION - | m.node.expr.kind.ptr() != nil - | m.node.expr.kind.map() != nil: - obj += "[" - obj += self.expr(m.node.index.model) - obj += "]" - |: - obj += ".__at(" - obj += self.expr(m.node.index.model) - obj += ")" - } - ret obj - } - - fn anon_func(mut self, mut m: &AnonFnExprModel): str { - let mut obj = TypeCoder.func(m.func) - obj += "([=]" - obj += self.oc.params_ins(m.func.params) - obj += " mutable -> " - obj += TypeCoder.func_ins_result(m.func) - obj += " " - obj += self.oc.sc.func_scope(m.func) - obj += ")" - ret obj - } - - fn map(mut self, mut m: &MapExprModel): str { - let mut obj = TypeCoder.Map + "<" - obj += TypeCoder.kind(m.key_kind) - obj += "," - obj += TypeCoder.kind(m.val_kind) - obj += ">({" - if m.entries.len > 0 { - for (_, mut pair) in m.entries { - let mut pair_obj = "{" - pair_obj += self.expr(pair.key) - pair_obj += "," - pair_obj += self.expr(pair.val) - pair_obj += "}" - obj += pair_obj - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - } - obj += "})" - ret obj - } - - fn slicing(mut self, mut m: &SlicingExprModel): str { - let mut obj = self.model(m.expr) - obj += ".slice(" - if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"," - } - obj += self.expr(m.left) - if m.right != nil { - obj += "," - obj += self.expr(m.right) - } - obj += ")" - ret obj - } - - fn trait_sub(mut self, mut m: &TraitSubIdentExprModel): str { - let mut obj = IdentCoder.trait_decl(m.trt) - obj += "_mptr_data" - obj += "[(" - obj += self.model(m.expr) - obj += ").type_offset]." - obj += IdentCoder.func(m.method) - ret obj - } - - fn structure_sub(mut self, mut m: &StructSubIdentExprModel): str { - let mut obj = self.model(m.expr) - if m.field != nil { - if m.expr_kind.ptr() != nil { - obj += "->" - } else if m.expr_kind.sptr() != nil { - obj += ".get(" - if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"" - } - obj += ")." - } else { - obj += "." - } - obj += IdentCoder.field(m.field.decl) - } - ret obj - } - - fn common_ident(self, m: &CommonIdentExprModel): str { - ret m.ident - } - - fn common_sub(mut self, mut m: &CommonSubIdentExprModel): str { - let mut obj = self.model(m.expr) - match { - | m.expr_kind.ptr() != nil: - obj += "->" - | m.expr_kind.sptr() != nil: - obj += ".get(" - if !env::PRODUCTION { - obj += "\n" - obj += self.oc.loc_info(m.token) - obj += "\n" - } - obj += ")." - |: - obj += "." - } - obj += m.ident - ret obj - } - - fn array(mut self, mut m: &ArrayExprModel): str { - let mut obj = TypeCoder.array(m.kind) - if m.elems.len == 0 { - obj += "()" - ret obj - } - - // Filled. - if m.elems.len == 2 && m.elems[1] == nil { - obj += "(" - obj += self.expr(m.elems[0]) - obj += ")" - ret obj - } - - obj += "({" - obj += self.args(m.elems) - obj += "})" - ret obj - } - - // Returns complete expression model of function instance. - // Usefull for strict type safety. - fn func_ins_common(self, mut m: &FnIns): str { - let mut obj = TypeCoder.func(m) - obj += "(" - obj += self.func_ins(m) - obj += ")" - ret obj - } - - // Returns elementary expression model of function instance. - fn func_ins(self, mut m: &FnIns): str { - if m.decl != nil && m.decl.cpp_linked { - let d = find_directive(m.decl.directives, Directive.Namespace) - if d != nil { - let mut obj = concat_all_parts(d.args...) - obj += "::" - obj += IdentCoder.func_ins(m) - ret obj - } - } - ret IdentCoder.func_ins(m) - } - - fn tuple(mut self, mut m: &TupleExprModel): str { - let mut obj = "std::make_tuple(" - for (_, mut d) in m.datas { - obj += self.expr(d.model) - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - obj += ")" - ret obj - } - - fn new_call(mut self, mut m: &BuiltinNewCallExprModel): str { - let mut obj = "jule::new_ptr<" - obj += TypeCoder.kind(m.kind) - obj += ">(" - if m.init != nil { - obj += self.expr(m.init) - } - obj += ")" - ret obj - } - - fn out_call(mut self, mut m: &BuiltinOutCallExprModel): str { - if m.debug && env::PRODUCTION { - ret "" - } - let mut obj = "jule::out(" - obj += self.expr(m.expr) - obj += ")" - ret obj - } - - fn outln_call(mut self, mut m: &BuiltinOutlnCallExprModel): str { - if m.debug && env::PRODUCTION { - ret "" - } - let mut obj = "jule::outln(" - obj += self.expr(m.expr) - obj += ")" - ret obj - } - - fn panic_call(mut self, mut m: &BuiltinPanicCallExprModel): str { - let mut obj = "jule::panic(" - obj += self.expr(m.expr) - obj += ` + jule::Str("\nlocation: ` - obj += self.oc.loc_info(m.token) - obj += "\"));" - ret obj - } - - fn assert_call(mut self, mut m: &BuiltinAssertCallExprModel): str { - if env::PRODUCTION { - ret "" - } - let mut obj = "if (!(" - obj += self.expr(m.expr) - obj += ")) jule::panic(jule::Str(" - obj += cstr_lit([]byte(m.log)) - obj += `) + jule::Str("\nlocation: ` - obj += self.oc.loc_info(m.token) - obj += "\"));" - ret obj - } - - fn error_call(mut self, mut m: &BuiltinErrorCallExprModel): str { - let mut obj = "return " - if m.func.decl.is_void() { - obj += "jule::VoidExceptional(" - } else { - obj += "jule::Exceptional<" - obj += TypeCoder.kind(m.func.result) - obj += ">(" - } - obj += self.expr(m.err) - obj += ")" - ret obj - } - - fn make_call(mut self, mut m: &BuiltinMakeCallExprModel): str { - let mut obj = "" - if m.len != nil { - obj += self.expr(m.len) - } else { - obj += "0" - } - if m.cap != nil { - obj += "," + self.expr(m.cap) - } - - if m.kind.slc().elem.enm() != nil { - obj += "," - obj += self.init_expr(m.kind.slc().elem) - if m.cap != nil { - obj = TypeCoder.kind(m.kind) + "::alloc(" + obj - } else { - obj = TypeCoder.kind(m.kind) + "::alloc_def(" + obj - } - } else { - obj = TypeCoder.kind(m.kind) + "::alloc(" + obj - } - - obj += ")" - ret obj - } - - fn push_to_slice(mut self, mut m: &PushToSliceExprModel): str { - let dest = self.model(m.dest) - let mut obj = dest - obj += " = jule::alloc_for_append(" - obj += dest - obj += "," - obj += conv::itoa(m.elems.elems.len) - obj += ");" - for (_, mut e) in m.elems.elems { - obj += dest - // Use the "__push" function to skip allocation boundary checking. - obj += ".__push(" - obj += self.model(e) - obj += ");" - } - ret obj - } - - fn append_call(mut self, mut m: &BuiltinAppendCallExprModel): str { - let mut obj = "jule::append(" - obj += self.model(m.dest) - obj += "," - obj += self.model(m.elements) - obj += ")" - ret obj - } - - fn clone_call(mut self, mut m: &BuiltinCloneCallExprModel): str { - let mut obj = "jule::clone(" - obj += self.model(m.expr) - obj += ")" - ret obj - } - - fn sizeof(mut self, mut m: &SizeofExprModel): str { - let mut obj = "sizeof(" - obj += self.expr(m.expr) - obj += ")" - ret obj - } - - fn alignof(mut self, mut m: &AlignofExprModel): str { - let mut obj = "alignof(" - obj += self.expr(m.expr) - obj += ")" - ret obj - } - - fn rune_lit(self, m: &RuneExprModel): str { - if m.code <= 127 { // ASCII - let mut b = sbtoa(byte(m.code)) - if b == "'" { - b = "\\'" - } - ret "'" + b + "'" - } - ret itoa(i64(m.code)) - } - - fn structure_static(self, mut m: &StructStaticIdentExprModel): str { - ret IdentCoder.func_ins(m.method) - } - - fn integrated_to_str(mut self, mut m: &IntegratedToStrExprModel): str { - let mut obj = "jule::to_str(" - obj += self.model(m.expr) - obj += ")" - ret obj - } - - fn backend_emit(mut self, mut m: &BackendEmitExprModel): str { - if m.exprs.len == 0 { - ret m.code - } - for (i, mut expr) in m.exprs { - m.exprs[i] = self.expr(expr) - } - ret fmt::format(m.code, m.exprs...) - } - - fn free(mut self, mut m: &FreeExprModel): str { - if env::RC { - ret self.expr(m.expr) + ".dealloc()" - } - ret self.expr(m.expr) + ".__free()" - } - - fn mut_slicing(mut self, mut m: &MutSlicingExprModel): str { - let mut obj = "(" - obj += self.model(m.expr) - obj += ").mut_slice(" - if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"," - } - obj += self.expr(m.left) - if m.right != nil { - obj += "," - obj += self.expr(m.right) - } - obj += ");" - ret obj - } - - fn str_insert_begin(mut self, mut m: &StrInsertBeginExprModel): str { - let mut obj = "(" - obj += self.model(m.dest) - obj += ").buffer.insert(0, (" - obj += self.model(m.expr) - obj += "));" - ret obj - } - - fn model(mut self, mut m: ExprModel): str { - match type m { - | &Data: - ret self.model((&Data)(m).model) - | &TypeKind: - ret TypeCoder.kind((&TypeKind)(m)) - | &Const: - ret self.constant((&Const)(m), false) - | &Var: - ret self.var((&Var)(m)) - | &Trait: - ret IdentCoder.trait_decl((&Trait)(m)) - | &Struct: - ret self.structure((&Struct)(m)) - | &StructIns: - ret self.structure_ins((&StructIns)(m)) - | &FnIns: - ret self.func_ins_common((&FnIns)(m)) - | &UnsafeBinopExprModel: - ret self.unsafe_binary((&UnsafeBinopExprModel)(m).node) - | &BinopExprModel: - ret self.binary((&BinopExprModel)(m)) - | &UnaryExprModel: - ret self.unary((&UnaryExprModel)(m)) - | &StructLitExprModel: - ret self.structure_lit((&StructLitExprModel)(m)) - | &AllocStructLitExprModel: - ret self.alloc_structure((&AllocStructLitExprModel)(m)) - | &CastingExprModel: - ret self.casting((&CastingExprModel)(m)) - | &FnCallExprModel: - ret self.func_call((&FnCallExprModel)(m)) - | &SliceExprModel: - ret self.slice((&SliceExprModel)(m)) - | &ArrayExprModel: - ret self.array((&ArrayExprModel)(m)) - | &UnsafeIndexingExprModel: - ret self.unsafe_indexing((&UnsafeIndexingExprModel)(m)) - | &IndexingExprModel: - ret self.indexing((&IndexingExprModel)(m)) - | &AnonFnExprModel: - ret self.anon_func((&AnonFnExprModel)(m)) - | &MapExprModel: - ret self.map((&MapExprModel)(m)) - | &SlicingExprModel: - ret self.slicing((&SlicingExprModel)(m)) - | &TraitSubIdentExprModel: - ret self.trait_sub((&TraitSubIdentExprModel)(m)) - | &StructSubIdentExprModel: - ret self.structure_sub((&StructSubIdentExprModel)(m)) - | &CommonIdentExprModel: - ret self.common_ident((&CommonIdentExprModel)(m)) - | &CommonSubIdentExprModel: - ret self.common_sub((&CommonSubIdentExprModel)(m)) - | &TupleExprModel: - ret self.tuple((&TupleExprModel)(m)) - | &BuiltinOutCallExprModel: - ret self.out_call((&BuiltinOutCallExprModel)(m)) - | &BuiltinOutlnCallExprModel: - ret self.outln_call((&BuiltinOutlnCallExprModel)(m)) - | &BuiltinNewCallExprModel: - ret self.new_call((&BuiltinNewCallExprModel)(m)) - | &BuiltinPanicCallExprModel: - ret self.panic_call((&BuiltinPanicCallExprModel)(m)) - | &BuiltinAssertCallExprModel: - ret self.assert_call((&BuiltinAssertCallExprModel)(m)) - | &BuiltinErrorCallExprModel: - ret self.error_call((&BuiltinErrorCallExprModel)(m)) - | &BuiltinMakeCallExprModel: - ret self.make_call((&BuiltinMakeCallExprModel)(m)) - | &BuiltinAppendCallExprModel: - ret self.append_call((&BuiltinAppendCallExprModel)(m)) - | &BuiltinCloneCallExprModel: - ret self.clone_call((&BuiltinCloneCallExprModel)(m)) - | &SizeofExprModel: - ret self.sizeof((&SizeofExprModel)(m)) - | &AlignofExprModel: - ret self.alignof((&AlignofExprModel)(m)) - | &RuneExprModel: - ret self.rune_lit((&RuneExprModel)(m)) - | &StructStaticIdentExprModel: - ret self.structure_static((&StructStaticIdentExprModel)(m)) - | &IntegratedToStrExprModel: - ret self.integrated_to_str((&IntegratedToStrExprModel)(m)) - | &BackendEmitExprModel: - ret self.backend_emit((&BackendEmitExprModel)(m)) - | &FreeExprModel: - ret self.free((&FreeExprModel)(m)) - | &MutSlicingExprModel: - ret self.mut_slicing((&MutSlicingExprModel)(m)) - | &StrInsertBeginExprModel: - ret self.str_insert_begin((&StrInsertBeginExprModel)(m)) - |: - ret "" - } - } - - fn expr(mut self, mut e: ExprModel): str { - let mut obj = self.model(e) - if obj.len == 0 || obj[0] != '(' { - ret obj - } - match type e { - | &BinopExprModel: - obj = obj[1:obj.len-1] - } - ret obj - } - - fn val(mut self, mut v: &Value): str { - if v.data.is_const() { - ret self.constant(v.data.constant, v.data.kind != nil && v.data.kind.prim().is_f32()) - } - ret self.expr(v.data.model) - } - - fn init_expr(mut self, mut t: &TypeKind): str { - if t.ptr() != nil { - ret "nullptr" - } - let mut enm = t.enm() - if enm != nil { - ret self.val(enm.items[0].value) - } - ret TypeCoder.kind(t) + "()" - } -} - -// Concatenate all strings into single string. -fn concat_all_parts(parts: ...&Token): str { - let mut s = "" - for _, p in parts { - s += p.kind - } - ret s -} - -fn decompose_common_esq(b: byte): str { - match b { - | '\\': - ret "\\\\" - | '\'': - ret "'" - | '"': - ret `\"` - | '\a': - ret `\a` - | '\b': - ret `\b` - | '\f': - ret `\f` - | '\n': - ret `\n` - | '\r': - ret `\r` - | '\t': - ret `\t` - | '\v': - ret `\v` - |: - ret "" - } -} - -fn sbtoa(b: byte): str { - if b == 0 { - ret "\\x00" - } - if b < utf8::RUNE_SELF { // ASCII, fast way. - let seq = decompose_common_esq(b) - if seq != "" { - ret seq - } - if 32 <= b && b <= 126 { - ret str(b) - } - } - let seq = conv::fmt_uint(u64(b), 8) - if seq.len == 2 { - ret "\\0" + seq - } - ret "\\" + seq -} - -fn cstr_bytes(bytes: []byte): str { - let mut lit = "" - for _, b in bytes { - lit += sbtoa(b) - } - ret lit -} - -fn cstr_lit(bytes: []byte): str { - ret `"` + cstr_bytes(bytes) + `"` -} - -fn ftoa(f: f64, bitsize: int): str { - if bitsize != 32 { - if f == f64(i64(f)) { - ret itoa(i64(f)) - } - if f == f64(u64(f)) { - ret utoa(u64(f)) - } - } - let mut m = conv::fmt_float(f, 'f', -1, bitsize) - if !strings::contains(m, ".") { - m += ".0" - } - ret m -} - -fn itoa(x: i64): str { - match { - | x == MAX_I64: - ret "jule::MAX_I64" - | x == MIN_I64: - ret "jule::MIN_I64" - } - - let fmt = conv::fmt_int(x, 10) - if is_64bit(ARCH) { - ret fmt + "LL" - } - ret fmt + "L" -} - -fn utoa(x: u64): str { - match { - | x == MAX_U64: - ret "jule::MAX_U64" - } - - let fmt = conv::fmt_uint(x, 10) - if is_64bit(ARCH) { - ret fmt + "LLU" - } - ret fmt + "LU" -} - -fn is_forwarded(&s: &Scope): bool { - let last = s.stmts[s.stmts.len-1] - match type last { - | &Data: - match type (&Data)(last).model { - | &BuiltinErrorCallExprModel: - ret true - |: - ret false - } - |: - ret true - } -} - -fn is_builtin_call_has_debuginf(&m: &FnCallExprModel): bool { - if !m.func.is_builtin() { - ret false - } - match type m.expr { - | &CommonSubIdentExprModel: - let csie = (&CommonSubIdentExprModel)(m.expr) - ret csie.ident == "swap" - |: - ret false - } -} \ No newline at end of file diff --git a/src/julec/obj/cxx/ident.jule b/src/julec/obj/cxx/ident.jule deleted file mode 100644 index 17f071f5b..000000000 --- a/src/julec/obj/cxx/ident.jule +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use env -use conv for std::conv -use std::jule::build::{ENTRY_POINT, Directive} -use std::jule::lex::{TokenKind, is_anon_ident, is_ignore_ident} -use std::jule::sema::{ - Fn, - FnIns, - Trait, - Struct, - StructIns, - Field, - Var, - Param, -} - -// Identifier of initialize function caller function. -const INIT_CALLER_IDENT = "__jule_call_initializers" - -struct IdentCoder {} - -impl IdentCoder { - const Self = "_self_" - - // Returns specified identifer as JuleC identifer. - // Equavalents: "JULEC_ID(" + ident + ")" of JuleC API. - static fn to_ident(ident: str): str { - ret "_" + ident - } - - // Returns cpp output identifier form of pointer address. - static fn addr(addr: uintptr): str { - ret "_" + conv::fmt_uint(u64(addr), 0xF) - } - - // Returns cpp output identifier form of given identifier. - // - // Parameters: - // - ident: Identifier. - // - addr: Pointer address of package file handler. - static fn to_out(ident: str, addr: uintptr): str { - if addr != 0 { - let mut obj = IdentCoder.addr(addr) - obj += "_" - obj += ident - ret obj - } - ret IdentCoder.to_ident(ident) - } - - // Returns cpp output local identifier form of fiven identifier. - // - // Parameters: - // - row: Row of definition. - // - col: Column of definition. - // - ident: Identifier of definition. - static fn to_local(row: int, col: int, ident: str): str { - let mut obj = conv::itoa(row) - obj += conv::itoa(col) - obj += "_" - obj += ident - ret IdentCoder.to_ident(obj) - } - - // Returns output identifier of function. - static fn func(&f: &Fn): str { - match { - | f.cpp_linked: - ret f.ident - | f.ident == ENTRY_POINT: - ret "entry_point" - | f.is_method(): - let mut obj = IdentCoder.to_out(f.ident, uintptr(f)) - if f.statically { - obj = "static_" + obj - ret obj - } - ret obj - |: - ret IdentCoder.to_out(f.ident, uintptr(f)) - } - } - - // Returns output identifier of function instance. - static fn func_ins(mut &f: &FnIns): str { - if f.is_builtin() { - ret "jule::" + f.decl.ident - } - if f.decl.cpp_linked || f.generics.len == 0 { - ret IdentCoder.func(f.decl) - } - for (i, mut ins) in f.decl.instances { - if ins.same(f) { - let mut obj = IdentCoder.func(f.decl) - obj += "_" - obj += conv::itoa(i) - ret obj - } - } - ret "__?__" - } - - // Returns output identifier of trait. - static fn trait_decl(t: &Trait): str { - if t.is_builtin() { - ret "jule::" + t.ident - } - ret IdentCoder.to_out(t.ident, uintptr(t)) - } - - // Returns output identifier of parameter. - static fn param(&p: &Param): str { - if is_anon_ident(p.ident) || is_ignore_ident(p.ident) { - ret "" - } - if p.is_self() { - ret IdentCoder.Self - } - if p.token == nil { - ret IdentCoder.to_local(0, 0, p.ident) - } - ret IdentCoder.to_local(p.token.row, p.token.column, p.ident) - } - - // Returns output identifier of structure. - static fn structure(&s: &Struct): str { - if s.cpp_linked { - if has_directive(s.directives, Directive.Typedef) { - ret s.ident - } - ret "struct " + s.ident - } - ret IdentCoder.to_out(s.ident, uintptr(s)) - } - - // Returns output identifier of structure instance. - static fn structure_ins(mut &s: &StructIns): str { - if s.decl.cpp_linked || s.generics.len == 0 { - ret IdentCoder.structure(s.decl) - } - for (i, mut ins) in s.decl.instances { - if ins.same(s) { - let mut obj = IdentCoder.structure(s.decl) - obj += "_" - obj += conv::itoa(i) - ret obj - } - } - ret "__?__" - } - - // Returns output identifier of field. - static fn field(&f: &Field): str { - if f.owner.cpp_linked { - ret f.ident - } - ret "_field_" + f.ident - } - - // Returns output identifier of variable. - static fn var(mut v: &Var): str { - match { - | v.cpp_linked: - ret v.ident - | v.ident == TokenKind.Error: - ret "except.error" - | v.ident == TokenKind.Self: - if v.kind.kind.sptr() == nil { - ret "(*" + IdentCoder.Self + ")" - } - ret IdentCoder.Self - | v.scope != nil: - ret IdentCoder.to_local(v.token.row, v.token.column, v.ident) - |: - ret IdentCoder.to_out(v.ident, uintptr(v)) - } - } - - // Returns begin label identifier of iteration. - static fn iter_begin(it: uintptr): str { - ret "_iter_begin_" + conv::fmt_uint(u64(it), 0xF) - } - - // Returns end label identifier of iteration. - static fn iter_end(it: uintptr): str { - ret "_iter_end_" + conv::fmt_uint(u64(it), 0xF) - } - - // Returns next label identifier of iteration. - static fn iter_next(it: uintptr): str { - ret "_iter_next_" + conv::fmt_uint(u64(it), 0xF) - } - - // Returns label identifier. - static fn label(ident: str): str { - ret "_julec_label_" + ident - } - - // Returns end label identifier of match-case. - static fn match_end(m: uintptr): str { - ret "_match_end_" + conv::fmt_uint(u64(m), 0xF) - } - - // Returns begin label identifier of case. - static fn case_begin(c: uintptr): str { - ret "_case_begin_" + conv::fmt_uint(u64(c), 0xF) - } -} \ No newline at end of file diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule deleted file mode 100644 index ee978f816..000000000 --- a/src/julec/obj/cxx/object.jule +++ /dev/null @@ -1,1205 +0,0 @@ -// Copyright 2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use env -use obj::{IR} -use conv for std::conv -use std::jule::{VERSION} -use std::jule::build::{ - Directive, - Derive, - INIT_FN, - PATH_API, - PATH_STDLIB, - is_std_header_path, - is_valid_header_ext, -} -use std::jule::lex::{ - Token, - TokenId, - is_ignore_ident, - is_anon_ident, -} -use std::jule::sema::{ - FuncPattern, - Package, - SymbolTable, - Param, - ParamIns, - Trait, - Struct, - FieldIns, - Var, - StructIns, - Fn, - FnIns, - TypeKind, - Prim, - Sptr, - TypeSymbol, -} -use path for std::fs::path -use strings for std::strings -use std::time::{Time} - -pub struct SerializationInfo { - pub compiler: str - pub compiler_command: str -} - -struct TraitHash { - t: &Trait - s: &StructIns - i: int -} - -pub struct ObjectCoder { - ir: &IR - info: SerializationInfo - - // Current indention. - indent_buffer: str - - trait_declarations: str - trait_wrappers: str - trait_data: str - trait_data_t: str - trait_map: []&TraitHash - - ec: &ExprCoder - sc: &ScopeCoder -} - -impl ObjectCoder { - pub static fn new(mut &ir: &IR, info: SerializationInfo): &ObjectCoder { - let mut oc = &ObjectCoder{ - ir: ir, - info: info, - } - oc.ec = ExprCoder.new(oc) - oc.sc = ScopeCoder.new(oc) - ret oc - } - - // Increase indentation. - fn add_indent(mut self) { - const INDENT_KIND = "\t" - self.indent_buffer += INDENT_KIND - } - - // Decrase indentation. - fn done_indent(mut self) { - self.indent_buffer = self.indent_buffer[:self.indent_buffer.len-1] - } - - // Returns indention string by indent_buffer. - fn indent(self): str { - ret self.indent_buffer - } - - fn find_type_offset(self, t: &Trait, mut k: &TypeKind): int { - let mut s: &StructIns = nil - if k.sptr() != nil { - k = k.sptr().elem - } - if k.strct() == nil { - ret -1 - } - s = k.strct() - for _, hash in self.trait_map { - if hash.t == t && hash.s == s { - ret hash.i - } - } - ret -1 - } - - // Returns location information of token as cstr bytes. - fn loc_info(self, &t: &Token): str { - let mut loc = t.file.path - - // Normalize path if production compilation enabled. - if env::PRODUCTION { - match { - | strings::has_prefix(loc, PATH_STDLIB): - // Remove absolute path prefix of standard library. - // Just keeps "std/" prefix. - loc = loc[path::dir(PATH_STDLIB).len+1:] - | strings::has_prefix(loc, self.ir.root): - // Remove absolute path prefix of root package. - // Just keeps "[package_dir]/" prefix. - loc = loc[path::dir(self.ir.root).len+1:] - } - } - loc += ":" - loc += conv::itoa(t.row) - loc += ":" - loc += conv::itoa(t.column) - ret cstr_bytes([]byte(loc)) - } - - // Generates all C/C++ include directives. - fn links(mut self): str { - let mut obj = "" - for (_, mut pkg) in self.ir.used { - match { - | !pkg.cpp_linked: - continue - | is_std_header_path(pkg.path): - obj += "#include " - obj += pkg.path - obj += "\n" - } - } - - for (_, mut pkg) in self.ir.used { - match { - | !pkg.cpp_linked: - continue - | is_cpp_header_file(pkg.path): - obj += `#include "` - obj += pkg.path - obj += "\"\n" - } - } - ret obj - } - - // Generates C++ code of parameter instance. - fn param_ins(self, mut &p: &ParamIns): str { - let mut obj = TypeCoder.param_ins(p) - obj += " " - obj += IdentCoder.param(p.decl) - ret obj - } - - // Generates C++ code of parameter. - fn param(mut self, mut &p: &Param): str { - let mut obj = TypeCoder.param(p) - if p.ident != "" && !is_ignore_ident(p.ident) && !is_anon_ident(p.ident) { - obj += " " - obj += IdentCoder.param(p) - } - ret obj - } - - // Generates C++ code of parameters. - fn params(mut self, mut ¶ms: []&Param): str { - if params.len == 0 { - ret "(void)" - } - let mut obj = "(" - for (_, mut p) in params { - if p.is_self() { - if p.is_ref() { - obj += self.param(p) - } - } else { - obj += self.param(p) - } - obj += "," - } - - // Remove comma. - obj = obj[:obj.len-1] - ret obj + ")" - } - - fn params_ins(mut self, mut ¶ms: []&ParamIns): str { - match { - | params.len == 0: - ret "(void)" - } - - let mut obj = "(" - for (_, mut p) in params { - obj += self.param_ins(p) - obj += "," - } - - // Remove comma. - obj = obj[:obj.len-1] - ret obj + ")" - } - - // Generates C++ declaration code of parameters. - fn params_decls(mut self, mut ¶ms: []&ParamIns): str { - if params.len == 0 { - ret "(void)" - } - - let mut obj = "(" - for (_, mut p) in params { - obj += TypeCoder.param_ins(p) - obj += "," - } - - // Remove comma. - obj = obj[:obj.len-1] - ret obj + ")" - } - - fn prepare_structure(mut self, mut &s: &Struct) { - for (_, mut ins) in s.instances { - for (_, mut m) in ins.methods { - if m.statically { - continue - } - for (_, mut ins) in m.instances { - let mut p = ins.params[0] - if !p.decl.is_ref() { - p.kind = &TypeKind{ - kind: &CustomType{ - kind: TypeCoder.as_ptr(TypeCoder.kind(p.kind)), - }, - } - } else { - p.kind = &TypeKind{ - kind: &CustomType{ - kind: TypeCoder.kind(p.kind), - }, - } - } - } - } - } - } - - fn prepare_structures(mut self) { - for (_, mut s) in self.ir.ordered.structs { - if !s.cpp_linked && s.token != nil { - self.prepare_structure(s) - } - } - } - - fn build_trait_wrapper(mut self, mut &hash: &TraitHash) { - for (_, mut m) in hash.t.methods { - let ident = m.ident - m.instances[0].scope = nil - let ptr = !m.params[0].is_ref() - - let mut sm = hash.s.find_method(m.ident, false) - if sm == nil || sm.instances.len == 0 { - continue - } - - m.ident = ident + "_" + conv::itoa(hash.i) - self.trait_wrappers += self.func(m) - m.ident = ident - self.add_indent() - self.trait_wrappers += "{\n" - self.trait_wrappers += self.indent() - if !sm.is_void() { - self.trait_wrappers += "return " - } - self.trait_wrappers += IdentCoder.func(sm) - self.trait_wrappers += "(" - if ptr { - self.trait_wrappers += "_self_.safe_ptr<" - self.trait_wrappers += TypeCoder.structure_ins(hash.s) - self.trait_wrappers += ">(" - if !env::PRODUCTION { - self.trait_wrappers += "_00___file" - } - self.trait_wrappers += ")" - } else { - self.trait_wrappers += "_self_.data.as<" - self.trait_wrappers += TypeCoder.structure(sm.owner) - self.trait_wrappers += ">()" - } - for _, mp in m.params[1:] { - self.trait_wrappers += ", " - self.trait_wrappers += IdentCoder.param(mp) - } - self.trait_wrappers += ");\n}\n" - self.done_indent() - } - } - - fn trait_decl(mut self, mut &t: &Trait) { - let ident = IdentCoder.trait_decl(t) - - let type_data = ident + "MptrData" - self.trait_data_t += "struct " - self.trait_data_t += type_data - self.trait_data_t += " {\n" - - for (_, mut m) in t.methods { - let mut ins = m.instances[0] - let mut p = ins.params[0] - p.kind = &TypeKind{ - kind: t, - } - for (i, mut ip) in ins.params[1:] { - if is_anon_ident(ip.decl.ident) { - ip.decl.ident = "_" + conv::itoa(i) - } - } - if !env::PRODUCTION { - ins.params = append(ins.params, &ParamIns{ - decl: &Param{ - ident: "__file", - }, - kind: &TypeKind{ - kind: &CustomType{ - kind: "const char*", - }, - }, - }) - } - - self.add_indent() - self.trait_data_t += self.func_decl(m, true) - self.done_indent() - } - self.trait_data_t += self.indent() - self.trait_data_t += "};" - self.trait_data_t += "\n\n" - - let n = self.trait_map.len - let mut i = 0 - for (_, mut s) in t.implemented { - for (_, mut ins) in s.instances { - let mut hash = &TraitHash{ - t: t, - s: ins, - i: i, - } - i++ - self.build_trait_wrapper(hash) - self.trait_map = append(self.trait_map, hash) - } - } - self.trait_declarations += "struct " - self.trait_declarations += ident - self.trait_declarations += " {};\n" - - self.add_indent() - - self.trait_data += "static " - self.trait_data += type_data - self.trait_data += " " - self.trait_data += ident - self.trait_data += "_mptr_data[] = {\n" - - for (_, mut hash) in self.trait_map[n:] { - self.trait_data += self.indent() - self.trait_data += "{\n" - self.add_indent() - for (_, mut m) in hash.t.methods { - let m_ident = IdentCoder.func(m) - self.trait_data += self.indent() - self.trait_data += "." - self.trait_data += m_ident - self.trait_data += "=" - self.trait_data += m_ident - self.trait_data += "_" - self.trait_data += conv::itoa(hash.i) - self.trait_data += ",\n" - } - self.done_indent() - self.trait_data += self.indent() - self.trait_data += "},\n" - } - - self.done_indent() - self.trait_data += self.indent() - self.trait_data += "};" - } - - fn trait_decls(mut self, mut &p: &Package) { - for (_, mut f) in p.files { - for (_, mut t) in f.traits { - if t.token != nil { - self.trait_decl(t) - } - } - } - } - - // Generates C++ plain-prototype code of structure. - fn structure_plain_decl(mut self, mut &s: &Struct): str { - let mut obj = "" - for (_, mut ins) in s.instances { - obj += "\nstruct " - obj += IdentCoder.structure_ins(ins) - obj += ";\n" - } - ret obj - } - - // Generates C++ plain-prototype code of all structures. - fn structure_plain_decls(mut self): str { - let mut obj = "" - for (_, mut s) in self.ir.ordered.structs { - if !s.cpp_linked && s.token != nil { - obj += self.structure_plain_decl(s) - obj += "\n" - } - } - ret obj - } - - // Generats C++ code of variable with initialize expression. - fn var_init_expr(mut self, mut &v: &Var, init: str): str { - let mut obj = "" - if v.statically { - obj += "static " - } - - obj += TypeCoder.kind(v.kind.kind) - obj += " " - if v.reference { - obj += "&" - } - obj += IdentCoder.var(v) - if init != "" { - obj += " = " - obj += init - } - obj += ";" - ret obj - } - - // Generates C++ code of variable. - fn var(mut self, mut v: &Var): str { - if is_ignore_ident(v.ident) { - ret "" - } - if v.value != nil && v.value.expr != nil { - if v.value.data.model != nil { - ret self.var_init_expr(v, self.ec.val(v.value)) - } - ret self.var_init_expr(v, "") - } - ret self.var_init_expr(v, self.ec.init_expr(v.kind.kind)) - } - - // Generates C++ declaration code of field. - fn field_decl(mut self, mut &f: &FieldIns): str { - let mut obj = TypeCoder.kind(f.kind) - obj += " " - obj += IdentCoder.field(f.decl) - obj += " = " - if f.default == nil { - // No default expression. - // Use default expression of data-type. - obj += self.ec.init_expr(f.kind) - } else { - obj += self.ec.expr(f.default.model) - } - obj += ";" - ret obj - } - - fn structure_constructor(mut self, mut &s: &StructIns): str { - let mut obj = IdentCoder.structure_ins(s) - - obj += "(" - if s.fields.len > 0 { - for (_, mut f) in s.fields { - obj += TypeCoder.kind(f.kind) - obj += " __param_" - obj += f.decl.ident - obj += ", " - } - obj = obj[:obj.len-2] // Remove last comma. - } else { - obj += "void" - } - - obj += ")" - if s.fields.len > 0 { - obj += ": " - for _, f in s.fields { - obj += IdentCoder.field(f.decl) - obj += "(" - obj += "__param_" - obj += f.decl.ident - obj += "), " - } - obj = obj[:obj.len-2] // Remove trailing comma. - } - - obj += " {}" - ret obj - } - - fn structure_destructor(mut self, mut &s: &StructIns): str { - const STATIC = false // Dispose method must be non-static - let dispose_method = s.find_method("dispose", STATIC) - let mut disposed = FuncPattern.dispose(dispose_method) - // Call destructor if implemented. - if !disposed { - ret "" - } - let mut obj = "~" - obj += IdentCoder.structure_ins(s) - obj += "(void) { " - obj += IdentCoder.func(dispose_method) - obj += "(this); }" - ret obj - } - - fn structure_operator_eq(mut self, mut &obj: str, &ident: str, mut &s: &StructIns) { - // Operator overloading. - if s.operators.eq != nil { - self.structure_operator(obj, ident, s.operators.eq, "==") - ret - } - - obj += self.indent() - if env::OPT_INLINE { - obj += "inline " - } - obj += "bool operator==(" - obj += ident - obj += " _other) {" - if s.fields.len > 0 { - self.add_indent() - obj += "\n" - obj += self.indent() - obj += "return " - self.add_indent() - let mut n = 0 - for (_, mut f) in s.fields { - // Skip C++-linked struct kinds. - let strct = f.kind.strct() - if strct != nil && strct.decl != nil && strct.decl.cpp_linked { - continue - } - - n++ - obj += "\n" - obj += self.indent() - obj += "this->" - let f_ident = IdentCoder.field(f.decl) - obj += f_ident - obj += " == _other." - obj += f_ident - obj += " &&" - } - self.done_indent() - if n > 0 { - obj = obj[:obj.len-3] // Remove last suffix " &&" - } else { - obj += "true" - } - obj += ";\n" - self.done_indent() - obj += self.indent() - obj += "}" - } else { - obj += " return true; }" - } - obj += "\n\n" - } - - fn structure_operator_not_eq(mut self, mut &obj: str, &ident: str, mut &s: &StructIns) { - obj += self.indent() - if env::OPT_INLINE { - obj += "inline " - } - obj += "bool operator!=(" - obj += ident - obj += " _other) { return !this->operator==(_other); }\n\n" - } - - // Write operator overloading forwarding for reserved function. - fn structure_operator(mut self, mut &obj: str, &ident: str, mut &f: &FnIns, op: str) { - if f == nil { - ret - } - - let unary = f.params.len == 1 // Just self parameter. - let assignment = f.decl.is_void() - - obj += self.indent() - if env::OPT_INLINE { - obj += "inline " - } - if assignment { - obj += ident - obj += "&" - } else { - if f.result.prim() == nil { - // If result type is not primitive, always structure's itself. - obj += ident - } else { - // Logical. - obj += TypeCoder.Bool - } - } - obj += " operator" - obj += op - obj += "(" - if !unary { - let mut p = f.params[1] - obj += TypeCoder.param_ins(p) - obj += " _other" - } - obj += ") { " - if !assignment { - obj += "return " - } - obj += IdentCoder.func_ins(f) - if !unary { - obj += "(this, _other); " - if assignment { - obj += "return *this; " - } - obj += "}" - } else { - obj += "(this); }" - } - obj += "\n\n" - } - - fn structure_operators(mut self, mut &s: &StructIns): str { - let ident = IdentCoder.structure_ins(s) - let mut obj = "" - - // Binary. - self.structure_operator_eq(obj, ident, s) - self.structure_operator_not_eq(obj, ident, s) - self.structure_operator(obj, ident, s.operators.gt, ">") - self.structure_operator(obj, ident, s.operators.gt_eq, ">=") - self.structure_operator(obj, ident, s.operators.lt, "<") - self.structure_operator(obj, ident, s.operators.lt_eq, "<=") - self.structure_operator(obj, ident, s.operators.shl, "<<") - self.structure_operator(obj, ident, s.operators.shr, ">>") - self.structure_operator(obj, ident, s.operators.add, "+") - self.structure_operator(obj, ident, s.operators.sub, "-") - self.structure_operator(obj, ident, s.operators.div, "/") - self.structure_operator(obj, ident, s.operators.mul, "*") - self.structure_operator(obj, ident, s.operators.mod, "%") - self.structure_operator(obj, ident, s.operators.bit_and, "&") - self.structure_operator(obj, ident, s.operators.bit_or, "|") - self.structure_operator(obj, ident, s.operators.bit_xor, "^") - - // Unary. - self.structure_operator(obj, ident, s.operators.neg, "-") - self.structure_operator(obj, ident, s.operators.pos, "+") - self.structure_operator(obj, ident, s.operators.bit_not, "~") - - // Assignment. - self.structure_operator(obj, ident, s.operators.add_assign, "+=") - self.structure_operator(obj, ident, s.operators.sub_assign, "-=") - self.structure_operator(obj, ident, s.operators.div_assign, "/=") - self.structure_operator(obj, ident, s.operators.mul_assign, "*=") - self.structure_operator(obj, ident, s.operators.mod_assign, "%=") - self.structure_operator(obj, ident, s.operators.shl_assign, "<<=") - self.structure_operator(obj, ident, s.operators.shr_assign, ">>=") - self.structure_operator(obj, ident, s.operators.bit_or_assign, "|=") - self.structure_operator(obj, ident, s.operators.bit_and_assign, "&=") - self.structure_operator(obj, ident, s.operators.bit_xor_assign, "^=") - ret obj - } - - fn structure_derive_defs_decls(mut self, &s: &StructIns): str { - let mut obj = "" - if s.decl.is_derives(Derive.Clone) { - obj += self.indent() - obj += DeriveCoder.clone_func_decl(s.decl) - obj += ";\n\n" - } - ret obj - } - - fn structure_ins_decl(mut self, mut &s: &StructIns): str { - let mut obj = "" - - if s.methods.len > 0 { - for (_, mut m) in s.methods { - obj += self.func_decl(m, false) - } - } - - obj += "struct " - let out_ident = IdentCoder.structure_ins(s) - - obj += out_ident - obj += " {\n" - - self.add_indent() - if s.fields.len > 0 { - for (_, mut f) in s.fields { - obj += self.indent() - obj += self.field_decl(f) - obj += "\n" - } - obj += "\n\n" - obj += self.indent() - obj += self.structure_constructor(s) - obj += "\n\n" - } - - obj += self.indent() - obj += self.structure_destructor(s) - obj += "\n\n" - - // Default constructor. - obj += self.indent() - obj += out_ident - obj += "(void) = default;\n\n" - - obj += self.structure_derive_defs_decls(s) - - obj += self.structure_operators(s) - obj += "\n" - - self.done_indent() - obj += self.indent() + "};" - - ret obj - } - - // Generates C++ declaration code of structure. - fn structure_decl(mut self, mut &s: &Struct): str { - let mut obj = "" - for (_, mut ins) in s.instances { - obj += self.structure_ins_decl(ins) - } - ret obj - } - - // Generates C++ declaration code of all structures. - fn structure_decls(mut self): str { - let mut obj = "" - for (_, mut s) in self.ir.ordered.structs { - if !s.cpp_linked && s.token != nil { - obj += self.structure_decl(s) - obj += "\n" - } - } - ret obj - } - - fn func_head(mut self, mut &f: &FnIns, ptr: bool): str { - let mut obj = "" - if !ptr && env::OPT_INLINE && !f.decl.is_entry_point() { - obj += "inline " - } - obj += TypeCoder.func_ins_result(f) - if ptr { - obj += "(*" - obj += IdentCoder.func_ins(f) - obj += ")" - } else { - obj += " " - obj += IdentCoder.func_ins(f) - } - ret obj - } - - // Generates C++ declaration code of function's combinations. - fn func_decl(mut self, mut &f: &Fn, ptr: bool): str { - let mut obj = "" - for (_, mut c) in f.instances { - obj += self.indent() - obj += self.func_head(c, ptr) - obj += self.params_decls(c.params) - obj += ";\n" - } - ret obj - } - - // Generates C++ declaration code of all functions. - fn func_decls(mut self, mut &pkg: &Package): str { - let mut obj = "" - for (_, mut file) in pkg.files { - for (_, mut f) in file.funcs { - if !f.cpp_linked && f.token != nil { - obj += self.func_decl(f, false) - } - } - } - ret obj - } - - fn build_trait_map(mut self) { - for (_, mut u) in self.ir.used { - if !u.cpp_linked { - self.trait_decls(u.package) - } - } - self.trait_decls(self.ir.main) - } - - fn process_traits(mut self) { - self.build_trait_map() - } - - // Generates C++ code of all can-be-prototyped declarations. - fn decls(mut self): str { - let mut obj = "" - - obj += self.trait_declarations - obj += self.structure_plain_decls() - - obj += self.structure_decls() - - for (_, mut u) in self.ir.used { - if !u.cpp_linked { - obj += self.func_decls(u.package) - } - } - obj += self.func_decls(self.ir.main) - - if self.trait_map.len > 0 { - obj += "\n\n" - obj += self.trait_data_t - obj += "\n\n" - obj += self.trait_wrappers - obj += "\n\n" - obj += self.trait_data - } - - ret obj - } - - fn pkg_globals(mut self, mut &p: &Package, mut &global_initializers: str): str { - let mut obj = "" - for (_, mut f) in p.files { - for (_, mut v) in f.vars { - if v.token != nil && !v.cpp_linked && !v.constant { - obj += TypeCoder.kind(v.kind.kind) - obj += " " - if v.reference { - obj += "&" - } - obj += IdentCoder.var(v) - obj += ";\n" - - global_initializers += self.indent() // Indentation for initializer scope. - global_initializers += IdentCoder.var(v) - if v.value != nil && v.value.expr != nil { - if v.value.data.model != nil { - global_initializers += " = " - global_initializers += self.ec.val(v.value) - } - } else { - global_initializers += " = " - global_initializers += self.ec.init_expr(v.kind.kind) - } - global_initializers += ";\n" - } - } - } - ret obj - } - - // Generates C++ code of all globals. - fn globals(mut self, mut &global_initializers: str): str { - let mut obj = "" - self.add_indent() // For global initializers's function indentation. - for (_, mut u) in self.ir.used { - if !u.cpp_linked { - obj += self.pkg_globals(u.package, global_initializers) - } - } - obj += self.pkg_globals(self.ir.main, global_initializers) - self.done_indent() - ret obj - } - - // Generates C++ code of function. - fn func(mut self, mut &f: &Fn): str { - let mut obj = "" - for (_, mut ins) in f.instances { - obj += self.func_head(ins, false) - obj += self.params_ins(ins.params) - obj += " " - obj += self.sc.func_scope(ins) - if ins.scope != nil { - obj += "\n\n" - } - } - ret obj - } - - // Generates C++ code of all functions of package. - fn pkg_funcs(mut self, mut &p: &Package): str { - let mut obj = "" - for (_, mut f) in p.files { - for (_, mut f) in f.funcs { - if !env::TEST && has_directive(f.directives, Directive.Test) { - continue - } - if !f.cpp_linked && f.token != nil { - obj += self.func(f) - obj += "\n\n" - } - } - } - ret obj - } - - // Generates C++ code of structure's methods. - fn structure_methods(mut self, mut &s: &StructIns): str { - let mut obj = "" - for (_, mut f) in s.methods { - obj += self.indent() - obj += self.func(f) - obj += "\n\n" - } - ret obj - } - - // Generates C++ code of structure's ostream. - fn structure_ostream(mut self, mut &s: &StructIns): str { - let mut obj = "" - obj += self.indent() - obj += "std::ostream &operator<<(std::ostream &_Stream, " - obj += IdentCoder.structure_ins(s) - obj += " _Src) {\n" - self.add_indent() - obj += self.indent() - - let mut fts = s.find_method("to_str", false) - if FuncPattern.to_str(fts) { - obj += "_Stream << " - obj += IdentCoder.func(fts) - obj += "(&_Src);\n" - } else { - obj += `_Stream << "` - obj += s.decl.ident - obj += "{\";\n" - - for (i, mut f) in s.fields { - obj += self.indent() - obj += `_Stream << "` - obj += f.decl.ident - obj += `:` - - // Skip C++-linked struct kinds. - let strct = f.kind.strct() - if strct != nil && strct.decl != nil && strct.decl.cpp_linked { - obj += ` cpp.` - obj += IdentCoder.field(f.decl) - obj += `"` - } else { - obj += `" << _Src.` - obj += IdentCoder.field(f.decl) - } - if i+1 < s.fields.len { - obj += " << \", \"" - } - obj += ";\n" - } - - obj += self.indent() - obj += "_Stream << \"}\";\n" - } - - obj += self.indent() - obj += "return _Stream;\n" - - self.done_indent() - obj += self.indent() - obj += "}" - ret obj - } - - fn structure_derive_defs(mut self, mut &s: &StructIns): str { - let mut obj = "" - if s.decl.is_derives(Derive.Clone) { - obj += self.indent() - obj += DeriveCoder.clone_func_def(s.decl) - obj += "{\n" - self.add_indent() - obj += self.indent() - obj += TypeCoder.structure_ins(s) - obj += " clone;\n" - for _, f in s.fields { - let ident = IdentCoder.field(f.decl) - obj += self.indent() - obj += "clone." - obj += ident - obj += " = jule::clone(this->" - obj += ident - obj += ");\n" - } - obj += self.indent() - obj += "return clone;\n" - self.done_indent() - obj += self.indent() - obj += "}" - } - ret obj - } - - // Generates C++ code of structure instance definition. - fn structure_ins(mut self, mut &s: &StructIns): str { - let mut obj = self.structure_methods(s) - obj += "\n\n" - obj += self.structure_derive_defs(s) - obj += "\n\n" - obj += self.structure_ostream(s) - ret obj - } - - // Generates C++ code of structure definition. - fn structure(mut self, mut &s: &Struct): str { - let mut obj = "" - for (_, mut ins) in s.instances { - obj += self.structure_ins(ins) - obj += "\n\n" - } - ret obj - } - - // Generates C++ code of all structures. - fn structures(mut self): str { - let mut obj = "" - for (_, mut s) in self.ir.ordered.structs { - if !s.cpp_linked && s.token != nil { - obj += self.structure(s) - obj += "\n\n" - } - } - ret obj - } - - // Generates C++ code of all functions. - fn funcs(mut self): str { - let mut obj = "" - for (_, mut u) in self.ir.used { - if !u.cpp_linked { - obj += self.pkg_funcs(u.package) - } - } - obj += self.pkg_funcs(self.ir.main) - ret obj - } - - fn push_init(self, mut &pkg: &Package, mut &obj: str) { - const INDENTION = "\t" - for _, file in pkg.files { - for _, f in file.funcs { - if f.ident == INIT_FN { - obj += "\n" + INDENTION - obj += IdentCoder.func(f) - obj += "();" - } - } - } - } - - // Generated C++ code of all initializer functions. - fn init_caller(mut self, &global_initializers: str): str { - let mut obj = "void " - obj += INIT_CALLER_IDENT - obj += "(void) {\n" - obj += global_initializers - - for (_, mut u) in self.ir.used { - if !u.cpp_linked { - self.push_init(u.package, obj) - } - } - self.push_init(self.ir.main, obj) - - obj += "\n}" - ret obj - } - - // Appends standard codes to object code. - // Usually includes top comments and entry point of program. - pub fn append_standard(self, mut &obj_code: str) { - let time = Time.now() - let abs = time.abs() - - let mut time_str = "" - time_str += conv::fmt_uint(abs.day, 10) - time_str += "/" - time_str += conv::fmt_uint(abs.month, 10) - time_str += "/" - time_str += conv::fmt_uint(abs.year, 10) - time_str += " " - time_str += conv::fmt_uint(abs.hour, 10) - time_str += "." - time_str += conv::fmt_uint(abs.minute, 10) - time_str += " (DD/MM/YYYY) (HH.MM) UTC" - - let mut s = "" - s += "// Auto generated by JuleC.\n" - s += "// JuleC version: " - s += VERSION - s += "\n" - s += "// Date: " - s += time_str - s += "\n//\n// Recommended Compile Command;\n// " - s += self.info.compiler - s += " " - s += self.info.compiler_command - s += "\n\n" - - if env::PRODUCTION { - s += "#define __JULE_ENABLE__PRODUCTION\n" - } - if !env::RC { - s += "#define __JULE_DISABLE__REFERENCE_COUNTING\n" - } - if !env::SAFETY { - s += "#define __JULE_DISABLE__SAFETY\n" - } - - s += "\n\n#include \"" - s += PATH_API - s += "\"\n\n" - s += obj_code - s += ` -int main(int argc, char *argv[], char *envp[]) { - jule::setup_argv(argc, argv); - jule::setup_envp(envp); - - __jule_call_initializers(); - ` - - if env::TEST { - s += "test_point();" - } else { - s += "entry_point();" - } - - s += ` - - return EXIT_SUCCESS; -}` - - obj_code = s - } - - // Serializes IR to C++. - // Returns fully implemented IR in C++. - // Except standard content, to add standard content, use [ObjectCoder.append_standard]. - pub fn serialize(mut self): str { - self.prepare_structures() - self.process_traits() - let mut global_initializers = "" - let mut obj = "" - obj += self.links() - obj += "\n" - obj += self.decls() - obj += "\n\n" - obj += self.globals(global_initializers) - obj += "\n" - obj += self.structures() - obj += self.funcs() - obj += "\n" - obj += self.init_caller(global_initializers) - obj += "\n" - ret obj - } -} - -fn is_cpp_header_file(path: str): bool { - let offset = strings::find_last_byte(path, '.') - if offset == -1 { - ret false - } - ret is_valid_header_ext(path[offset:]) -} \ No newline at end of file diff --git a/src/julec/obj/cxx/scope.jule b/src/julec/obj/cxx/scope.jule deleted file mode 100644 index 3d471b02a..000000000 --- a/src/julec/obj/cxx/scope.jule +++ /dev/null @@ -1,791 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use env -use optimizing::{ - PushToSliceExprModel, - MutSlicingExprModel, - StrInsertBeginExprModel, -} -use lex for std::jule::lex::{TokenKind} -use std::jule::sema::{ - Data, - St, - FnIns, - Var, - Scope, - If, - Conditional, - InfIter, - WhileIter, - RangeIter, - ContSt, - BreakSt, - Label, - GotoSt, - Postfix, - Assign, - MultiAssign, - Match, - Case, - FallSt, - RetSt, - TupleExprModel, - TypeKind, - BuiltinAppendCallExprModel, - SlicingExprModel, -} - -const MATCH_EXPR = "_match_expr" - -struct ScopeCoder { - oc: &ObjectCoder -} - -impl ScopeCoder { - static fn new(mut &oc: &ObjectCoder): &ScopeCoder { - ret &ScopeCoder{ - oc: oc, - } - } - - fn range_index_iter(mut self, mut &it: &RangeIter): str { - let begin = IdentCoder.iter_begin(uintptr(it)) - let next = IdentCoder.iter_next(uintptr(it)) - - let mut obj = "{\n" - self.oc.add_indent() - obj += self.oc.indent() - obj += "auto " - if env::OPT_COPY && is_copy_optimizable(it.expr) { - obj += "&" - } - obj += "expr = " - obj += self.oc.ec.model(it.expr.model) - obj += ";\n" - obj += self.oc.indent() - obj += "auto it = expr.begin();\n" - obj += self.oc.indent() - obj += begin - obj += ":;\n" - obj += self.oc.indent() - obj += "if (it != expr.end()) {\n" - self.oc.add_indent() - obj += self.oc.indent() - if it.key_a != nil { - obj += self.oc.var_init_expr(it.key_a, "it - expr.begin()") - obj += "\n" - obj += self.oc.indent() - } - if it.key_b != nil { - if env::OPT_COPY { - it.key_b.reference = is_iter_copy_optimizable(it.expr, it.key_b) - } - obj += self.oc.var_init_expr(it.key_b, "*it") - obj += "\n" - obj += self.oc.indent() - } - obj += self.scope(it.scope) - obj += "\n" - obj += self.oc.indent() - obj += next - obj += ":;\n" - obj += self.oc.indent() - obj += "++it;\n" - obj += self.oc.indent() - if it.key_a != nil { - obj += IdentCoder.var(it.key_a) - obj += "++;\n" - obj += self.oc.indent() - } - obj += "goto " - obj += begin - obj += ";\n" - - // Close if. - self.oc.done_indent() - obj += self.oc.indent() - obj += "}\n" - - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;\n" - - // Close scope. - self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - ret obj - } - - fn range_hashmap_iter(mut self, mut &it: &RangeIter): str { - let begin = IdentCoder.iter_begin(uintptr(it)) - let next = IdentCoder.iter_next(uintptr(it)) - - let mut obj = "{\n" - self.oc.add_indent() - obj += self.oc.indent() - obj += "auto " - if env::OPT_COPY && is_copy_optimizable(it.expr) { - obj += "&" - } - obj += "expr = " - obj += self.oc.ec.model(it.expr.model) - obj += ";\n" - obj += self.oc.indent() - obj += "auto it = expr.begin();\n" - obj += self.oc.indent() - obj += begin - obj += ":;\n" - obj += self.oc.indent() - obj += "if (it != expr.end()) {\n" - self.oc.add_indent() - obj += self.oc.indent() - if it.key_a != nil { - if env::OPT_COPY { - it.key_a.reference = is_iter_copy_optimizable(it.expr, it.key_a) - } - obj += self.oc.var_init_expr(it.key_a, "it->first") - obj += "\n" - obj += self.oc.indent() - } - if it.key_b != nil { - if env::OPT_COPY { - it.key_b.reference = is_iter_copy_optimizable(it.expr, it.key_b) - } - obj += self.oc.var_init_expr(it.key_b, "it->second") - obj += "\n" - obj += self.oc.indent() - } - obj += self.scope(it.scope) - obj += "\n" - obj += self.oc.indent() - obj += next - obj += ":;\n" - obj += self.oc.indent() - obj += "++it;\n" - obj += self.oc.indent() - obj += "goto " - obj += begin - obj += ";\n" - - // Close if. - self.oc.done_indent() - obj += self.oc.indent() - obj += "}\n" - - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;\n" - - // Close scope. - self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - ret obj - } - - fn if_case(mut self, mut i: &If): str { - let mut obj = "" - if i.expr != nil { - obj += "if (" - obj += self.oc.ec.expr(i.expr) - obj += ") " - } - obj += self.scope(i.scope) - ret obj - } - - fn conditional(mut self, mut c: &Conditional): str { - let mut obj = "" - for (_, mut elif) in c.elifs { - if elif == nil { - continue - } - if obj.len != 0 { - obj += " else " - } - obj += self.if_case(elif) - } - if c.default != nil { - if obj.len != 0 { - obj += " else " - } - obj += self.scope(c.default.scope) - } - ret obj - } - - fn inf_iter(mut self, mut it: &InfIter): str { - let mut obj = "for (;;) {\n" - - self.oc.add_indent() // Indent scope. - obj += self.oc.indent() - obj += self.scope(it.scope) - self.oc.done_indent() - - obj += "\n" - obj += self.oc.indent() - obj += IdentCoder.iter_next(uintptr(it)) - obj += ":;\n" - obj += self.oc.indent() - obj += "}\n" - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;" - - ret obj - } - - fn while_iter(mut self, mut it: &WhileIter): str { - let mut obj = "" - if it.expr != nil && it.next == nil { - obj += "while (" - obj += self.oc.ec.expr(it.expr) - obj += ") {\n" - } else { - obj += "for (; " - if it.expr != nil { - obj += self.oc.ec.expr(it.expr) - } - obj += "; " - if it.next != nil { - let st = self.st(it.next) - obj += st[:st.len-1] - } - obj += ") {\n" - } - - self.oc.add_indent() - obj += self.oc.indent() - obj += self.scope(it.scope) - obj += "\n" - self.oc.done_indent() - obj += self.oc.indent() - - obj += IdentCoder.iter_next(uintptr(it)) - obj += ":;\n" - obj += self.oc.indent() - obj += "}\n" - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;" - ret obj - } - - fn range_iter(mut self, mut it: &RangeIter): str { - match { - | it.expr.kind.slc() != nil: - ret self.range_index_iter(it) - | it.expr.kind.arr() != nil: - ret self.range_index_iter(it) - | it.expr.kind.map() != nil: - ret self.range_hashmap_iter(it) - |: - ret self.range_index_iter(it) // Str - } - } - - fn cont(self, c: &ContSt): str { - let mut obj = "goto " - obj += IdentCoder.iter_next(c.it) - obj += ";" - ret obj - } - - fn label(self, l: &Label): str { - ret IdentCoder.label(l.ident) + ":;" - } - - fn goto_st(self, gt: &GotoSt): str { - let mut obj = "goto " - obj += IdentCoder.label(gt.ident) - obj += ";" - ret obj - } - - fn postfix(mut self, mut p: &Postfix): str { - let mut obj = "(" - obj += self.oc.ec.expr(p.expr) - obj += ")" - obj += p.op - obj += ";" - ret obj - } - - fn assign(mut self, mut a: &Assign): str { - let mut obj = self.oc.ec.expr(a.l.model) - obj += a.op.kind - obj += self.oc.ec.expr(a.r.model) - obj += ";" - ret obj - } - - fn multi_assign(mut self, mut a: &MultiAssign): str { - let mut obj = "std::tie(" - - for (_, mut l) in a.l { - if l == nil { - obj += CPP_IGNORE - } else { - obj += self.oc.ec.expr(l) - } - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - - obj += ") = " - obj += self.oc.ec.expr(a.r) - obj += ";" - ret obj - } - - fn match_expr(mut self, mut &m: &Match): str { - if !m.expr.is_const() { - ret MATCH_EXPR - } - if !m.expr.constant.is_bool() || !m.expr.constant.read_bool() { - ret self.oc.ec.model(m.expr.model) - } - ret "" - } - - fn case(mut self, mut m: &Match, mut c: &Case): str { - let mut obj = "" - - if c.exprs.len != 0 && !m.is_generic_type_match() { - if m.cases.len > 0 && m.cases[0] == c { - obj += "if (" - } else { - obj += "else if (" - } - for (i, mut expr) in c.exprs { - match { - | !m.type_match: - let case_expr = self.match_expr(m) - if m.expr.good_operand(expr) { - if case_expr.len != 0 { - obj += case_expr - obj += " == " - } - obj += self.oc.ec.expr(expr.model) - } else { - obj += self.oc.ec.expr(expr.model) - if case_expr.len != 0 { - obj += " == " - obj += case_expr - } - } - |: - obj += MATCH_EXPR - obj += ".type_is<" - obj += self.oc.ec.expr(expr.model) - obj += ">()" - } - - if i+1 < c.exprs.len { - obj += " || " - } - } - obj += ") " - } else if m.default == c && m.cases.len != 0 { - obj += self.oc.indent() - obj += "else " - } - - self.oc.add_indent() - - obj += "{\n" - obj += self.oc.indent() - obj += IdentCoder.case_begin(uintptr(c)) - obj += ":;\n" - if c.scope.stmts.len > 0 { - obj += self.oc.indent() - obj += self.scope(c.scope) - obj += "\n" - } - - self.oc.done_indent() - - obj += self.oc.indent() - obj += "}" - ret obj - } - - fn match_st(mut self, mut m: &Match): str { - if m.cases.len == 0 && m.default == nil { - ret "" - } - - let generic_type_match = m.is_generic_type_match() - if generic_type_match && (m.default == nil || m.default.scope.stmts.len == 0) { - ret "" - } - - let mut obj = "{\n" - - self.oc.add_indent() - - obj += self.oc.indent() - - // Constant expressions generated as literals in conditions. - if !generic_type_match && !m.expr.is_const() { - if env::OPT_COPY && is_copy_optimizable(m.expr) { - obj += "auto &_match_expr{ " - } else { - obj += "auto _match_expr{ " - } - obj += self.oc.ec.expr(m.expr.model) - obj += " };\n" - obj += self.oc.indent() - } - - if m.cases.len > 0 { - for (_, mut c) in m.cases { - if c == nil { - continue - } - obj += "\n" - obj += self.oc.indent() - obj += self.case(m, c) - } - } - - if m.default != nil { - obj += "\n" - obj += self.case(m, m.default) - } - - obj += "\n" - obj += self.oc.indent() - obj += IdentCoder.match_end(uintptr(m)) - obj += ":;" - obj += "\n" - - self.oc.done_indent() - - obj += self.oc.indent() - obj += "}" - - ret obj - } - - fn fall_st(self, f: &FallSt): str { - let mut obj = "goto " - obj += IdentCoder.case_begin(f.dest_case) - obj += ";" - ret obj - } - - fn break_st(self, b: &BreakSt): str { - let mut obj = "goto " - if b.it != 0 { - obj += IdentCoder.iter_end(b.it) - } else { - obj += IdentCoder.match_end(b.mtch) - } - obj += ";" - ret obj - } - - fn ret_with_vars(mut self, mut r: &RetSt): str { - let mut obj = "" - for (_, mut v) in r.vars { - if lex::is_ignore_ident(v.ident) { - obj += self.oc.ec.init_expr(v.kind.kind) - } else { - obj += IdentCoder.var(v) - } - obj += "," - } - - obj = obj[:obj.len-1] // Remove last comma. - - let mut oobj = "return " - - if r.func.decl.exceptional { - oobj += "jule::Exceptional<" - oobj += TypeCoder.kind(r.func.result) - oobj += ">(jule::Any(), " - } - - if r.vars.len > 1 { - oobj += "std::make_tuple(" - oobj += obj - oobj += ")" - } else { - oobj += obj - } - - if r.func.decl.exceptional { - oobj += ")" - } - - oobj += ";" - ret oobj - } - - fn ret_tuple(mut self, mut r: &RetSt): str { - let mut datas = (&TupleExprModel)(r.expr).datas - let mut obj = "" - - for (i, mut v) in r.vars { - if lex::is_ignore_ident(v.ident) { - continue - } - let mut model = datas[i].model - // Ignore self assignment. - if model == v { - continue - } - let ident = IdentCoder.var(v) - obj += ident - obj += " = " - obj += self.oc.ec.expr(model) - obj += ";\n" - obj += self.oc.indent() - } - - let mut oobj = "std::make_tuple(" - for (i, mut d) in datas { - let mut v = r.vars[i] - if lex::is_ignore_ident(v.ident) { - oobj += self.oc.ec.expr(d.model) - } else { - oobj += IdentCoder.var(v) - } - - oobj += "," - } - oobj = oobj[:oobj.len-1] // Remove last comma. - oobj += ")" - - if r.func.decl.exceptional { - obj += "return jule::Exceptional<" - obj += TypeCoder.kind(r.func.result) - obj += ">(jule::Any()," - obj += oobj - obj += ")" - } else { - obj += "return " - obj += oobj - } - - obj += ";" - ret obj - } - - fn ret_with_exprs(mut self, mut r: &RetSt): str { - if r.vars.len > 1 { - ret self.ret_tuple(r) - } - - // Ignore self assignments and ignored variables. - if r.vars.len > 0 { - let mut v = r.vars[0] - if !lex::is_ignore_ident(v.ident) && r.expr != v { - let ident = IdentCoder.var(v) - let mut obj = ident - obj += " = " - obj += self.oc.ec.expr(r.expr) - obj += ";\n" - obj += self.oc.indent() - if r.func.decl.exceptional { - obj += "return jule::Exceptional<" - obj += TypeCoder.kind(r.func.result) - obj += ">(jule::Any()," - obj += ident - obj += ")" - } else { - obj += "return " - obj += ident - } - obj += ";" - ret obj - } - } - - if r.func.decl.exceptional { - let mut obj = "return jule::Exceptional<" - obj += TypeCoder.kind(r.func.result) - obj += ">(jule::Any()," - obj += self.oc.ec.expr(r.expr) - obj += ")" - obj += ";" - ret obj - } - - let mut obj = "return " - obj += self.oc.ec.expr(r.expr) - obj += ";" - ret obj - } - - fn ret_st(mut self, mut r: &RetSt): str { - // Void. - if r.expr == nil && r.vars.len == 0 { - if r.func.decl.exceptional { - ret "return jule::VoidExceptional();" - } - ret "return;" - } - - if r.expr == nil { - ret self.ret_with_vars(r) - } - ret self.ret_with_exprs(r) - } - - fn ret_with_defaults(mut self, mut result: &TypeKind): str { - let mut obj = "return " - if result.tup() != nil { - obj += "std::make_tuple(" - for (_, mut t) in result.tup().types { - obj += self.oc.ec.init_expr(t) - obj += "," - } - obj = obj[:obj.len-1] // Remove last comma. - obj += ")" - } else { - obj += self.oc.ec.init_expr(result) - } - obj += ";" - ret obj - } - - fn var(mut self, mut v: &Var): str { - if v.constant { - ret "" - } - ret self.oc.var(v) - } - - // Generates C++ code of statement. - fn st(mut self, mut st: St): str { - if st == nil { - ret "" - } - match type st { - | &Scope: - ret self.scope((&Scope)(st)) - | &Var: - ret self.var((&Var)(st)) - | &Data: - ret self.oc.ec.expr((&Data)(st)) + ";" - | &Conditional: - ret self.conditional((&Conditional)(st)) - | &InfIter: - ret self.inf_iter((&InfIter)(st)) - | &WhileIter: - ret self.while_iter((&WhileIter)(st)) - | &RangeIter: - ret self.range_iter((&RangeIter)(st)) - | &ContSt: - ret self.cont((&ContSt)(st)) - | &Label: - ret self.label((&Label)(st)) - | &GotoSt: - ret self.goto_st((&GotoSt)(st)) - | &Postfix: - ret self.postfix((&Postfix)(st)) - | &Assign: - ret self.assign((&Assign)(st)) - | &MultiAssign: - ret self.multi_assign((&MultiAssign)(st)) - | &Match: - ret self.match_st((&Match)(st)) - | &FallSt: - ret self.fall_st((&FallSt)(st)) - | &BreakSt: - ret self.break_st((&BreakSt)(st)) - | &RetSt: - ret self.ret_st((&RetSt)(st)) - | &PushToSliceExprModel: - ret self.oc.ec.push_to_slice((&PushToSliceExprModel)(st)) - | &MutSlicingExprModel: - ret self.oc.ec.mut_slicing((&MutSlicingExprModel)(st)) - | &StrInsertBeginExprModel: - ret self.oc.ec.str_insert_begin((&StrInsertBeginExprModel)(st)) - |: - ret "" - } - } - - fn scope_end(mut self, mut &obj: str, mut &s: &Scope) { - for (_, mut st) in s.stmts { - obj += self.oc.indent() - obj += self.st(st) - obj += "\n" - } - - self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - if s.deferred { - obj = "__JULE_DEFER(" + obj + ");" - } - } - - // Generates C++ code of scope. - fn scope(mut self, mut s: &Scope): str { - self.oc.add_indent() - let mut obj = "{\n" - self.scope_end(obj, s) - ret obj - } - - // Generates C++ code of function's scope. - fn func_scope(mut self, mut f: &FnIns): str { - if f.scope == nil { - ret "" - } - let mut obj = "{\n" - self.oc.add_indent() - if !f.decl.is_void() { - let mut types = f.types() - for i, ident in f.decl.result.idents { - if lex::is_ignore_ident(ident.kind) || - lex::is_anon_ident(ident.kind) { - continue - } - obj += self.oc.indent() - obj += TypeCoder.kind(types[i]) - obj += " " - obj += IdentCoder.to_local(ident.row, ident.column, ident.kind) - obj += " = " - obj += self.oc.ec.init_expr(types[i]) - obj += ";\n" - } - } - self.scope_end(obj, f.scope) - if f.decl.exceptional && f.decl.is_void() { - // Just for void exceptionals. - // Other cases checked by semantic analsis and disallowed - // if they are not returns. - obj = obj[:obj.len-2] + " return jule::VoidExceptional(); }" - } - ret obj - } -} - -fn is_copy_optimizable(&expr: &Data): bool { - if !expr.lvalue { - ret false - } - match type expr.model { - | &SlicingExprModel: - ret false - } - ret true -} - -fn is_iter_copy_optimizable(&expr: &Data, &v: &Var): bool { - if !expr.lvalue && !expr.kind.mutable() { - ret true - } - ret !v.mutable && !expr.mutable -} \ No newline at end of file diff --git a/src/julec/obj/cxx/testing.jule b/src/julec/obj/cxx/testing.jule deleted file mode 100644 index 885dc42ba..000000000 --- a/src/julec/obj/cxx/testing.jule +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use env -use obj::{IR} -use std::jule::build::{ - Directive, -} -use std::jule::sema::{ - ImportInfo, - Package, - Fn, - FnIns, - StructIns, -} - -pub struct TestCoder { - t: &StructIns - tm_reset: &Fn - tm_failed: &Fn - tm_skipped: &Fn - - oc: &ObjectCoder -} - -impl TestCoder { - pub static fn new(mut &oc: &ObjectCoder): &TestCoder { - ret &TestCoder{ - oc: oc, - } - } - - fn find_testing_package(mut self): &ImportInfo { - for (_, mut imp) in self.oc.ir.used { - if imp.link_path == "std::testing" { - ret imp - } - } - ret nil - } - - fn append_test(mut self, mut &obj: str, mut f: &FnIns) { - obj += self.oc.indent() - obj += self.call_tm_reset() - obj += ";\n" - obj += self.oc.indent() - obj += "std::cout << \">>> TEST RUNNING: \";\n" - obj += self.oc.indent() - obj += "jule::outln(" - obj += cstr_lit([]byte(f.decl.ident)) - obj += ");\n" - obj += self.oc.indent() - obj += IdentCoder.func_ins(f) - obj += "(_t);\n" - obj += self.oc.indent() - obj += "post_test();\n" - } - - fn append_package_tests(mut self, mut &obj: str, mut &p: &Package) { - for (_, mut file) in p.files { - for (_, mut f) in file.funcs { - if has_directive(f.directives, Directive.Test) { - self.append_test(obj, f.instances[0]) - } - } - } - } - - fn ready_testing_package(mut self): bool { - let mut p = self.find_testing_package() - if p == nil { - // std::testing is not used. - // So, developers cannot write valid test functions. - ret false - } - - self.t = p.find_struct("T", false).instances[0] - - self.tm_reset = self.t.find_method("reset", false) - self.tm_failed = self.t.find_method("failed", false) - self.tm_skipped = self.t.find_method("skipped", false) - ret true - } - - fn call_tm_reset(mut self): str { - let mut obj = IdentCoder.func(self.tm_reset) - obj += "(_t)" - ret obj - } - - fn call_tm_failed(mut self): str { - let mut obj = IdentCoder.func(self.tm_failed) - obj += "(_t)" - ret obj - } - - fn call_tm_skipped(mut self): str { - let mut obj = IdentCoder.func(self.tm_skipped) - obj += "(_t)" - ret obj - } - - // Serialize tests and test point. - // Appends to object code. - pub fn serialize(mut self, mut &obj: str) { - obj += "\nvoid test_point(void) {\n" - self.oc.add_indent() - obj += self.oc.indent() - - if !self.ready_testing_package() { - obj += "}" - self.oc.done_indent() - ret - } - - obj += TypeCoder.as_sptr(TypeCoder.structure_ins(self.t)) - obj += " _t = jule::new_ptr<" - obj += TypeCoder.structure_ins(self.t) - obj += ">(); _t.ref = nullptr;\n" - - obj += self.oc.indent() - obj += "jule::Uint total = 0, failed = 0, skipped = 0;\n" - obj += self.oc.indent() - - obj += "auto post_test = [&](void) {\n" - self.oc.add_indent() - obj += self.oc.indent() - obj += "++total;\n" - obj += self.oc.indent() - obj += "if (" - obj += self.call_tm_failed() - obj += ") { ++failed; std::cout << \" [*] FAILED\" << std::endl; }\n" - obj += self.oc.indent() - obj += "else if (" - obj += self.call_tm_skipped() - obj += ") { ++skipped; std::cout << \" [*] SKIPPED\" << std::endl; }\n" - obj += self.oc.indent() - obj += "else { std::cout << \" [*] PASSED\" << std::endl; }\n" - self.oc.done_indent() - obj += self.oc.indent() - obj += "};\n" - - self.append_package_tests(obj, self.oc.ir.main) - - obj += "\n\n" - obj += self.oc.indent() - obj += "std::cout << std::endl << \"total tests: \" << total << \" skipped: \" << skipped << \" failed: \" << failed << \" pass: \" << total-failed-skipped << std::endl;\n" - obj += self.oc.indent() - obj += "if (failed != 0) std::exit(1);\n" - - self.oc.done_indent() - obj += self.oc.indent() - obj += "}\n" - } -} \ No newline at end of file diff --git a/src/julec/obj/cxx/type.jule b/src/julec/obj/cxx/type.jule deleted file mode 100644 index c5e01261f..000000000 --- a/src/julec/obj/cxx/type.jule +++ /dev/null @@ -1,330 +0,0 @@ -// Copyright 2023-2024 The Jule Programming Language. -// Use of this source code is governed by a BSD 3-Clause -// license that can be found in the LICENSE file. - -use ast for std::jule::ast -use conv for std::conv -use std::jule::build::{Directive} -use std::jule::sema::{ - Prim, - Tuple, - Sptr, - Ptr, - Slc, - Enum, - TypeKind, - Map, - Trait, - Struct, - StructIns, - FnIns, - Arr, - ParamIns, - Fn, - Param, - Kind, -} -use types for std::jule::types - -// Returns directive if exist. -fn find_directive(mut &directives: []&ast::Directive, tag: str): &ast::Directive { - for (_, mut dr) in directives { - if dr.tag.kind == tag { - ret dr - } - } - ret nil -} - -// Reports whether directive is exist. -fn has_directive(&directives: []&ast::Directive, tag: str): bool { - ret find_directive(unsafe { *(&directives) }, tag) != nil -} - -struct CustomType { - kind: str -} - -impl Kind for CustomType { - pub fn to_str(self): str { - ret self.kind - } - - pub fn equals(&self, k: &TypeKind): bool { - ret false - } -} - -struct TypeCoder {} - -impl TypeCoder { - const Str = "jule::Str" - const Map = "jule::Map" - const Ptr = "jule::Ptr" - const Sptr = "jule::Sptr" - const Slice = "jule::Slice" - const Trait = "jule::Trait" - const Array = "jule::Array" - const Fn = "jule::Fn" - const Bool = "jule::Bool" - const Uintptr = "jule::Uintptr" - - // Returns given identifier as Jule type identifier. - static fn to_type(mut id: str): str { - id = types::real_kind_of(id) - if 97 <= id[0] && id[0] <= 122 { - id[0] -= 32 // To upper first byte. - } - ret "jule::" + id - } - - // Generates C++ code of Prim TypeKind. - static fn prim(p: &Prim): str { - ret TypeCoder.to_type(p.to_str()) - } - - // Generates C++ code of Tupe TypeKind. - static fn tuple(mut t: &Tuple): str { - let mut obj = "std::tuple<" - for (_, mut tk) in t.types { - obj += TypeCoder.kind(tk) - obj += "," - } - obj = obj[:obj.len-1] // Remove comma - obj += ">" - ret obj - } - - // Returns C++ code of smart pointer type with element type. - static fn as_sptr(elem: str): str { - let mut obj = TypeCoder.Ptr + "<" - obj += elem - obj += ">" - ret obj - } - - // Returns C++ code of pointer type with element type. - static fn as_ptr(elem: str): str { - ret elem + "*" - } - - // Generates C++ code of smart pointer TypeKind. - static fn sptr(mut sptr: &Sptr): str { - ret TypeCoder.as_sptr(TypeCoder.kind(sptr.elem)) - } - - // Generates C++ code of Ptr TypeKind. - static fn ptr(mut p: &Ptr): str { - const CPP_POINTER_MARK = "*" - if p.is_unsafe() { - ret "void" + CPP_POINTER_MARK - } - let mut elem = TypeCoder.kind(p.elem) - elem += CPP_POINTER_MARK - ret elem - } - - // Generates C++ code of Enum TypeKind. - static fn enum_decl(mut e: &Enum): str { - ret TypeCoder.kind(e.kind.kind) - } - - static fn as_slice(mut elem: &TypeKind): str { - let mut obj = TypeCoder.Slice + "<" - obj += TypeCoder.kind(elem) - obj += ">" - ret obj - } - - // Generates C++ code of Slc TypeKind. - static fn slice(mut s: &Slc): str { - ret TypeCoder.as_slice(s.elem) - } - - // Generates C++ code of Map TypeKind. - static fn map(mut m: &Map): str { - let mut obj = TypeCoder.Map + "<" - obj += TypeCoder.kind(m.key) - obj += "," - obj += TypeCoder.kind(m.val) - obj += ">" - ret obj - } - - static fn trait_ident(ident: str): str { - let mut obj = TypeCoder.Trait + "<" - obj += ident - obj += ">" - ret obj - } - - // Generates C++ code of Trait TypeKind. - static fn trait_decl(t: &Trait): str { - ret TypeCoder.trait_ident(IdentCoder.trait_decl(t)) - } - - // Generates C++ code of Struct TypeKind. - static fn structure(s: &Struct): str { - let mut rep = "" - if s.cpp_linked && !has_directive(s.directives, Directive.Typedef) { - rep += "struct " - } - rep += IdentCoder.structure(s) - ret rep - } - - // Generates C++ code of Struct instance TypeKind. - static fn structure_ins(mut s: &StructIns): str { - if s.decl.cpp_linked { - let mut ident = IdentCoder.structure_ins(s) - if s.generics.len > 0 { - ident += "<" - for (_, mut g) in s.generics { - ident += TypeCoder.kind(g) - ident += "," - } - ident = ident[:ident.len-1] // Remove last comma. - ident += ">" - } - let d = find_directive(s.decl.directives, Directive.Namespace) - if d != nil { - ident = concat_all_parts(d.args...) + "::" + ident - } - ret ident - } - ret IdentCoder.structure_ins(s) - } - - // Generates C++ code of Arr TypeKind. - static fn array(mut a: &Arr): str { - let mut obj = TypeCoder.Array + "<" - obj += TypeCoder.kind(a.elem) - obj += "," - obj += conv::itoa(a.n) - obj += ">" - ret obj - } - - // Generates C++ prototype code of parameter. - static fn param(mut &p: &Param): str { - let mut obj = "" - if p.variadic { - obj += TypeCoder.Slice + "<" - obj += TypeCoder.kind(p.kind.kind) - obj += ">" - } else { - obj += TypeCoder.kind(p.kind.kind) - } - if p.reference { - obj += "&" - } - ret obj - } - - // Generates C++ prototype code of parameter instance. - static fn param_ins(mut &p: &ParamIns): str { - let mut obj = "" - if p.decl.variadic { - obj += TypeCoder.Slice + "<" - obj += TypeCoder.kind(p.kind) - obj += ">" - } else { - obj += TypeCoder.kind(p.kind) - } - if p.decl.reference { - obj += "&" - } - ret obj - } - - // Generates C++ code of function's result type. - static fn func_result(mut &f: &Fn): str { - if f.is_void() { - if f.exceptional { - ret "jule::VoidExceptional" - } - ret "void" - } - if f.exceptional { - ret "jule::Exceptional<" + TypeCoder.kind(f.result.kind.kind) + ">" - } - ret TypeCoder.kind(f.result.kind.kind) - } - - // Generates C++ code of function instance's result type. - static fn func_ins_result(mut &f: &FnIns): str { - if f.decl.is_void() { - if f.decl.exceptional { - ret "jule::VoidExceptional" - } - ret "void" - } - if f.decl.exceptional { - ret "jule::Exceptional<" + TypeCoder.kind(f.result) + ">" - } - ret TypeCoder.kind(f.result) - } - - static fn anon_func(mut f: &FnIns): str { - let mut decl = TypeCoder.func_ins_result(f) - decl += "(" - if f.params.len > 0 { - for (_, mut param) in f.params { - if param.decl.is_self() { - continue - } - decl += TypeCoder.param_ins(param) - decl += "," - } - decl = decl[:decl.len-1] // Remove last comma. - } else { - decl += "void" - } - decl += ")" - ret decl - } - - // Generates C++ code of Fn TypeKind. - static fn func(mut f: &FnIns): str { - let mut obj = TypeCoder.Fn + "<" - obj += TypeCoder.anon_func(f) - obj += ">" - ret obj - } - - // Generates C++ code of TypeKind. - static fn kind(mut k: &TypeKind): str { - match { - | k.cpp_linked(): - ret k.cpp_ident - | k.prim() != nil: - ret TypeCoder.prim(k.prim()) - | k.tup() != nil: - ret TypeCoder.tuple(k.tup()) - | k.sptr() != nil: - ret TypeCoder.sptr(k.sptr()) - | k.ptr() != nil: - ret TypeCoder.ptr(k.ptr()) - | k.enm() != nil: - ret TypeCoder.enum_decl(k.enm()) - | k.slc() != nil: - ret TypeCoder.slice(k.slc()) - | k.map() != nil: - ret TypeCoder.map(k.map()) - | k.trt() != nil: - ret TypeCoder.trait_decl(k.trt()) - | k.strct() != nil: - ret TypeCoder.structure_ins(k.strct()) - | k.arr() != nil: - ret TypeCoder.array(k.arr()) - | k.fnc() != nil: - ret TypeCoder.func(k.fnc()) - } - match type k.kind { - | &CustomType: - ret (&CustomType)(k.kind).kind - |: - ret "[]" - } - } -} \ No newline at end of file From df1d3e26d23f54d3f926428ef5312cb543a4fbad Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 17:46:10 +0300 Subject: [PATCH 02/17] compiler: add head comment code generation --- src/julec/compile.jule | 41 +++++++++--------------- src/julec/obj/cxx/object.jule | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 src/julec/obj/cxx/object.jule diff --git a/src/julec/compile.jule b/src/julec/compile.jule index a4bf4bcb1..2c26bb48f 100644 --- a/src/julec/compile.jule +++ b/src/julec/compile.jule @@ -46,7 +46,7 @@ fn init() { env::COMPILER = "clang" } -fn write_output(path: str, content: str) { +fn open_output(&path: str): &File { let dir = dir(path) Status.of(dir) else { @@ -55,8 +55,9 @@ fn write_output(path: str, content: str) { } } - File.write(path, []byte(content), 0660) else { + ret File.create(path) else { throw("a problem occurs when code generation") + use nil } } @@ -106,15 +107,6 @@ fn compile_ir(compiler: str, compiler_cmd: str) { clear_objects() } -// Compile. -fn do_spell(obj: str, compiler: str, compiler_cmd: str) { - let path = get_compile_path() - write_output(path, obj) - if !env::TRANSPILATION { - compile_ir(compiler, compiler_cmd) - } -} - fn is_cpp_source_file(path: str): bool { let offset = strings::find_last_byte(path, '.') if offset == -1 { @@ -415,15 +407,15 @@ fn compile_command(mut &args: []str) { const CPP_LINKED = false if !env::TEST { - let mut f = ir.main.find_fn(ENTRY_POINT, CPP_LINKED) - if f == nil { + let mut main = ir.main.find_fn(ENTRY_POINT, CPP_LINKED) + if main == nil { throw(logf(LogMsg.NoEntryPoint)) } - f.statically = true // Mark used for deadcode elimination. + main.statically = true // Mark used for deadcode elimination. } - let mut f = ir.main.find_fn(INIT_FN, CPP_LINKED) - if f != nil { - f.statically = true // Mark used for deadcode elimination. + let mut init = ir.main.find_fn(INIT_FN, CPP_LINKED) + if init != nil { + init.statically = true // Mark used for deadcode elimination. } apply_target_independent_optimizations(ir) @@ -433,17 +425,12 @@ fn compile_command(mut &args: []str) { let (compiler, compiler_cmd) = gen_compile_cmd(get_compile_path(), ir) - let mut oc = cxx::ObjectCoder.new(ir, cxx::SerializationInfo{ + let path = get_compile_path() + let mut file = open_output(path) + + let mut oc = cxx::ObjectCoder.new(ir, file, cxx::SerializationInfo{ compiler: compiler, compiler_command: compiler_cmd, }) - let mut obj = oc.serialize() - - if env::TEST { - let mut tc = cxx::TestCoder.new(oc) - tc.serialize(obj) - } - oc.append_standard(obj) - - do_spell(obj, compiler, compiler_cmd) + oc.serialize() } \ No newline at end of file diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule new file mode 100644 index 000000000..f757f5098 --- /dev/null +++ b/src/julec/obj/cxx/object.jule @@ -0,0 +1,59 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use obj::{IR} +use conv for std::conv +use std::fs::{File} +use std::time::{Time} +use jule for std::jule + +pub struct SerializationInfo { + pub compiler: str + pub compiler_command: str +} + +pub struct ObjectCoder { + ir: &IR + info: SerializationInfo + f: &File +} + +impl ObjectCoder { + pub static fn new(mut &ir: &IR, mut &f: &File, info: SerializationInfo): &ObjectCoder { + let mut oc = &ObjectCoder{ + ir: ir, + info: info, + f: f, + } + ret oc + } + + fn write(mut &self, mut s: str) { + _ = self.f.write([]byte(s))! + } + + fn head(mut &self) { + let time = Time.now() + let abs = time.abs() + self.write("// Auto generated by JuleC.\n") + self.write("// JuleC version: ") + self.write(jule::VERSION) + self.write("\n") + self.write("// Date: ") + self.write(conv::fmt_uint(abs.day, 10)) + self.write("/") + self.write(conv::fmt_uint(abs.month, 10)) + self.write("/") + self.write(conv::fmt_uint(abs.year, 10)) + self.write(" (DD/MM/YYYY) UTC\n//\n// Recomended Compile Command;\n// ") + self.write(self.info.compiler) + self.write(" ") + self.write(self.info.compiler_command) + self.write("\n\n") + } + + pub fn serialize(mut &self) { + self.head() + } +} From e1d9767494ee6ba13efa9c0b27378813fc6a6fb4 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 18:05:34 +0300 Subject: [PATCH 03/17] compiler: add code generation for cpp-links --- src/julec/obj/cxx/object.jule | 64 ++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index f757f5098..af1562422 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -2,11 +2,42 @@ // Use of this source code is governed by a BSD 3-Clause // license that can be found in the LICENSE file. +use env use obj::{IR} use conv for std::conv use std::fs::{File} -use std::time::{Time} use jule for std::jule +use build for std::jule::build::{ + Directive, + Derive, +} +use std::jule::lex::{ + Token, + TokenId, + is_ignore_ident, + is_anon_ident, +} +use std::jule::sema::{ + FuncPattern, + Package, + SymbolTable, + Param, + ParamIns, + Trait, + Struct, + FieldIns, + Var, + StructIns, + Fn, + FnIns, + TypeKind, + Prim, + Sptr, + TypeSymbol, +} +use path for std::fs::path +use strings for std::strings +use std::time::{Time} pub struct SerializationInfo { pub compiler: str @@ -51,9 +82,40 @@ impl ObjectCoder { self.write(" ") self.write(self.info.compiler_command) self.write("\n\n") + + if env::PRODUCTION { + self.write("#define __JULE_ENABLE__PRODUCTION\n") + } + if !env::RC { + self.write("#define __JULE_DISABLE__REFERENCE_COUNTING\n") + } + if !env::SAFETY { + self.write("#define __JULE_DISABLE__SAFETY\n") + } + self.write("\n\n#include \"") + self.write(build::PATH_API) + self.write("\"\n\n") + } + + fn links(mut &self) { + for _, used in self.ir.used { + match { + | !used.cpp_linked: + continue + | build::is_std_header_path(used.path): + self.write("#include ") + self.write(used.path) + self.write("\n") + |: + self.write("#include \"") + self.write(used.path) + self.write("\n") + } + } } pub fn serialize(mut &self) { self.head() + self.links() } } From 00e63d36f99eb277f76370081c1d8824ed57ff53 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 18:48:55 +0300 Subject: [PATCH 04/17] compiler: add ident and type code generation --- src/julec/obj/cxx/ident.jule | 211 ++++++++++++++++++++++ src/julec/obj/cxx/object.jule | 95 ++++++++++ src/julec/obj/cxx/type.jule | 330 ++++++++++++++++++++++++++++++++++ 3 files changed, 636 insertions(+) create mode 100644 src/julec/obj/cxx/ident.jule create mode 100644 src/julec/obj/cxx/type.jule diff --git a/src/julec/obj/cxx/ident.jule b/src/julec/obj/cxx/ident.jule new file mode 100644 index 000000000..17f071f5b --- /dev/null +++ b/src/julec/obj/cxx/ident.jule @@ -0,0 +1,211 @@ +// Copyright 2023-2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use env +use conv for std::conv +use std::jule::build::{ENTRY_POINT, Directive} +use std::jule::lex::{TokenKind, is_anon_ident, is_ignore_ident} +use std::jule::sema::{ + Fn, + FnIns, + Trait, + Struct, + StructIns, + Field, + Var, + Param, +} + +// Identifier of initialize function caller function. +const INIT_CALLER_IDENT = "__jule_call_initializers" + +struct IdentCoder {} + +impl IdentCoder { + const Self = "_self_" + + // Returns specified identifer as JuleC identifer. + // Equavalents: "JULEC_ID(" + ident + ")" of JuleC API. + static fn to_ident(ident: str): str { + ret "_" + ident + } + + // Returns cpp output identifier form of pointer address. + static fn addr(addr: uintptr): str { + ret "_" + conv::fmt_uint(u64(addr), 0xF) + } + + // Returns cpp output identifier form of given identifier. + // + // Parameters: + // - ident: Identifier. + // - addr: Pointer address of package file handler. + static fn to_out(ident: str, addr: uintptr): str { + if addr != 0 { + let mut obj = IdentCoder.addr(addr) + obj += "_" + obj += ident + ret obj + } + ret IdentCoder.to_ident(ident) + } + + // Returns cpp output local identifier form of fiven identifier. + // + // Parameters: + // - row: Row of definition. + // - col: Column of definition. + // - ident: Identifier of definition. + static fn to_local(row: int, col: int, ident: str): str { + let mut obj = conv::itoa(row) + obj += conv::itoa(col) + obj += "_" + obj += ident + ret IdentCoder.to_ident(obj) + } + + // Returns output identifier of function. + static fn func(&f: &Fn): str { + match { + | f.cpp_linked: + ret f.ident + | f.ident == ENTRY_POINT: + ret "entry_point" + | f.is_method(): + let mut obj = IdentCoder.to_out(f.ident, uintptr(f)) + if f.statically { + obj = "static_" + obj + ret obj + } + ret obj + |: + ret IdentCoder.to_out(f.ident, uintptr(f)) + } + } + + // Returns output identifier of function instance. + static fn func_ins(mut &f: &FnIns): str { + if f.is_builtin() { + ret "jule::" + f.decl.ident + } + if f.decl.cpp_linked || f.generics.len == 0 { + ret IdentCoder.func(f.decl) + } + for (i, mut ins) in f.decl.instances { + if ins.same(f) { + let mut obj = IdentCoder.func(f.decl) + obj += "_" + obj += conv::itoa(i) + ret obj + } + } + ret "__?__" + } + + // Returns output identifier of trait. + static fn trait_decl(t: &Trait): str { + if t.is_builtin() { + ret "jule::" + t.ident + } + ret IdentCoder.to_out(t.ident, uintptr(t)) + } + + // Returns output identifier of parameter. + static fn param(&p: &Param): str { + if is_anon_ident(p.ident) || is_ignore_ident(p.ident) { + ret "" + } + if p.is_self() { + ret IdentCoder.Self + } + if p.token == nil { + ret IdentCoder.to_local(0, 0, p.ident) + } + ret IdentCoder.to_local(p.token.row, p.token.column, p.ident) + } + + // Returns output identifier of structure. + static fn structure(&s: &Struct): str { + if s.cpp_linked { + if has_directive(s.directives, Directive.Typedef) { + ret s.ident + } + ret "struct " + s.ident + } + ret IdentCoder.to_out(s.ident, uintptr(s)) + } + + // Returns output identifier of structure instance. + static fn structure_ins(mut &s: &StructIns): str { + if s.decl.cpp_linked || s.generics.len == 0 { + ret IdentCoder.structure(s.decl) + } + for (i, mut ins) in s.decl.instances { + if ins.same(s) { + let mut obj = IdentCoder.structure(s.decl) + obj += "_" + obj += conv::itoa(i) + ret obj + } + } + ret "__?__" + } + + // Returns output identifier of field. + static fn field(&f: &Field): str { + if f.owner.cpp_linked { + ret f.ident + } + ret "_field_" + f.ident + } + + // Returns output identifier of variable. + static fn var(mut v: &Var): str { + match { + | v.cpp_linked: + ret v.ident + | v.ident == TokenKind.Error: + ret "except.error" + | v.ident == TokenKind.Self: + if v.kind.kind.sptr() == nil { + ret "(*" + IdentCoder.Self + ")" + } + ret IdentCoder.Self + | v.scope != nil: + ret IdentCoder.to_local(v.token.row, v.token.column, v.ident) + |: + ret IdentCoder.to_out(v.ident, uintptr(v)) + } + } + + // Returns begin label identifier of iteration. + static fn iter_begin(it: uintptr): str { + ret "_iter_begin_" + conv::fmt_uint(u64(it), 0xF) + } + + // Returns end label identifier of iteration. + static fn iter_end(it: uintptr): str { + ret "_iter_end_" + conv::fmt_uint(u64(it), 0xF) + } + + // Returns next label identifier of iteration. + static fn iter_next(it: uintptr): str { + ret "_iter_next_" + conv::fmt_uint(u64(it), 0xF) + } + + // Returns label identifier. + static fn label(ident: str): str { + ret "_julec_label_" + ident + } + + // Returns end label identifier of match-case. + static fn match_end(m: uintptr): str { + ret "_match_end_" + conv::fmt_uint(u64(m), 0xF) + } + + // Returns begin label identifier of case. + static fn case_begin(c: uintptr): str { + ret "_case_begin_" + conv::fmt_uint(u64(c), 0xF) + } +} \ No newline at end of file diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index af1562422..6635eae4c 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -44,10 +44,17 @@ pub struct SerializationInfo { pub compiler_command: str } +struct TraitHash { + t: &Trait + s: &StructIns + i: int +} + pub struct ObjectCoder { ir: &IR info: SerializationInfo f: &File + tmap: []&TraitHash } impl ObjectCoder { @@ -114,8 +121,96 @@ impl ObjectCoder { } } + fn prepare_structures(mut &self) { + for (_, mut s) in self.ir.ordered.structs { + if !s.cpp_linked && s.token != nil { + prepare_structure(s) + } + } + } + + fn iter_packages(mut &self, f: fn(mut &pkg: &Package)) { + for (_, mut used) in self.ir.used { + if !used.cpp_linked { + f(used.package) + } + } + f(self.ir.main) + } + + fn build_trait_map(mut &self) { + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut t) in file.traits { + if t.token == nil { + ret + } + let mut i = 0 + for (_, mut s) in t.implemented { + for (_, mut ins) in s.instances { + self.tmap = append(self.tmap, &TraitHash{ + t: t, + s: ins, + i: i, + }) + i++ + } + } + } + }) + }) + } + + fn decls(mut &self) { + + } + pub fn serialize(mut &self) { + self.prepare_structures() + self.build_trait_map() self.head() self.links() + self.decls() + } +} + +fn iter_files(mut &pkg: &Package, f: fn(mut &f: &SymbolTable)) { + for (_, mut file) in pkg.files { + f(file) } } + +fn prepare_structure(mut &s: &Struct) { + for (_, mut ins) in s.instances { + for (_, mut m) in ins.methods { + if m.statically { + continue + } + for (_, mut ins) in m.instances { + let mut p = ins.params[0] + if !p.decl.is_ref() { + p.kind = &TypeKind{ + kind: &CustomType{ + kind: TypeCoder.as_ptr(TypeCoder.kind(p.kind)), + }, + } + } else { + p.kind = &TypeKind{ + kind: &CustomType{ + kind: TypeCoder.kind(p.kind), + }, + } + } + } + } + } +} + +// Concatenate all strings into single string. +fn concat_all_parts(parts: ...&Token): str { + let mut s = "" + for _, p in parts { + s += p.kind + } + ret s +} \ No newline at end of file diff --git a/src/julec/obj/cxx/type.jule b/src/julec/obj/cxx/type.jule new file mode 100644 index 000000000..6da2c7e9e --- /dev/null +++ b/src/julec/obj/cxx/type.jule @@ -0,0 +1,330 @@ +// Copyright 2023-2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use ast for std::jule::ast +use conv for std::conv +use std::jule::build::{Directive} +use std::jule::sema::{ + Prim, + Tuple, + Sptr, + Ptr, + Slc, + Enum, + TypeKind, + Map, + Trait, + Struct, + StructIns, + FnIns, + Arr, + ParamIns, + Fn, + Param, + Kind, +} +use types for std::jule::types + +struct CustomType { + kind: str +} + +impl Kind for CustomType { + pub fn to_str(self): str { + ret self.kind + } + + pub fn equals(&self, k: &TypeKind): bool { + ret false + } +} + +struct TypeCoder {} + +impl TypeCoder { + const Str = "jule::Str" + const Map = "jule::Map" + const Ptr = "jule::Ptr" + const Sptr = "jule::Sptr" + const Slice = "jule::Slice" + const Trait = "jule::Trait" + const Array = "jule::Array" + const Fn = "jule::Fn" + const Bool = "jule::Bool" + const Uintptr = "jule::Uintptr" + + // Returns given identifier as Jule type identifier. + static fn to_type(mut id: str): str { + id = types::real_kind_of(id) + if 97 <= id[0] && id[0] <= 122 { + id[0] -= 32 // To upper first byte. + } + ret "jule::" + id + } + + // Generates C++ code of Prim TypeKind. + static fn prim(p: &Prim): str { + ret TypeCoder.to_type(p.to_str()) + } + + // Generates C++ code of Tupe TypeKind. + static fn tuple(mut t: &Tuple): str { + let mut obj = "std::tuple<" + for (_, mut tk) in t.types { + obj += TypeCoder.kind(tk) + obj += "," + } + obj = obj[:obj.len-1] // Remove comma + obj += ">" + ret obj + } + + // Returns C++ code of smart pointer type with element type. + static fn as_sptr(elem: str): str { + let mut obj = TypeCoder.Ptr + "<" + obj += elem + obj += ">" + ret obj + } + + // Returns C++ code of pointer type with element type. + static fn as_ptr(elem: str): str { + ret elem + "*" + } + + // Generates C++ code of smart pointer TypeKind. + static fn sptr(mut sptr: &Sptr): str { + ret TypeCoder.as_sptr(TypeCoder.kind(sptr.elem)) + } + + // Generates C++ code of Ptr TypeKind. + static fn ptr(mut p: &Ptr): str { + const CPP_POINTER_MARK = "*" + if p.is_unsafe() { + ret "void" + CPP_POINTER_MARK + } + let mut elem = TypeCoder.kind(p.elem) + elem += CPP_POINTER_MARK + ret elem + } + + // Generates C++ code of Enum TypeKind. + static fn enum_decl(mut e: &Enum): str { + ret TypeCoder.kind(e.kind.kind) + } + + static fn as_slice(mut elem: &TypeKind): str { + let mut obj = TypeCoder.Slice + "<" + obj += TypeCoder.kind(elem) + obj += ">" + ret obj + } + + // Generates C++ code of Slc TypeKind. + static fn slice(mut s: &Slc): str { + ret TypeCoder.as_slice(s.elem) + } + + // Generates C++ code of Map TypeKind. + static fn map(mut m: &Map): str { + let mut obj = TypeCoder.Map + "<" + obj += TypeCoder.kind(m.key) + obj += "," + obj += TypeCoder.kind(m.val) + obj += ">" + ret obj + } + + static fn trait_ident(ident: str): str { + let mut obj = TypeCoder.Trait + "<" + obj += ident + obj += ">" + ret obj + } + + // Generates C++ code of Trait TypeKind. + static fn trait_decl(t: &Trait): str { + ret TypeCoder.trait_ident(IdentCoder.trait_decl(t)) + } + + // Generates C++ code of Struct TypeKind. + static fn structure(s: &Struct): str { + let mut rep = "" + if s.cpp_linked && !has_directive(s.directives, Directive.Typedef) { + rep += "struct " + } + rep += IdentCoder.structure(s) + ret rep + } + + // Generates C++ code of Struct instance TypeKind. + static fn structure_ins(mut s: &StructIns): str { + if s.decl.cpp_linked { + let mut ident = IdentCoder.structure_ins(s) + if s.generics.len > 0 { + ident += "<" + for (_, mut g) in s.generics { + ident += TypeCoder.kind(g) + ident += "," + } + ident = ident[:ident.len-1] // Remove last comma. + ident += ">" + } + let d = find_directive(s.decl.directives, Directive.Namespace) + if d != nil { + ident = concat_all_parts(d.args...) + "::" + ident + } + ret ident + } + ret IdentCoder.structure_ins(s) + } + + // Generates C++ code of Arr TypeKind. + static fn array(mut a: &Arr): str { + let mut obj = TypeCoder.Array + "<" + obj += TypeCoder.kind(a.elem) + obj += "," + obj += conv::itoa(a.n) + obj += ">" + ret obj + } + + // Generates C++ prototype code of parameter. + static fn param(mut &p: &Param): str { + let mut obj = "" + if p.variadic { + obj += TypeCoder.Slice + "<" + obj += TypeCoder.kind(p.kind.kind) + obj += ">" + } else { + obj += TypeCoder.kind(p.kind.kind) + } + if p.reference { + obj += "&" + } + ret obj + } + + // Generates C++ prototype code of parameter instance. + static fn param_ins(mut &p: &ParamIns): str { + let mut obj = "" + if p.decl.variadic { + obj += TypeCoder.Slice + "<" + obj += TypeCoder.kind(p.kind) + obj += ">" + } else { + obj += TypeCoder.kind(p.kind) + } + if p.decl.reference { + obj += "&" + } + ret obj + } + + // Generates C++ code of function's result type. + static fn func_result(mut &f: &Fn): str { + if f.is_void() { + if f.exceptional { + ret "jule::VoidExceptional" + } + ret "void" + } + if f.exceptional { + ret "jule::Exceptional<" + TypeCoder.kind(f.result.kind.kind) + ">" + } + ret TypeCoder.kind(f.result.kind.kind) + } + + // Generates C++ code of function instance's result type. + static fn func_ins_result(mut &f: &FnIns): str { + if f.decl.is_void() { + if f.decl.exceptional { + ret "jule::VoidExceptional" + } + ret "void" + } + if f.decl.exceptional { + ret "jule::Exceptional<" + TypeCoder.kind(f.result) + ">" + } + ret TypeCoder.kind(f.result) + } + + static fn anon_func(mut f: &FnIns): str { + let mut decl = TypeCoder.func_ins_result(f) + decl += "(" + if f.params.len > 0 { + for (_, mut param) in f.params { + if param.decl.is_self() { + continue + } + decl += TypeCoder.param_ins(param) + decl += "," + } + decl = decl[:decl.len-1] // Remove last comma. + } else { + decl += "void" + } + decl += ")" + ret decl + } + + // Generates C++ code of Fn TypeKind. + static fn func(mut f: &FnIns): str { + let mut obj = TypeCoder.Fn + "<" + obj += TypeCoder.anon_func(f) + obj += ">" + ret obj + } + + // Generates C++ code of TypeKind. + static fn kind(mut k: &TypeKind): str { + match { + | k.cpp_linked(): + ret k.cpp_ident + | k.prim() != nil: + ret TypeCoder.prim(k.prim()) + | k.tup() != nil: + ret TypeCoder.tuple(k.tup()) + | k.sptr() != nil: + ret TypeCoder.sptr(k.sptr()) + | k.ptr() != nil: + ret TypeCoder.ptr(k.ptr()) + | k.enm() != nil: + ret TypeCoder.enum_decl(k.enm()) + | k.slc() != nil: + ret TypeCoder.slice(k.slc()) + | k.map() != nil: + ret TypeCoder.map(k.map()) + | k.trt() != nil: + ret TypeCoder.trait_decl(k.trt()) + | k.strct() != nil: + ret TypeCoder.structure_ins(k.strct()) + | k.arr() != nil: + ret TypeCoder.array(k.arr()) + | k.fnc() != nil: + ret TypeCoder.func(k.fnc()) + } + match type k.kind { + | &CustomType: + ret (&CustomType)(k.kind).kind + |: + ret "[]" + } + } +} + +// Returns directive if exist. +fn find_directive(mut &directives: []&ast::Directive, tag: str): &ast::Directive { + for (_, mut dr) in directives { + if dr.tag.kind == tag { + ret dr + } + } + ret nil +} + +// Reports whether directive is exist. +fn has_directive(&directives: []&ast::Directive, tag: str): bool { + ret find_directive(unsafe { *(&directives) }, tag) != nil +} From ad4849f4b36d60c1e3cbe14f1178d9b05a28b705 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 18:55:24 +0300 Subject: [PATCH 05/17] compiler: add code generation for trait declarations --- src/julec/obj/cxx/object.jule | 38 ++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 6635eae4c..661967b8e 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -55,6 +55,9 @@ pub struct ObjectCoder { info: SerializationInfo f: &File tmap: []&TraitHash + + // Current indentation. + indent_buffer: []byte } impl ObjectCoder { @@ -71,6 +74,22 @@ impl ObjectCoder { _ = self.f.write([]byte(s))! } + // Increase indentation. + fn add_indent(mut &self) { + const INDENT_KIND = '\t' + self.indent_buffer = append(self.indent_buffer, INDENT_KIND) + } + + // Decrase indentation. + fn done_indent(mut &self) { + self.indent_buffer = self.indent_buffer[:self.indent_buffer.len-1] + } + + // Returns indention string by indent_buffer. + fn indent(mut &self) { + _ = self.f.write(self.indent_buffer)! + } + fn head(mut &self) { let time = Time.now() let abs = time.abs() @@ -161,8 +180,24 @@ impl ObjectCoder { }) } + fn trait_decls(mut &self) { + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut t) in file.traits { + if t.token == nil { + ret + } + self.indent() + self.write("struct ") + self.write(IdentCoder.trait_decl(t)) + self.write("{};\n") + } + }) + }) + } + fn decls(mut &self) { - + self.trait_decls() } pub fn serialize(mut &self) { @@ -170,6 +205,7 @@ impl ObjectCoder { self.build_trait_map() self.head() self.links() + self.write("\n") self.decls() } } From 6d255414854337348df17b16d1f2cf46f972d13f Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 18:59:56 +0300 Subject: [PATCH 06/17] compiler: add code generation for plain structure declarations --- src/julec/obj/cxx/object.jule | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 661967b8e..27ff06040 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -135,7 +135,7 @@ impl ObjectCoder { |: self.write("#include \"") self.write(used.path) - self.write("\n") + self.write("\"\n") } } } @@ -196,8 +196,25 @@ impl ObjectCoder { }) } + fn structure_plain_decl(mut &self, mut &s: &Struct) { + for (_, mut ins) in s.instances { + self.write("struct ") + self.write(IdentCoder.structure_ins(ins)) + self.write(";\n") + } + } + + fn structure_plain_decls(mut &self) { + for (_, mut s) in self.ir.ordered.structs { + if !s.cpp_linked && s.token != nil { + self.structure_plain_decl(s) + } + } + } + fn decls(mut &self) { self.trait_decls() + self.structure_plain_decls() } pub fn serialize(mut &self) { From 6be3884851a748291263a46fb2a0f73cbed5ffd3 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 19:31:39 +0300 Subject: [PATCH 07/17] compiler: add structure declaration code generation --- src/julec/obj/cxx/derive.jule | 22 +++ src/julec/obj/cxx/expr.jule | 234 ++++++++++++++++++++++++ src/julec/obj/cxx/object.jule | 329 ++++++++++++++++++++++++++++++++++ 3 files changed, 585 insertions(+) create mode 100644 src/julec/obj/cxx/derive.jule create mode 100644 src/julec/obj/cxx/expr.jule diff --git a/src/julec/obj/cxx/derive.jule b/src/julec/obj/cxx/derive.jule new file mode 100644 index 000000000..64fd72fe1 --- /dev/null +++ b/src/julec/obj/cxx/derive.jule @@ -0,0 +1,22 @@ +// Copyright 2023-2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use std::jule::sema::{Struct} + +struct DeriveCoder {} + +impl DeriveCoder { + static fn clone_func_decl(&s: &Struct): str { + let mut obj = TypeCoder.structure(s) + obj += " clone(void) const " + ret obj + } + + static fn clone_func_def(&s: &Struct): str { + let mut obj = TypeCoder.structure(s) + obj += " " + obj + obj += "::clone(void) const " + ret obj + } +} \ No newline at end of file diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule new file mode 100644 index 000000000..7e0c606f9 --- /dev/null +++ b/src/julec/obj/cxx/expr.jule @@ -0,0 +1,234 @@ +// Copyright 2023-2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use env +use optimizing::{ + UnsafeBinopExprModel, + UnsafeIndexingExprModel, + PushToSliceExprModel, + MutSlicingExprModel, + StrInsertBeginExprModel, +} +use conv for std::conv +use std::env::{ARCH} +use fmt for std::fmt +use std::jule::build::{Directive, is_64bit} +use std::jule::constant::{Const} +use std::jule::lex::{Token, TokenKind} +use std::jule::sema::{ + Var, + Struct, + FnIns, + Trait, + StructIns, + TypeKind, + Data, + Value, + ExprModel, + BinopExprModel, + UnaryExprModel, + StructLitExprModel, + AllocStructLitExprModel, + CastingExprModel, + FnCallExprModel, + SliceExprModel, + IndexingExprModel, + AnonFnExprModel, + MapExprModel, + SlicingExprModel, + TraitSubIdentExprModel, + StructSubIdentExprModel, + ArrayExprModel, + CommonIdentExprModel, + CommonSubIdentExprModel, + TupleExprModel, + BuiltinOutCallExprModel, + BuiltinOutlnCallExprModel, + BuiltinCloneCallExprModel, + BuiltinNewCallExprModel, + BuiltinPanicCallExprModel, + BuiltinAssertCallExprModel, + BuiltinMakeCallExprModel, + BuiltinAppendCallExprModel, + BuiltinErrorCallExprModel, + SizeofExprModel, + AlignofExprModel, + RuneExprModel, + StructStaticIdentExprModel, + IntegratedToStrExprModel, + BackendEmitExprModel, + FreeExprModel, + OperandExprModel, + Scope, +} +use types for std::jule::types::{ + MAX_F32, + MAX_F64, + MIN_F32, + MIN_F64, + MAX_I64, + MIN_I64, + MAX_U64, +} +use math for std::math +use strings for std::strings +use utf8 for std::unicode::utf8 + +// Ignore expression for std::tie function. +const CPP_IGNORE = "std::ignore" + +// Represents default expression for type. +const CPP_DEFAULT_EXPR = "{}" + +struct ExprCoder { + oc: &ObjectCoder +} + +impl ExprCoder { + static fn new(mut &oc: &ObjectCoder): &ExprCoder { + ret &ExprCoder{ + oc: oc, + } + } + + fn expr(mut &self, mut e: ExprModel) { + } + + fn val(mut &self, mut v: &Value) { + } + + fn init_expr(mut &self, mut t: &TypeKind) { + } +} + +fn decompose_common_esq(b: byte): str { + match b { + | '\\': + ret "\\\\" + | '\'': + ret "'" + | '"': + ret `\"` + | '\a': + ret `\a` + | '\b': + ret `\b` + | '\f': + ret `\f` + | '\n': + ret `\n` + | '\r': + ret `\r` + | '\t': + ret `\t` + | '\v': + ret `\v` + |: + ret "" + } +} + +fn sbtoa(b: byte): str { + if b == 0 { + ret "\\x00" + } + if b < utf8::RUNE_SELF { // ASCII, fast way. + let seq = decompose_common_esq(b) + if seq != "" { + ret seq + } + if 32 <= b && b <= 126 { + ret str(b) + } + } + let seq = conv::fmt_uint(u64(b), 8) + if seq.len == 2 { + ret "\\0" + seq + } + ret "\\" + seq +} + +fn cstr_bytes(bytes: []byte): str { + let mut lit = "" + for _, b in bytes { + lit += sbtoa(b) + } + ret lit +} + +fn cstr_lit(bytes: []byte): str { + ret `"` + cstr_bytes(bytes) + `"` +} + +fn ftoa(f: f64, bitsize: int): str { + if bitsize != 32 { + if f == f64(i64(f)) { + ret itoa(i64(f)) + } + if f == f64(u64(f)) { + ret utoa(u64(f)) + } + } + let mut m = conv::fmt_float(f, 'f', -1, bitsize) + if !strings::contains(m, ".") { + m += ".0" + } + ret m +} + +fn itoa(x: i64): str { + match { + | x == MAX_I64: + ret "jule::MAX_I64" + | x == MIN_I64: + ret "jule::MIN_I64" + } + + let fmt = conv::fmt_int(x, 10) + if is_64bit(ARCH) { + ret fmt + "LL" + } + ret fmt + "L" +} + +fn utoa(x: u64): str { + match { + | x == MAX_U64: + ret "jule::MAX_U64" + } + + let fmt = conv::fmt_uint(x, 10) + if is_64bit(ARCH) { + ret fmt + "LLU" + } + ret fmt + "LU" +} + +fn is_forwarded(&s: &Scope): bool { + let last = s.stmts[s.stmts.len-1] + match type last { + | &Data: + match type (&Data)(last).model { + | &BuiltinErrorCallExprModel: + ret true + |: + ret false + } + |: + ret true + } +} + +fn is_builtin_call_has_debuginf(&m: &FnCallExprModel): bool { + if !m.func.is_builtin() { + ret false + } + match type m.expr { + | &CommonSubIdentExprModel: + let csie = (&CommonSubIdentExprModel)(m.expr) + ret csie.ident == "swap" + |: + ret false + } +} \ No newline at end of file diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 27ff06040..dbb5fb5a4 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -58,6 +58,8 @@ pub struct ObjectCoder { // Current indentation. indent_buffer: []byte + + ec: &ExprCoder } impl ObjectCoder { @@ -67,6 +69,7 @@ impl ObjectCoder { info: info, f: f, } + oc.ec = ExprCoder.new(oc) ret oc } @@ -212,9 +215,335 @@ impl ObjectCoder { } } + fn field_decl(mut &self, mut &f: &FieldIns) { + self.write(TypeCoder.kind(f.kind)) + self.write(" ") + self.write(IdentCoder.field(f.decl)) + self.write(" = ") + if f.default == nil { + // No default expression. + // Use default expression of data-type. + self.ec.init_expr(f.kind) + } else { + self.ec.expr(f.default.model) + } + self.write(";") + } + + fn structure_constructor(mut &self, mut &s: &StructIns) { + self.write(IdentCoder.structure_ins(s)) + self.write("(") + if s.fields.len > 0 { + for (i, mut f) in s.fields { + self.write(TypeCoder.kind(f.kind)) + self.write(" __param_") + self.write(f.decl.ident) + if s.fields.len - i > 1 { + self.write(", ") + } + } + } else { + self.write("void") + } + + self.write(")") + if s.fields.len > 0 { + self.write(": ") + for i, f in s.fields { + self.write(IdentCoder.field(f.decl)) + self.write("(") + self.write("__param_") + self.write(f.decl.ident) + self.write(")") + if s.fields.len - i > 1 { + self.write(", ") + } + } + } + self.write(" {}") + } + + fn structure_destructor(mut &self, mut &s: &StructIns) { + const STATIC = false // Dispose method must be non-static + let dispose_method = s.find_method("dispose", STATIC) + let mut disposed = FuncPattern.dispose(dispose_method) + // Call destructor if implemented. + if !disposed { + ret + } + self.write("~") + self.write(IdentCoder.structure_ins(s)) + self.write("(void) { ") + self.write(IdentCoder.func(dispose_method)) + self.write("(this); }") + } + + fn structure_derive_defs_decls(mut &self, &s: &StructIns) { + if s.decl.is_derives(Derive.Clone) { + self.indent() + self.write(DeriveCoder.clone_func_decl(s.decl)) + self.write(";\n\n") + } + } + + fn structure_operator_eq(mut &self, &ident: str, mut &s: &StructIns) { + // Operator overloading. + if s.operators.eq != nil { + self.structure_operator(ident, s.operators.eq, "==") + ret + } + + self.indent() + if env::OPT_INLINE { + self.write("inline ") + } + self.write("bool operator==(") + self.write(ident) + self.write(" _other) {") + if s.fields.len > 0 { + self.add_indent() + self.write("\n") + self.indent() + self.write("return ") + self.add_indent() + let mut writed = false + for (_, mut f) in s.fields { + // Skip C++-linked struct kinds. + let strct = f.kind.strct() + if strct != nil && strct.decl != nil && strct.decl.cpp_linked { + continue + } + + if writed { + self.write(" &&") + } + writed = true + self.write("\n") + self.indent() + self.write("this->") + let f_ident = IdentCoder.field(f.decl) + self.write(f_ident) + self.write(" == _other.") + self.write(f_ident) + } + self.done_indent() + if !writed { + self.write("true") + } + self.write(";\n") + self.done_indent() + self.indent() + self.write("}") + } else { + self.write(" return true; }") + } + self.write("\n\n") + } + + fn structure_operator_not_eq(mut &self, &ident: str, mut &s: &StructIns) { + self.indent() + if env::OPT_INLINE { + self.write("inline ") + } + self.write("bool operator!=(") + self.write(ident) + self.write(" _other) { return !this->operator==(_other); }\n\n") + } + + // Write operator overloading forwarding for reserved function. + fn structure_operator(mut &self, &ident: str, mut &f: &FnIns, op: str) { + if f == nil { + ret + } + + let unary = f.params.len == 1 // Just self parameter. + let assignment = f.decl.is_void() + + self.indent() + if env::OPT_INLINE { + self.write("inline ") + } + if assignment { + self.write(ident) + self.write("&") + } else { + if f.result.prim() == nil { + // If result type is not primitive, always structure's itself. + self.write(ident) + } else { + // Logical. + self.write(TypeCoder.Bool) + } + } + self.write(" operator") + self.write(op) + self.write("(") + if !unary { + let mut p = f.params[1] + self.write(TypeCoder.param_ins(p)) + self.write(" _other") + } + self.write(") { ") + if !assignment { + self.write("return ") + } + self.write(IdentCoder.func_ins(f)) + if !unary { + self.write("(this, _other); ") + if assignment { + self.write("return *this; ") + } + self.write("}") + } else { + self.write("(this); }") + } + self.write("\n\n") + } + + fn structure_operators(mut &self, mut &s: &StructIns) { + let ident = IdentCoder.structure_ins(s) + + // Binary. + self.structure_operator_eq(ident, s) + self.structure_operator_not_eq(ident, s) + self.structure_operator(ident, s.operators.gt, ">") + self.structure_operator(ident, s.operators.gt_eq, ">=") + self.structure_operator(ident, s.operators.lt, "<") + self.structure_operator(ident, s.operators.lt_eq, "<=") + self.structure_operator(ident, s.operators.shl, "<<") + self.structure_operator(ident, s.operators.shr, ">>") + self.structure_operator(ident, s.operators.add, "+") + self.structure_operator(ident, s.operators.sub, "-") + self.structure_operator(ident, s.operators.div, "/") + self.structure_operator(ident, s.operators.mul, "*") + self.structure_operator(ident, s.operators.mod, "%") + self.structure_operator(ident, s.operators.bit_and, "&") + self.structure_operator(ident, s.operators.bit_or, "|") + self.structure_operator(ident, s.operators.bit_xor, "^") + + // Unary. + self.structure_operator(ident, s.operators.neg, "-") + self.structure_operator(ident, s.operators.pos, "+") + self.structure_operator(ident, s.operators.bit_not, "~") + + // Assignment. + self.structure_operator(ident, s.operators.add_assign, "+=") + self.structure_operator(ident, s.operators.sub_assign, "-=") + self.structure_operator(ident, s.operators.div_assign, "/=") + self.structure_operator(ident, s.operators.mul_assign, "*=") + self.structure_operator(ident, s.operators.mod_assign, "%=") + self.structure_operator(ident, s.operators.shl_assign, "<<=") + self.structure_operator(ident, s.operators.shr_assign, ">>=") + self.structure_operator(ident, s.operators.bit_or_assign, "|=") + self.structure_operator(ident, s.operators.bit_and_assign, "&=") + self.structure_operator(ident, s.operators.bit_xor_assign, "^=") + } + + fn structure_ins_decl(mut &self, mut &s: &StructIns) { + if s.methods.len > 0 { + for (_, mut m) in s.methods { + self.func_decl(m, false) + } + } + + self.write("struct ") + let out_ident = IdentCoder.structure_ins(s) + + self.write(out_ident) + self.write(" {\n") + + self.add_indent() + if s.fields.len > 0 { + for (_, mut f) in s.fields { + self.indent() + self.field_decl(f) + self.write("\n") + } + self.write("\n\n") + self.indent() + self.structure_constructor(s) + self.write("\n\n") + } + + self.indent() + self.structure_destructor(s) + self.write("\n\n") + + // Default constructor. + self.indent() + self.write(out_ident) + self.write("(void) = default;\n\n") + + self.structure_derive_defs_decls(s) + + self.structure_operators(s) + self.write("\n") + + self.done_indent() + self.indent() + self.write("};") + } + + fn structure_decl(mut &self, mut &s: &Struct) { + for (_, mut ins) in s.instances { + self.structure_ins_decl(ins) + } + } + + fn structure_decls(mut &self) { + for (_, mut s) in self.ir.ordered.structs { + if !s.cpp_linked && s.token != nil { + self.structure_decl(s) + self.write("\n") + } + } + } + + fn params_decls(mut &self, mut ¶ms: []&ParamIns) { + if params.len == 0 { + self.write("(void)") + ret + } + + self.write("(") + for (i, mut p) in params { + self.write(TypeCoder.param_ins(p)) + if params.len - i > 1 { + self.write(", ") + } + } + + self.write(")") + } + + fn func_head(mut &self, mut &f: &FnIns, ptr: bool) { + if !ptr && env::OPT_INLINE && !f.decl.is_entry_point() { + self.write("inline ") + } + self.write(TypeCoder.func_ins_result(f)) + if ptr { + self.write("(*") + self.write(IdentCoder.func_ins(f)) + self.write(")") + } else { + self.write(" ") + self.write(IdentCoder.func_ins(f)) + } + } + + fn func_decl(mut &self, mut &f: &Fn, ptr: bool) { + for (_, mut c) in f.instances { + self.indent() + self.func_head(c, ptr) + self.params_decls(c.params) + self.write(";\n") + } + } + fn decls(mut &self) { self.trait_decls() self.structure_plain_decls() + self.structure_decls() } pub fn serialize(mut &self) { From c48d8a8bce2c1b20ca34f4ebc2d8b7c9d099eea1 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 19:36:16 +0300 Subject: [PATCH 08/17] compiler: add function declaration code generation --- src/julec/obj/cxx/object.jule | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index dbb5fb5a4..72c5043c6 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -540,10 +540,23 @@ impl ObjectCoder { } } + fn func_decls(mut &self) { + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut f) in file.funcs { + if !f.cpp_linked && f.token != nil { + self.func_decl(f, false) + } + } + }) + }) + } + fn decls(mut &self) { self.trait_decls() self.structure_plain_decls() self.structure_decls() + self.func_decls() } pub fn serialize(mut &self) { From 7656ef7443e44c98a340da24a231ad9067aca30a Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 20:23:52 +0300 Subject: [PATCH 09/17] compiler: code generation support for traits --- src/julec/obj/cxx/expr.jule | 9 +- src/julec/obj/cxx/object.jule | 180 +++++++++++++++++++++++++++++++++- src/julec/obj/cxx/scope.jule | 76 ++++++++++++++ src/julec/obj/cxx/type.jule | 2 +- 4 files changed, 256 insertions(+), 11 deletions(-) create mode 100644 src/julec/obj/cxx/scope.jule diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule index 7e0c606f9..696979cd2 100644 --- a/src/julec/obj/cxx/expr.jule +++ b/src/julec/obj/cxx/expr.jule @@ -92,14 +92,11 @@ impl ExprCoder { } } - fn expr(mut &self, mut e: ExprModel) { - } + fn expr(mut &self, mut e: ExprModel) {} - fn val(mut &self, mut v: &Value) { - } + fn val(mut &self, mut v: &Value) {} - fn init_expr(mut &self, mut t: &TypeKind) { - } + fn init_expr(mut &self, mut t: &TypeKind) {} } fn decompose_common_esq(b: byte): str { diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 72c5043c6..12b3b9927 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -60,6 +60,7 @@ pub struct ObjectCoder { indent_buffer: []byte ec: &ExprCoder + sc: &ScopeCoder } impl ObjectCoder { @@ -70,6 +71,7 @@ impl ObjectCoder { f: f, } oc.ec = ExprCoder.new(oc) + oc.sc = ScopeCoder.new(oc) ret oc } @@ -238,7 +240,7 @@ impl ObjectCoder { self.write(TypeCoder.kind(f.kind)) self.write(" __param_") self.write(f.decl.ident) - if s.fields.len - i > 1 { + if s.fields.len-i > 1 { self.write(", ") } } @@ -255,7 +257,7 @@ impl ObjectCoder { self.write("__param_") self.write(f.decl.ident) self.write(")") - if s.fields.len - i > 1 { + if s.fields.len-i > 1 { self.write(", ") } } @@ -316,7 +318,7 @@ impl ObjectCoder { if writed { self.write(" &&") - } + } writed = true self.write("\n") self.indent() @@ -508,7 +510,7 @@ impl ObjectCoder { self.write("(") for (i, mut p) in params { self.write(TypeCoder.param_ins(p)) - if params.len - i > 1 { + if params.len-i > 1 { self.write(", ") } } @@ -552,11 +554,181 @@ impl ObjectCoder { }) } + fn trait_data_types(mut &self) { + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut t) in file.traits { + if t.token == nil { + ret + } + self.write("struct ") + self.write(IdentCoder.trait_decl(t)) + self.write("MptrData") + self.write(" {\n") + self.add_indent() + for (_, mut m) in t.methods { + let mut ins = m.instances[0] + let mut p = ins.params[0] + p.kind = &TypeKind{ + kind: t, + } + for (i, mut ip) in ins.params[1:] { + if is_anon_ident(ip.decl.ident) { + ip.decl.ident = "_" + conv::itoa(i) + } + } + if !env::PRODUCTION { + ins.params = append(ins.params, &ParamIns{ + decl: &Param{ + ident: "__file", + }, + kind: &TypeKind{ + kind: &CustomType{ + kind: "const char*", + }, + }, + }) + } + self.func_decl(m, true) + } + self.done_indent() + self.indent() + self.write("};\n\n") + } + }) + }) + } + + fn param_ins(mut &self, mut &p: &ParamIns) { + self.write(TypeCoder.param_ins(p)) + self.write(" ") + self.write(IdentCoder.param(p.decl)) + } + + fn params_ins(mut &self, mut ¶ms: []&ParamIns) { + if params.len == 0 { + self.write("(void)") + ret + } + self.write("(") + for (i, mut p) in params { + self.param_ins(p) + if params.len - i > 1 { + self.write(", ") + } + } + self.write(")") + } + + fn func(mut &self, mut &f: &Fn) { + for (_, mut ins) in f.instances { + self.func_head(ins, false) + self.params_ins(ins.params) + self.write(" ") + self.sc.func_scope(ins) + if ins.scope != nil { + self.write("\n\n") + } + } + } + + fn trait_wrappers(mut &self) { + for (_, mut hash) in self.tmap { + for (_, mut m) in hash.t.methods { + let ident = m.ident + m.instances[0].scope = nil + let ptr = !m.params[0].is_ref() + + let mut sm = hash.s.find_method(m.ident, false) + if sm == nil || sm.instances.len == 0 { + continue + } + + m.ident = ident + "_" + conv::itoa(hash.i) + self.func(m) + m.ident = ident + self.add_indent() + self.write("{\n") + self.indent() + if !sm.is_void() { + self.write("return ") + } + self.write(IdentCoder.func(sm)) + self.write("(") + if ptr { + self.write("_self_.safe_ptr<") + self.write(TypeCoder.structure_ins(hash.s)) + self.write(">(") + if !env::PRODUCTION { + self.write("_00___file") + } + self.write(")") + } else { + self.write("_self_.data.as<") + self.write(TypeCoder.structure(sm.owner)) + self.write(">()") + } + for _, mp in m.params[1:] { + self.write(", ") + self.write(IdentCoder.param(mp)) + } + self.write(");\n}\n") + self.done_indent() + } + } + } + + fn trait_datas(mut &self) { + let mut old: &Trait = nil + for (_, mut hash) in self.tmap { + let ident = IdentCoder.trait_decl(hash.t) + if hash.t != old { + if old != nil { + self.done_indent() + self.indent() + self.write("};\n") + } + self.write("static ") + self.write(ident) + self.write("MptrData ") + self.write(ident) + self.write("_mptr_data[] = {\n") + old = hash.t + self.add_indent() + } + self.indent() + self.write("{\n") + self.add_indent() + for (_, mut m) in hash.t.methods { + let m_ident = IdentCoder.func(m) + self.indent() + self.write(".") + self.write(m_ident) + self.write("=") + self.write(m_ident) + self.write("_") + self.write(conv::itoa(hash.i)) + self.write(",\n") + } + self.done_indent() + self.indent() + self.write("},\n") + } + if old != nil { + self.done_indent() + self.indent() + self.write("};\n") + } + } + fn decls(mut &self) { self.trait_decls() self.structure_plain_decls() self.structure_decls() self.func_decls() + self.trait_data_types() + self.trait_wrappers() + self.trait_datas() } pub fn serialize(mut &self) { diff --git a/src/julec/obj/cxx/scope.jule b/src/julec/obj/cxx/scope.jule new file mode 100644 index 000000000..5087db4f4 --- /dev/null +++ b/src/julec/obj/cxx/scope.jule @@ -0,0 +1,76 @@ +// Copyright 2023-2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use env +use optimizing::{ + PushToSliceExprModel, + MutSlicingExprModel, + StrInsertBeginExprModel, +} +use lex for std::jule::lex::{TokenKind} +use std::jule::sema::{ + Data, + St, + FnIns, + Var, + Scope, + If, + Conditional, + InfIter, + WhileIter, + RangeIter, + ContSt, + BreakSt, + Label, + GotoSt, + Postfix, + Assign, + MultiAssign, + Match, + Case, + FallSt, + RetSt, + TupleExprModel, + TypeKind, + BuiltinAppendCallExprModel, + SlicingExprModel, +} + +const MATCH_EXPR = "_match_expr" + +struct ScopeCoder { + oc: &ObjectCoder +} + +impl ScopeCoder { + static fn new(mut &oc: &ObjectCoder): &ScopeCoder { + ret &ScopeCoder{ + oc: oc, + } + } + + fn scope(mut &self, mut s: &Scope) { + } + + fn func_scope(mut &self, mut f: &FnIns) { + } +} + +fn is_copy_optimizable(&expr: &Data): bool { + if !expr.lvalue { + ret false + } + match type expr.model { + | &SlicingExprModel: + ret false + } + ret true +} + +fn is_iter_copy_optimizable(&expr: &Data, &v: &Var): bool { + if !expr.lvalue && !expr.kind.mutable() { + ret true + } + ret !v.mutable && !expr.mutable +} \ No newline at end of file diff --git a/src/julec/obj/cxx/type.jule b/src/julec/obj/cxx/type.jule index 6da2c7e9e..84394085c 100644 --- a/src/julec/obj/cxx/type.jule +++ b/src/julec/obj/cxx/type.jule @@ -327,4 +327,4 @@ fn find_directive(mut &directives: []&ast::Directive, tag: str): &ast::Directive // Reports whether directive is exist. fn has_directive(&directives: []&ast::Directive, tag: str): bool { ret find_directive(unsafe { *(&directives) }, tag) != nil -} +} \ No newline at end of file From 16dddad1c49973b4f79ac9c6d0747d6f4c802470 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 20:29:33 +0300 Subject: [PATCH 10/17] compiler: add code generation support for globals --- src/julec/obj/cxx/object.jule | 29 ++++++++++++++++++++++++++++- src/julec/obj/cxx/scope.jule | 6 ++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 12b3b9927..3625a062a 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -613,7 +613,7 @@ impl ObjectCoder { self.write("(") for (i, mut p) in params { self.param_ins(p) - if params.len - i > 1 { + if params.len-i > 1 { self.write(", ") } } @@ -721,14 +721,40 @@ impl ObjectCoder { } } + fn globals(mut &self) { + self.add_indent() // For global initializers's function indentation. + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut v) in file.vars { + if v.token == nil || v.cpp_linked || v.constant { + ret + } + self.write(TypeCoder.kind(v.kind.kind)) + self.write(" ") + if v.reference { + self.write("&") + } + self.write(IdentCoder.var(v)) + self.write(";\n") + } + }) + }) + self.done_indent() + } + fn decls(mut &self) { self.trait_decls() self.structure_plain_decls() self.structure_decls() self.func_decls() + self.write("\n\n") self.trait_data_types() + self.write("\n\n") self.trait_wrappers() + self.write("\n\n") self.trait_datas() + self.write("\n\n") + self.globals() } pub fn serialize(mut &self) { @@ -738,6 +764,7 @@ impl ObjectCoder { self.links() self.write("\n") self.decls() + self.write("\n") } } diff --git a/src/julec/obj/cxx/scope.jule b/src/julec/obj/cxx/scope.jule index 5087db4f4..c8dbe63e1 100644 --- a/src/julec/obj/cxx/scope.jule +++ b/src/julec/obj/cxx/scope.jule @@ -50,11 +50,9 @@ impl ScopeCoder { } } - fn scope(mut &self, mut s: &Scope) { - } + fn scope(mut &self, mut s: &Scope) {} - fn func_scope(mut &self, mut f: &FnIns) { - } + fn func_scope(mut &self, mut f: &FnIns) {} } fn is_copy_optimizable(&expr: &Data): bool { From e2117aa3e2dba090911a9da9777de95fa1c079f2 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 20:41:34 +0300 Subject: [PATCH 11/17] compiler: code generation support for structures --- src/julec/obj/cxx/object.jule | 109 +++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 3625a062a..6beb8b68e 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -722,7 +722,6 @@ impl ObjectCoder { } fn globals(mut &self) { - self.add_indent() // For global initializers's function indentation. self.iter_packages(fn(mut &pkg: &Package) { iter_files(pkg, fn(mut &file: &SymbolTable) { for (_, mut v) in file.vars { @@ -739,7 +738,6 @@ impl ObjectCoder { } }) }) - self.done_indent() } fn decls(mut &self) { @@ -756,6 +754,112 @@ impl ObjectCoder { self.write("\n\n") self.globals() } + + fn structure_methods(mut &self, mut &s: &StructIns) { + for (_, mut f) in s.methods { + self.func(f) + self.write("\n\n") + } + } + + fn structure_derive_defs(mut &self, mut &s: &StructIns) { + if s.decl.is_derives(Derive.Clone) { + self.write(DeriveCoder.clone_func_def(s.decl)) + self.write("{\n") + self.add_indent() + self.indent() + self.write(TypeCoder.structure_ins(s)) + self.write(" clone;\n") + for _, f in s.fields { + let ident = IdentCoder.field(f.decl) + self.indent() + self.write("clone.") + self.write(ident) + self.write(" = jule::clone(this->") + self.write(ident) + self.write(");\n") + } + self.indent() + self.write("return clone;\n") + self.done_indent() + self.write("}") + } + } + + fn structure_ostream(mut &self, mut &s: &StructIns) { + self.indent() + self.write("std::ostream &operator<<(std::ostream &_Stream, ") + self.write(IdentCoder.structure_ins(s)) + self.write(" _Src) {\n") + self.add_indent() + self.indent() + + let mut fts = s.find_method("to_str", false) + if FuncPattern.to_str(fts) { + self.write("_Stream << ") + self.write(IdentCoder.func(fts)) + self.write("(&_Src);\n") + } else { + self.write(`_Stream << "`) + self.write(s.decl.ident) + self.write("{\";\n") + + for (i, mut f) in s.fields { + self.indent() + self.write(`_Stream << "`) + self.write(f.decl.ident) + self.write(`:`) + + // Skip C++-linked struct kinds. + let strct = f.kind.strct() + if strct != nil && strct.decl != nil && strct.decl.cpp_linked { + self.write(` cpp.`) + self.write(IdentCoder.field(f.decl)) + self.write(`"`) + } else { + self.write(`" << _Src.`) + self.write(IdentCoder.field(f.decl)) + } + if i+1 < s.fields.len { + self.write(" << \", \"") + } + self.write(";\n") + } + + self.indent() + self.write("_Stream << \"}\";\n") + } + + self.indent() + self.write("return _Stream;\n") + + self.done_indent() + self.write("}") + } + + fn structure_ins(mut &self, mut &s: &StructIns) { + self.structure_methods(s) + self.write("\n\n") + self.structure_derive_defs(s) + self.write("\n\n") + self.structure_ostream(s) + } + + fn structure(mut &self, mut &s: &Struct) { + for (_, mut ins) in s.instances { + self.structure_ins(ins) + self.write("\n\n") + } + } + + fn structures(mut &self) { + for (_, mut s) in self.ir.ordered.structs { + if !s.cpp_linked && s.token != nil { + self.structure(s) + self.write("\n\n") + } + } + } pub fn serialize(mut &self) { self.prepare_structures() @@ -765,6 +869,7 @@ impl ObjectCoder { self.write("\n") self.decls() self.write("\n") + self.structures() } } From e5d6464233e570ba4547334e695c340a67f431d3 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 20:45:27 +0300 Subject: [PATCH 12/17] compiler: code generation support for functions --- src/julec/obj/cxx/object.jule | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 6beb8b68e..ab39b7df2 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -754,7 +754,7 @@ impl ObjectCoder { self.write("\n\n") self.globals() } - + fn structure_methods(mut &self, mut &s: &StructIns) { for (_, mut f) in s.methods { self.func(f) @@ -861,6 +861,22 @@ impl ObjectCoder { } } + fn funcs(mut &self) { + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut f) in file.funcs { + if !env::TEST && has_directive(f.directives, Directive.Test) { + continue + } + if !f.cpp_linked && f.token != nil { + self.func(f) + self.write("\n\n") + } + } + }) + }) + } + pub fn serialize(mut &self) { self.prepare_structures() self.build_trait_map() @@ -870,6 +886,7 @@ impl ObjectCoder { self.decls() self.write("\n") self.structures() + self.funcs() } } From 8eafd84ae8ce91cd462f6b5e5ac678cfa048d91c Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 21:01:48 +0300 Subject: [PATCH 13/17] compiler: complete essentially the object code generation without scope and expressions --- src/julec/obj/cxx/object.jule | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index ab39b7df2..d9fde1fac 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -877,6 +877,73 @@ impl ObjectCoder { }) } + fn push_init(mut &self, mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for _, f in file.funcs { + if f.ident == build::INIT_FN { + self.indent() + self.write(IdentCoder.func(f)) + self.write("();\n") + } + } + }) + } + + fn global_initializers(mut &self) { + self.iter_packages(fn(mut &pkg: &Package) { + iter_files(pkg, fn(mut &file: &SymbolTable) { + for (_, mut v) in file.vars { + if v.token == nil || v.cpp_linked || v.constant { + ret + } + self.indent() + self.write(IdentCoder.var(v)) + if v.value != nil && v.value.expr != nil { + if v.value.data.model != nil { + self.write(" = ") + self.ec.val(v.value) + } + } else { + self.write(" = ") + self.ec.init_expr(v.kind.kind) + } + self.write(";\n") + } + }) + }) + } + + fn init_caller(mut &self) { + self.write("void " + INIT_CALLER_IDENT + "(void) {\n") + self.add_indent() + self.global_initializers() + self.iter_packages(fn(mut &pkg: &Package) { + self.push_init(pkg) + }) + self.done_indent() + self.write("\n}") + } + + fn end(mut &self) { + self.write(`int main(int argc, char *argv[], char *envp[]) { + jule::setup_argv(argc, argv); + jule::setup_envp(envp); + + __jule_call_initializers(); + `) + + if env::TEST { + self.write("test_point();") + } else { + self.write("entry_point();") + } + + self.write(` + + return EXIT_SUCCESS; +}`) + } + pub fn serialize(mut &self) { self.prepare_structures() self.build_trait_map() @@ -887,6 +954,9 @@ impl ObjectCoder { self.write("\n") self.structures() self.funcs() + self.init_caller() + self.write("\n\n") + self.end() } } From 21df1922de1268d2174161b211cf3fe6b3656515 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Wed, 3 Apr 2024 23:11:21 +0300 Subject: [PATCH 14/17] compiler: use old implementations as temporary algorithm --- src/julec/compile.jule | 6 + src/julec/obj/cxx/expr.jule | 1051 ++++++++++++++++++++++++++++++++- src/julec/obj/cxx/object.jule | 114 +++- src/julec/obj/cxx/scope.jule | 723 ++++++++++++++++++++++- 4 files changed, 1868 insertions(+), 26 deletions(-) diff --git a/src/julec/compile.jule b/src/julec/compile.jule index 2c26bb48f..41ba9b856 100644 --- a/src/julec/compile.jule +++ b/src/julec/compile.jule @@ -433,4 +433,10 @@ fn compile_command(mut &args: []str) { compiler_command: compiler_cmd, }) oc.serialize() + + file.close()! + + if !env::TRANSPILATION { + compile_ir(compiler, compiler_cmd) + } } \ No newline at end of file diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule index 696979cd2..161046cdc 100644 --- a/src/julec/obj/cxx/expr.jule +++ b/src/julec/obj/cxx/expr.jule @@ -92,11 +92,1054 @@ impl ExprCoder { } } - fn expr(mut &self, mut e: ExprModel) {} + fn string(self, &c: &Const): str { + let content = c.read_str() + if content.len == 0 { // Empty. + ret TypeCoder.Str + "()" + } + let bytes = []byte(content) + let len = conv::fmt_int(i64(bytes.len), 10) + let lit = cstr_lit(bytes) + ret TypeCoder.Str + "(" + lit + ", " + len + ")" + } + + fn boolean(self, &c: &Const): str { + if c.read_bool() { + ret "true" + } + ret "false" + } + + fn nil_lit(self): str { + ret "nullptr" + } + + fn ftoa_special_cases(self, &x: f64): str { + match { + | math::is_nan(x): + ret "NAN" + | math::is_inf(x, 1): + ret "INFINITY" + | math::is_inf(x, -1): + ret "-INFINITY" + |: + ret "" + } + } + + fn float32(self, &c: &Const): str { + let x = c.as_f64() + + // Special cases. + let f = self.ftoa_special_cases(x) + if f != "" { + ret f + } + + match { + | x == MAX_F32: + ret "jule::MAX_F32" + | x == MIN_F32: + ret "jule::MIN_F32" + |: + ret ftoa(x, 32) + "f" + } + } + + fn float64(self, &c: &Const): str { + let x = c.as_f64() + + // Special cases. + let f = self.ftoa_special_cases(x) + if f != "" { + ret f + } + + match { + | x == MAX_F64: + ret "jule::MAX_F64" + | x == MIN_F64: + ret "jule::MIN_F64" + |: + ret ftoa(x, 64) + } + } + + // fx32: 32-bit floating-point + fn constant(self, mut c: &Const, fx32: bool): str { + match { + | c.is_str(): + ret self.string(c) + | c.is_bool(): + ret self.boolean(c) + | c.is_f64(): + match { + | fx32: + ret self.float32(c) + |: + ret self.float64(c) + } + | c.is_i64(): + ret itoa(c.read_i64()) + | c.is_u64(): + ret utoa(c.read_u64()) + | c.is_nil(): + ret self.nil_lit() + |: + ret "" + } + } + + fn div_by_zero_binary(mut self, &op: &Token, mut &l: &OperandExprModel, mut &r: &OperandExprModel): str { + let mut op_func = "" + match op.kind { + | TokenKind.Solidus + | TokenKind.SolidusEq: + op_func = "div" + | TokenKind.Percent + | TokenKind.PercentEq: + op_func = "mod" + } + + let mut obj = "jule::" + obj += op_func + obj += "(" + if !env::PRODUCTION { + obj += "\"" + obj += self.oc.loc_info(op) + obj += "\"," + } + obj += self.expr(l.model) + obj += "," + obj += self.expr(r.model) + obj += ")" + ret obj + } + + fn unsafe_binary(mut self, mut m: &BinopExprModel): str { + let mut obj = "(" + obj += self.model(m.left.model) + obj += " " + obj += m.op.kind + obj += " " + obj += self.model(m.right.model) + obj += ")" + ret obj + } + + fn binary(mut self, mut m: &BinopExprModel): str { + match m.op.kind { + | TokenKind.Solidus | TokenKind.Percent: + // Do not check division of structures safety. + if m.left.kind.strct() == nil { + ret self.div_by_zero_binary(m.op, m.left, m.right) + } + } + ret self.unsafe_binary(m) + } + + fn var(self, mut m: &Var): str { + if m.cpp_linked { + let d = find_directive(m.directives, Directive.Namespace) + if d != nil { + let mut obj = concat_all_parts(d.args...) + obj += "::" + obj += IdentCoder.var(m) + ret obj + } + } + ret IdentCoder.var(m) + } + + fn structure(self, m: &Struct): str { + ret TypeCoder.structure(m) + } + + fn structure_ins(self, mut m: &StructIns): str { + ret TypeCoder.structure_ins(m) + } + + fn unary(mut self, mut m: &UnaryExprModel): str { + match m.op.kind { + | TokenKind.Caret: + let mut obj = "(~(" + obj += self.expr(m.expr.model) + obj += "))" + ret obj + | TokenKind.Star: + if env::PRODUCTION || m.expr.kind.sptr() == nil { + break + } + let mut obj = self.expr(m.expr.model) + obj += ".get(\"" + obj += self.oc.loc_info(m.op) + obj += "\")" + ret obj + } + + let mut obj = "(" + obj += m.op.kind + obj += "(" + obj += self.expr(m.expr.model) + obj += "))" + ret obj + } + + fn cpp_structure_lit(mut self, mut m: &StructLitExprModel): str { + let mut obj = "(" + TypeCoder.structure_ins(m.strct) + obj += "){" + if m.args.len > 0 { + iter: + for (_, mut f) in m.strct.fields { + if m.strct.decl.cpp_linked { + for (_, mut arg) in m.args { + if arg.field == f { + obj += "." + obj += IdentCoder.field(f.decl) + obj += "=" + obj += self.expr(arg.expr) + obj += "," + continue iter + } + } + continue + } + obj += IdentCoder.field(f.decl) + obj += ": " + for (_, mut arg) in m.args { + if arg.field == f { + obj += self.expr(arg.expr) + obj += "," + continue iter + } + } + obj += self.init_expr(f.kind) + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + } + obj += "}" + ret obj + } + + fn structure_lit(mut self, mut m: &StructLitExprModel): str { + if m.strct.decl.cpp_linked { + ret self.cpp_structure_lit(m) + } + + let mut obj = IdentCoder.structure_ins(m.strct) + obj += "(" + if m.args.len > 0 { + iter: + for (_, mut f) in m.strct.fields { + for (_, mut arg) in m.args { + if arg.field == f { + obj += self.expr(arg.expr) + obj += "," + continue iter + } + } + obj += self.init_expr(f.kind) + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + } + obj += ")" + ret obj + } + + fn alloc_structure(mut self, mut m: &AllocStructLitExprModel): str { + let mut obj = "jule::new_ptr<" + obj += IdentCoder.structure_ins(m.lit.strct) + obj += ">(" + obj += self.structure_lit(m.lit) + obj += ")" + ret obj + } + + fn casting(mut self, mut m: &CastingExprModel): str { + let mut obj = "" + match { + | m.kind.prim() != nil && m.kind.prim().is_any(): + obj += TypeCoder.kind(m.kind) + obj += "(" + obj += self.model(m.expr) + obj += ")" + | m.expr_kind.ptr() != nil + | m.kind.ptr() != nil: + obj += "((" + obj += TypeCoder.kind(m.kind) + obj += ")(" + obj += self.expr(m.expr) + obj += "))" + | m.expr_kind.trt() != nil + | m.expr_kind.prim() != nil && m.expr_kind.prim().is_any(): + obj += self.model(m.expr) + obj += "." + if env::PRODUCTION { + obj += "operator " + obj += TypeCoder.kind(m.kind) + obj += "()" + } else { + if m.expr_kind.trt() != nil && m.kind.sptr() != nil { + obj += "cast_ptr<" + obj += TypeCoder.kind(m.kind.sptr().elem) + } else { + obj += "cast<" + obj += TypeCoder.kind(m.kind) + } + obj += ">(\"" + obj += self.oc.loc_info(m.token) + obj += "\")" + } + | m.kind.trt() != nil: + obj += TypeCoder.kind(m.kind) + obj += "(" + obj += self.expr(m.expr) + obj += ", " + obj += conv::itoa(self.oc.find_type_offset(m.kind.trt(), m.expr_kind)) + obj += ")" + |: + obj += "static_cast<" + obj += TypeCoder.kind(m.kind) + obj += ">(" + obj += self.expr(m.expr) + obj += ")" + } + ret obj + } + + fn args(mut self, mut args: []ExprModel): str { + if args.len == 0 { + ret "" + } + let mut obj = "" + for (_, mut a) in args { + obj += self.expr(a) + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + ret obj + } + + fn model_for_call(mut self, mut expr: ExprModel): str { + match type expr { + | &FnIns: + ret self.func_ins((&FnIns)(expr)) + | &StructSubIdentExprModel: + let mut ssie = (&StructSubIdentExprModel)(expr) + if ssie.method != nil { + ret self.func_ins(ssie.method) + } + } + ret self.model(expr) + } + + fn push_call_inf(mut self, mut &obj: str, &m: &FnCallExprModel) { + if env::PRODUCTION || (!m.func.anon && !is_builtin_call_has_debuginf(m)) { + obj += "(" + ret + } + if m.func.anon { + match type m.expr { + | &StructSubIdentExprModel: + if (&StructSubIdentExprModel)(m.expr).field.decl.owner.cpp_linked { + obj += "(" + ret + } + fall + |: + obj += ".call" + } + } + obj += "(\"" + obj += self.oc.loc_info(m.token) + obj += "\"" + if m.args.len != 0 { + obj += "," + } + } + + fn pure_func_call(mut self, mut &m: &FnCallExprModel): str { + let mut obj = self.model_for_call(m.expr) + if !m.func.is_builtin() { + if m.func.decl.cpp_linked && m.func.generics.len > 0 { + if !has_directive(m.func.decl.directives, Directive.Cdef) { + obj += "<" + for (_, mut g) in m.func.generics { + obj += TypeCoder.kind(g) + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + obj += ">" + } + } + } + self.push_call_inf(obj, m) + let mut locinfo = false + let mut wrap_receiver = "" + if !m.func.is_builtin() && m.func.decl.params.len > 0 && m.func.decl.params[0].is_self() { + match type m.expr { + | &StructSubIdentExprModel: + let mut ssie = (&StructSubIdentExprModel)(m.expr) + match { + | m.func.decl.params[0].is_ref(): + obj += self.model(ssie.expr) + | ssie.expr_kind.sptr() != nil: + obj += self.model(ssie.expr) + obj += ".ptr(" + if !env::PRODUCTION { + obj += "\"" + obj += self.oc.loc_info(m.token) + obj += "\"" + } + obj += ")" + |: + if ssie.expr.kind.strct() != nil { + // Add address taking operation for non-pointers. + obj += "&" + if !ssie.expr.lvalue { + wrap_receiver = self.model(ssie.expr) + } + } + if wrap_receiver != "" { + obj += "_wrap_copy" + } else { + obj += self.model(ssie.expr) + } + } + if m.args.len > 0 { + obj += ", " + } + | &TraitSubIdentExprModel: + obj += self.model((&TraitSubIdentExprModel)(m.expr).expr) + if !env::PRODUCTION { + locinfo = true + } + if m.args.len > 0 { + obj += ", " + } + } + } + obj += self.args(m.args) + if locinfo { + obj += ", \"" + obj += self.oc.loc_info(m.token) + obj += "\"" + } + obj += ")" + + if wrap_receiver != "" { + obj = "({ auto _wrap_copy = " + wrap_receiver + "; " + obj + obj += "; })" + } + + if m.is_co { + obj = "__JULE_CO(" + obj + obj += ")" + } + + ret obj + } + + fn func_call(mut self, mut m: &FnCallExprModel): str { + if m.func.is_builtin() || + !m.func.decl.exceptional || + m.except != nil && m.except.stmts.len == 0 { + ret self.pure_func_call(m) + } + + // Generate code for exceptional. + let mut obj = "({\n" + self.oc.add_indent() + obj += self.oc.indent() + obj += "auto except = " + obj += self.pure_func_call(m) + obj += ";\n" + obj += self.oc.indent() + if m.except != nil { + if m.func.result == nil || !m.assigned { + obj += "if (!except.ok()) " + obj += self.oc.sc.scope(m.except) + obj += "\n" + } else { + let forwarded = is_forwarded(m.except) + obj += "(except.ok()) ? (except.result) : (" + if forwarded { + obj += "{" + } + obj += self.oc.sc.scope(m.except) + if forwarded { + obj += " " + obj += self.init_expr(m.func.result) + obj += ";}" + } + obj += ");\n" + } + self.oc.done_indent() + } else { + obj += `if (!except.ok()) jule::panic(jule::Str("` + obj += `unhandled exceptional: ") + except.error.type->to_str(except.error.data) + jule::Str("\nlocation: ` + obj += self.oc.loc_info(m.token) + obj += "\"));\n" + if !m.func.decl.is_void() { + obj += self.oc.indent() + obj += "(except.result);\n" + } + self.oc.done_indent() + } + + obj += self.oc.indent() + obj += "})" + ret obj + } + + fn slice(mut self, mut m: &SliceExprModel): str { + if m.elems.len == 0 { + ret TypeCoder.as_slice(m.elem_kind) + "()" + } + let mut obj = TypeCoder.as_slice(m.elem_kind) + obj += "({" + obj += self.args(m.elems) + obj += "})" + ret obj + } - fn val(mut &self, mut v: &Value) {} + fn indexing(mut self, mut m: &IndexingExprModel): str { + let mut obj = self.model(m.expr.model) + // Index access with safety measures. + match { + | env::PRODUCTION + | m.expr.kind.ptr() != nil + | m.expr.kind.map() != nil: + obj += "[" + obj += self.expr(m.index.model) + obj += "]" + |: + obj += ".at(\"" + obj += self.oc.loc_info(m.token) + obj += "\"," + obj += self.expr(m.index.model) + obj += ")" + } + ret obj + } + + fn unsafe_indexing(mut self, mut m: &UnsafeIndexingExprModel): str { + let mut obj = self.model(m.node.expr.model) + // Index access with safety measures. + match { + | env::PRODUCTION + | m.node.expr.kind.ptr() != nil + | m.node.expr.kind.map() != nil: + obj += "[" + obj += self.expr(m.node.index.model) + obj += "]" + |: + obj += ".__at(" + obj += self.expr(m.node.index.model) + obj += ")" + } + ret obj + } + + fn anon_func(mut self, mut m: &AnonFnExprModel): str { + let mut obj = TypeCoder.func(m.func) + obj += "([=]" + obj += self.oc.params_ins(m.func.params) + obj += " mutable -> " + obj += TypeCoder.func_ins_result(m.func) + obj += " " + obj += self.oc.sc.func_scope(m.func) + obj += ")" + ret obj + } - fn init_expr(mut &self, mut t: &TypeKind) {} + fn map(mut self, mut m: &MapExprModel): str { + let mut obj = TypeCoder.Map + "<" + obj += TypeCoder.kind(m.key_kind) + obj += "," + obj += TypeCoder.kind(m.val_kind) + obj += ">({" + if m.entries.len > 0 { + for (_, mut pair) in m.entries { + let mut pair_obj = "{" + pair_obj += self.expr(pair.key) + pair_obj += "," + pair_obj += self.expr(pair.val) + pair_obj += "}" + obj += pair_obj + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + } + obj += "})" + ret obj + } + + fn slicing(mut self, mut m: &SlicingExprModel): str { + let mut obj = self.model(m.expr) + obj += ".slice(" + if !env::PRODUCTION { + obj += "\"" + obj += self.oc.loc_info(m.token) + obj += "\"," + } + obj += self.expr(m.left) + if m.right != nil { + obj += "," + obj += self.expr(m.right) + } + obj += ")" + ret obj + } + + fn trait_sub(mut self, mut m: &TraitSubIdentExprModel): str { + let mut obj = IdentCoder.trait_decl(m.trt) + obj += "_mptr_data" + obj += "[(" + obj += self.model(m.expr) + obj += ").type_offset]." + obj += IdentCoder.func(m.method) + ret obj + } + + fn structure_sub(mut self, mut m: &StructSubIdentExprModel): str { + let mut obj = self.model(m.expr) + if m.field != nil { + if m.expr_kind.ptr() != nil { + obj += "->" + } else if m.expr_kind.sptr() != nil { + obj += ".get(" + if !env::PRODUCTION { + obj += "\"" + obj += self.oc.loc_info(m.token) + obj += "\"" + } + obj += ")." + } else { + obj += "." + } + obj += IdentCoder.field(m.field.decl) + } + ret obj + } + + fn common_ident(self, m: &CommonIdentExprModel): str { + ret m.ident + } + + fn common_sub(mut self, mut m: &CommonSubIdentExprModel): str { + let mut obj = self.model(m.expr) + match { + | m.expr_kind.ptr() != nil: + obj += "->" + | m.expr_kind.sptr() != nil: + obj += ".get(" + if !env::PRODUCTION { + obj += "\n" + obj += self.oc.loc_info(m.token) + obj += "\n" + } + obj += ")." + |: + obj += "." + } + obj += m.ident + ret obj + } + + fn array(mut self, mut m: &ArrayExprModel): str { + let mut obj = TypeCoder.array(m.kind) + if m.elems.len == 0 { + obj += "()" + ret obj + } + + // Filled. + if m.elems.len == 2 && m.elems[1] == nil { + obj += "(" + obj += self.expr(m.elems[0]) + obj += ")" + ret obj + } + + obj += "({" + obj += self.args(m.elems) + obj += "})" + ret obj + } + + // Returns complete expression model of function instance. + // Usefull for strict type safety. + fn func_ins_common(self, mut m: &FnIns): str { + let mut obj = TypeCoder.func(m) + obj += "(" + obj += self.func_ins(m) + obj += ")" + ret obj + } + + // Returns elementary expression model of function instance. + fn func_ins(self, mut m: &FnIns): str { + if m.decl != nil && m.decl.cpp_linked { + let d = find_directive(m.decl.directives, Directive.Namespace) + if d != nil { + let mut obj = concat_all_parts(d.args...) + obj += "::" + obj += IdentCoder.func_ins(m) + ret obj + } + } + ret IdentCoder.func_ins(m) + } + + fn tuple(mut self, mut m: &TupleExprModel): str { + let mut obj = "std::make_tuple(" + for (_, mut d) in m.datas { + obj += self.expr(d.model) + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + obj += ")" + ret obj + } + + fn new_call(mut self, mut m: &BuiltinNewCallExprModel): str { + let mut obj = "jule::new_ptr<" + obj += TypeCoder.kind(m.kind) + obj += ">(" + if m.init != nil { + obj += self.expr(m.init) + } + obj += ")" + ret obj + } + + fn out_call(mut self, mut m: &BuiltinOutCallExprModel): str { + if m.debug && env::PRODUCTION { + ret "" + } + let mut obj = "jule::out(" + obj += self.expr(m.expr) + obj += ")" + ret obj + } + + fn outln_call(mut self, mut m: &BuiltinOutlnCallExprModel): str { + if m.debug && env::PRODUCTION { + ret "" + } + let mut obj = "jule::outln(" + obj += self.expr(m.expr) + obj += ")" + ret obj + } + + fn panic_call(mut self, mut m: &BuiltinPanicCallExprModel): str { + let mut obj = "jule::panic(" + obj += self.expr(m.expr) + obj += ` + jule::Str("\nlocation: ` + obj += self.oc.loc_info(m.token) + obj += "\"));" + ret obj + } + + fn assert_call(mut self, mut m: &BuiltinAssertCallExprModel): str { + if env::PRODUCTION { + ret "" + } + let mut obj = "if (!(" + obj += self.expr(m.expr) + obj += ")) jule::panic(jule::Str(" + obj += cstr_lit([]byte(m.log)) + obj += `) + jule::Str("\nlocation: ` + obj += self.oc.loc_info(m.token) + obj += "\"));" + ret obj + } + + fn error_call(mut self, mut m: &BuiltinErrorCallExprModel): str { + let mut obj = "return " + if m.func.decl.is_void() { + obj += "jule::VoidExceptional(" + } else { + obj += "jule::Exceptional<" + obj += TypeCoder.kind(m.func.result) + obj += ">(" + } + obj += self.expr(m.err) + obj += ")" + ret obj + } + + fn make_call(mut self, mut m: &BuiltinMakeCallExprModel): str { + let mut obj = "" + if m.len != nil { + obj += self.expr(m.len) + } else { + obj += "0" + } + if m.cap != nil { + obj += "," + self.expr(m.cap) + } + + if m.kind.slc().elem.enm() != nil { + obj += "," + obj += self.init_expr(m.kind.slc().elem) + if m.cap != nil { + obj = TypeCoder.kind(m.kind) + "::alloc(" + obj + } else { + obj = TypeCoder.kind(m.kind) + "::alloc_def(" + obj + } + } else { + obj = TypeCoder.kind(m.kind) + "::alloc(" + obj + } + + obj += ")" + ret obj + } + + fn push_to_slice(mut self, mut m: &PushToSliceExprModel): str { + let dest = self.model(m.dest) + let mut obj = dest + obj += " = jule::alloc_for_append(" + obj += dest + obj += "," + obj += conv::itoa(m.elems.elems.len) + obj += ");" + for (_, mut e) in m.elems.elems { + obj += dest + // Use the "__push" function to skip allocation boundary checking. + obj += ".__push(" + obj += self.model(e) + obj += ");" + } + ret obj + } + + fn append_call(mut self, mut m: &BuiltinAppendCallExprModel): str { + let mut obj = "jule::append(" + obj += self.model(m.dest) + obj += "," + obj += self.model(m.elements) + obj += ")" + ret obj + } + + fn clone_call(mut self, mut m: &BuiltinCloneCallExprModel): str { + let mut obj = "jule::clone(" + obj += self.model(m.expr) + obj += ")" + ret obj + } + + fn sizeof(mut self, mut m: &SizeofExprModel): str { + let mut obj = "sizeof(" + obj += self.expr(m.expr) + obj += ")" + ret obj + } + + fn alignof(mut self, mut m: &AlignofExprModel): str { + let mut obj = "alignof(" + obj += self.expr(m.expr) + obj += ")" + ret obj + } + + fn rune_lit(self, m: &RuneExprModel): str { + if m.code <= 127 { // ASCII + let mut b = sbtoa(byte(m.code)) + if b == "'" { + b = "\\'" + } + ret "'" + b + "'" + } + ret itoa(i64(m.code)) + } + + fn structure_static(self, mut m: &StructStaticIdentExprModel): str { + ret IdentCoder.func_ins(m.method) + } + + fn integrated_to_str(mut self, mut m: &IntegratedToStrExprModel): str { + let mut obj = "jule::to_str(" + obj += self.model(m.expr) + obj += ")" + ret obj + } + + fn backend_emit(mut self, mut m: &BackendEmitExprModel): str { + if m.exprs.len == 0 { + ret m.code + } + for (i, mut expr) in m.exprs { + m.exprs[i] = self.expr(expr) + } + ret fmt::format(m.code, m.exprs...) + } + + fn free(mut self, mut m: &FreeExprModel): str { + if env::RC { + ret self.expr(m.expr) + ".dealloc()" + } + ret self.expr(m.expr) + ".__free()" + } + + fn mut_slicing(mut self, mut m: &MutSlicingExprModel): str { + let mut obj = "(" + obj += self.model(m.expr) + obj += ").mut_slice(" + if !env::PRODUCTION { + obj += "\"" + obj += self.oc.loc_info(m.token) + obj += "\"," + } + obj += self.expr(m.left) + if m.right != nil { + obj += "," + obj += self.expr(m.right) + } + obj += ");" + ret obj + } + + fn str_insert_begin(mut self, mut m: &StrInsertBeginExprModel): str { + let mut obj = "(" + obj += self.model(m.dest) + obj += ").buffer.insert(0, (" + obj += self.model(m.expr) + obj += "));" + ret obj + } + + fn model(mut self, mut m: ExprModel): str { + match type m { + | &Data: + ret self.model((&Data)(m).model) + | &TypeKind: + ret TypeCoder.kind((&TypeKind)(m)) + | &Const: + ret self.constant((&Const)(m), false) + | &Var: + ret self.var((&Var)(m)) + | &Trait: + ret IdentCoder.trait_decl((&Trait)(m)) + | &Struct: + ret self.structure((&Struct)(m)) + | &StructIns: + ret self.structure_ins((&StructIns)(m)) + | &FnIns: + ret self.func_ins_common((&FnIns)(m)) + | &UnsafeBinopExprModel: + ret self.unsafe_binary((&UnsafeBinopExprModel)(m).node) + | &BinopExprModel: + ret self.binary((&BinopExprModel)(m)) + | &UnaryExprModel: + ret self.unary((&UnaryExprModel)(m)) + | &StructLitExprModel: + ret self.structure_lit((&StructLitExprModel)(m)) + | &AllocStructLitExprModel: + ret self.alloc_structure((&AllocStructLitExprModel)(m)) + | &CastingExprModel: + ret self.casting((&CastingExprModel)(m)) + | &FnCallExprModel: + ret self.func_call((&FnCallExprModel)(m)) + | &SliceExprModel: + ret self.slice((&SliceExprModel)(m)) + | &ArrayExprModel: + ret self.array((&ArrayExprModel)(m)) + | &UnsafeIndexingExprModel: + ret self.unsafe_indexing((&UnsafeIndexingExprModel)(m)) + | &IndexingExprModel: + ret self.indexing((&IndexingExprModel)(m)) + | &AnonFnExprModel: + ret self.anon_func((&AnonFnExprModel)(m)) + | &MapExprModel: + ret self.map((&MapExprModel)(m)) + | &SlicingExprModel: + ret self.slicing((&SlicingExprModel)(m)) + | &TraitSubIdentExprModel: + ret self.trait_sub((&TraitSubIdentExprModel)(m)) + | &StructSubIdentExprModel: + ret self.structure_sub((&StructSubIdentExprModel)(m)) + | &CommonIdentExprModel: + ret self.common_ident((&CommonIdentExprModel)(m)) + | &CommonSubIdentExprModel: + ret self.common_sub((&CommonSubIdentExprModel)(m)) + | &TupleExprModel: + ret self.tuple((&TupleExprModel)(m)) + | &BuiltinOutCallExprModel: + ret self.out_call((&BuiltinOutCallExprModel)(m)) + | &BuiltinOutlnCallExprModel: + ret self.outln_call((&BuiltinOutlnCallExprModel)(m)) + | &BuiltinNewCallExprModel: + ret self.new_call((&BuiltinNewCallExprModel)(m)) + | &BuiltinPanicCallExprModel: + ret self.panic_call((&BuiltinPanicCallExprModel)(m)) + | &BuiltinAssertCallExprModel: + ret self.assert_call((&BuiltinAssertCallExprModel)(m)) + | &BuiltinErrorCallExprModel: + ret self.error_call((&BuiltinErrorCallExprModel)(m)) + | &BuiltinMakeCallExprModel: + ret self.make_call((&BuiltinMakeCallExprModel)(m)) + | &BuiltinAppendCallExprModel: + ret self.append_call((&BuiltinAppendCallExprModel)(m)) + | &BuiltinCloneCallExprModel: + ret self.clone_call((&BuiltinCloneCallExprModel)(m)) + | &SizeofExprModel: + ret self.sizeof((&SizeofExprModel)(m)) + | &AlignofExprModel: + ret self.alignof((&AlignofExprModel)(m)) + | &RuneExprModel: + ret self.rune_lit((&RuneExprModel)(m)) + | &StructStaticIdentExprModel: + ret self.structure_static((&StructStaticIdentExprModel)(m)) + | &IntegratedToStrExprModel: + ret self.integrated_to_str((&IntegratedToStrExprModel)(m)) + | &BackendEmitExprModel: + ret self.backend_emit((&BackendEmitExprModel)(m)) + | &FreeExprModel: + ret self.free((&FreeExprModel)(m)) + | &MutSlicingExprModel: + ret self.mut_slicing((&MutSlicingExprModel)(m)) + | &StrInsertBeginExprModel: + ret self.str_insert_begin((&StrInsertBeginExprModel)(m)) + |: + ret "" + } + } + + fn expr(mut self, mut e: ExprModel): str { + let mut obj = self.model(e) + if obj.len == 0 || obj[0] != '(' { + ret obj + } + match type e { + | &BinopExprModel: + obj = obj[1:obj.len-1] + } + ret obj + } + + fn val(mut self, mut v: &Value): str { + if v.data.is_const() { + ret self.constant(v.data.constant, v.data.kind != nil && v.data.kind.prim().is_f32()) + } + ret self.expr(v.data.model) + } + + fn init_expr(mut self, mut t: &TypeKind): str { + if t.ptr() != nil { + ret "nullptr" + } + let mut enm = t.enm() + if enm != nil { + ret self.val(enm.items[0].value) + } + ret TypeCoder.kind(t) + "()" + } } fn decompose_common_esq(b: byte): str { @@ -228,4 +1271,4 @@ fn is_builtin_call_has_debuginf(&m: &FnCallExprModel): bool { |: ret false } -} \ No newline at end of file +} diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index d9fde1fac..495bf1a3c 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -90,11 +90,73 @@ impl ObjectCoder { self.indent_buffer = self.indent_buffer[:self.indent_buffer.len-1] } - // Returns indention string by indent_buffer. - fn indent(mut &self) { + // Writes indention string by indent_buffer. + fn indent(mut &self): str { + ret str(self.indent_buffer) _ = self.f.write(self.indent_buffer)! } + fn var_init_expr(mut &self, mut &v: &Var, init: str): str { + let mut obj = "" + if v.statically { + obj += "static " + } + + obj += TypeCoder.kind(v.kind.kind) + obj += " " + if v.reference { + obj += "&" + } + obj += IdentCoder.var(v) + if init != "" { + obj += " = " + obj += init + } + obj += ";" + ret obj + } + + fn find_type_offset(self, t: &Trait, mut k: &TypeKind): int { + let mut s: &StructIns = nil + if k.sptr() != nil { + k = k.sptr().elem + } + if k.strct() == nil { + ret -1 + } + s = k.strct() + for _, hash in self.tmap { + if hash.t == t && hash.s == s { + ret hash.i + } + } + ret -1 + } + + // Writes location information of token as cstr bytes. + fn loc_info(mut &self, &t: &Token): str { + let mut loc = t.file.path + + // Normalize path if production compilation enabled. + if env::PRODUCTION { + match { + | strings::has_prefix(loc, build::PATH_STDLIB): + // Remove absolute path prefix of standard library. + // Just keeps "std/" prefix. + loc = loc[path::dir(build::PATH_STDLIB).len+1:] + | strings::has_prefix(loc, self.ir.root): + // Remove absolute path prefix of root package. + // Just keeps "[package_dir]/" prefix. + loc = loc[path::dir(self.ir.root).len+1:] + } + } + loc += ":" + loc += conv::itoa(t.row) + loc += ":" + loc += conv::itoa(t.column) + ret cstr_bytes([]byte(loc)) + } + fn head(mut &self) { let time = Time.now() let abs = time.abs() @@ -225,9 +287,9 @@ impl ObjectCoder { if f.default == nil { // No default expression. // Use default expression of data-type. - self.ec.init_expr(f.kind) + self.write(self.ec.init_expr(f.kind)) } else { - self.ec.expr(f.default.model) + self.write(self.ec.expr(f.default.model)) } self.write(";") } @@ -599,33 +661,47 @@ impl ObjectCoder { }) } - fn param_ins(mut &self, mut &p: &ParamIns) { - self.write(TypeCoder.param_ins(p)) - self.write(" ") - self.write(IdentCoder.param(p.decl)) + fn param_ins(mut &self, mut &p: &ParamIns): str { + let mut obj = TypeCoder.param_ins(p) + obj += " " + obj += IdentCoder.param(p.decl) + ret obj } - fn params_ins(mut &self, mut ¶ms: []&ParamIns) { + fn params_ins(mut &self, mut ¶ms: []&ParamIns): str { if params.len == 0 { - self.write("(void)") - ret + ret "(void)" } - self.write("(") + let mut obj = "(" for (i, mut p) in params { - self.param_ins(p) + obj += self.param_ins(p) if params.len-i > 1 { - self.write(", ") + obj += ", " } } - self.write(")") + obj += ")" + ret obj + } + + fn var(mut &self, mut v: &Var): str { + if is_ignore_ident(v.ident) { + ret "" + } + if v.value != nil && v.value.expr != nil { + if v.value.data.model != nil { + ret self.var_init_expr(v, self.ec.val(v.value)) + } + ret self.var_init_expr(v, "") + } + ret self.var_init_expr(v, self.ec.init_expr(v.kind.kind)) } fn func(mut &self, mut &f: &Fn) { for (_, mut ins) in f.instances { self.func_head(ins, false) - self.params_ins(ins.params) + self.write(self.params_ins(ins.params)) self.write(" ") - self.sc.func_scope(ins) + self.write(self.sc.func_scope(ins)) if ins.scope != nil { self.write("\n\n") } @@ -901,11 +977,11 @@ impl ObjectCoder { if v.value != nil && v.value.expr != nil { if v.value.data.model != nil { self.write(" = ") - self.ec.val(v.value) + self.write(self.ec.val(v.value)) } } else { self.write(" = ") - self.ec.init_expr(v.kind.kind) + self.write(self.ec.init_expr(v.kind.kind)) } self.write(";\n") } diff --git a/src/julec/obj/cxx/scope.jule b/src/julec/obj/cxx/scope.jule index c8dbe63e1..b8a578b49 100644 --- a/src/julec/obj/cxx/scope.jule +++ b/src/julec/obj/cxx/scope.jule @@ -50,9 +50,726 @@ impl ScopeCoder { } } - fn scope(mut &self, mut s: &Scope) {} + fn range_index_iter(mut self, mut &it: &RangeIter): str { + let begin = IdentCoder.iter_begin(uintptr(it)) + let next = IdentCoder.iter_next(uintptr(it)) - fn func_scope(mut &self, mut f: &FnIns) {} + let mut obj = "{\n" + self.oc.add_indent() + obj += self.oc.indent() + obj += "auto " + if env::OPT_COPY && is_copy_optimizable(it.expr) { + obj += "&" + } + obj += "expr = " + obj += self.oc.ec.model(it.expr.model) + obj += ";\n" + obj += self.oc.indent() + obj += "auto it = expr.begin();\n" + obj += self.oc.indent() + obj += begin + obj += ":;\n" + obj += self.oc.indent() + obj += "if (it != expr.end()) {\n" + self.oc.add_indent() + obj += self.oc.indent() + if it.key_a != nil { + obj += self.oc.var_init_expr(it.key_a, "it - expr.begin()") + obj += "\n" + obj += self.oc.indent() + } + if it.key_b != nil { + if env::OPT_COPY { + it.key_b.reference = is_iter_copy_optimizable(it.expr, it.key_b) + } + obj += self.oc.var_init_expr(it.key_b, "*it") + obj += "\n" + obj += self.oc.indent() + } + obj += self.scope(it.scope) + obj += "\n" + obj += self.oc.indent() + obj += next + obj += ":;\n" + obj += self.oc.indent() + obj += "++it;\n" + obj += self.oc.indent() + if it.key_a != nil { + obj += IdentCoder.var(it.key_a) + obj += "++;\n" + obj += self.oc.indent() + } + obj += "goto " + obj += begin + obj += ";\n" + + // Close if. + self.oc.done_indent() + obj += self.oc.indent() + obj += "}\n" + + obj += self.oc.indent() + obj += IdentCoder.iter_end(uintptr(it)) + obj += ":;\n" + + // Close scope. + self.oc.done_indent() + obj += self.oc.indent() + obj += "}" + + ret obj + } + + fn range_hashmap_iter(mut self, mut &it: &RangeIter): str { + let begin = IdentCoder.iter_begin(uintptr(it)) + let next = IdentCoder.iter_next(uintptr(it)) + + let mut obj = "{\n" + self.oc.add_indent() + obj += self.oc.indent() + obj += "auto " + if env::OPT_COPY && is_copy_optimizable(it.expr) { + obj += "&" + } + obj += "expr = " + obj += self.oc.ec.model(it.expr.model) + obj += ";\n" + obj += self.oc.indent() + obj += "auto it = expr.begin();\n" + obj += self.oc.indent() + obj += begin + obj += ":;\n" + obj += self.oc.indent() + obj += "if (it != expr.end()) {\n" + self.oc.add_indent() + obj += self.oc.indent() + if it.key_a != nil { + if env::OPT_COPY { + it.key_a.reference = is_iter_copy_optimizable(it.expr, it.key_a) + } + obj += self.oc.var_init_expr(it.key_a, "it->first") + obj += "\n" + obj += self.oc.indent() + } + if it.key_b != nil { + if env::OPT_COPY { + it.key_b.reference = is_iter_copy_optimizable(it.expr, it.key_b) + } + obj += self.oc.var_init_expr(it.key_b, "it->second") + obj += "\n" + obj += self.oc.indent() + } + obj += self.scope(it.scope) + obj += "\n" + obj += self.oc.indent() + obj += next + obj += ":;\n" + obj += self.oc.indent() + obj += "++it;\n" + obj += self.oc.indent() + obj += "goto " + obj += begin + obj += ";\n" + + // Close if. + self.oc.done_indent() + obj += self.oc.indent() + obj += "}\n" + + obj += self.oc.indent() + obj += IdentCoder.iter_end(uintptr(it)) + obj += ":;\n" + + // Close scope. + self.oc.done_indent() + obj += self.oc.indent() + obj += "}" + + ret obj + } + + fn if_case(mut self, mut i: &If): str { + let mut obj = "" + if i.expr != nil { + obj += "if (" + obj += self.oc.ec.expr(i.expr) + obj += ") " + } + obj += self.scope(i.scope) + ret obj + } + + fn conditional(mut self, mut c: &Conditional): str { + let mut obj = "" + for (_, mut elif) in c.elifs { + if elif == nil { + continue + } + if obj.len != 0 { + obj += " else " + } + obj += self.if_case(elif) + } + if c.default != nil { + if obj.len != 0 { + obj += " else " + } + obj += self.scope(c.default.scope) + } + ret obj + } + + fn inf_iter(mut self, mut it: &InfIter): str { + let mut obj = "for (;;) {\n" + + self.oc.add_indent() // Indent scope. + obj += self.oc.indent() + obj += self.scope(it.scope) + self.oc.done_indent() + + obj += "\n" + obj += self.oc.indent() + obj += IdentCoder.iter_next(uintptr(it)) + obj += ":;\n" + obj += self.oc.indent() + obj += "}\n" + obj += self.oc.indent() + obj += IdentCoder.iter_end(uintptr(it)) + obj += ":;" + + ret obj + } + + fn while_iter(mut self, mut it: &WhileIter): str { + let mut obj = "" + if it.expr != nil && it.next == nil { + obj += "while (" + obj += self.oc.ec.expr(it.expr) + obj += ") {\n" + } else { + obj += "for (; " + if it.expr != nil { + obj += self.oc.ec.expr(it.expr) + } + obj += "; " + if it.next != nil { + let st = self.st(it.next) + obj += st[:st.len-1] + } + obj += ") {\n" + } + + self.oc.add_indent() + obj += self.oc.indent() + obj += self.scope(it.scope) + obj += "\n" + self.oc.done_indent() + obj += self.oc.indent() + + obj += IdentCoder.iter_next(uintptr(it)) + obj += ":;\n" + obj += self.oc.indent() + obj += "}\n" + obj += self.oc.indent() + obj += IdentCoder.iter_end(uintptr(it)) + obj += ":;" + ret obj + } + + fn range_iter(mut self, mut it: &RangeIter): str { + match { + | it.expr.kind.slc() != nil: + ret self.range_index_iter(it) + | it.expr.kind.arr() != nil: + ret self.range_index_iter(it) + | it.expr.kind.map() != nil: + ret self.range_hashmap_iter(it) + |: + ret self.range_index_iter(it) // Str + } + } + + fn cont(self, c: &ContSt): str { + let mut obj = "goto " + obj += IdentCoder.iter_next(c.it) + obj += ";" + ret obj + } + + fn label(self, l: &Label): str { + ret IdentCoder.label(l.ident) + ":;" + } + + fn goto_st(self, gt: &GotoSt): str { + let mut obj = "goto " + obj += IdentCoder.label(gt.ident) + obj += ";" + ret obj + } + + fn postfix(mut self, mut p: &Postfix): str { + let mut obj = "(" + obj += self.oc.ec.expr(p.expr) + obj += ")" + obj += p.op + obj += ";" + ret obj + } + + fn assign(mut self, mut a: &Assign): str { + let mut obj = self.oc.ec.expr(a.l.model) + obj += a.op.kind + obj += self.oc.ec.expr(a.r.model) + obj += ";" + ret obj + } + + fn multi_assign(mut self, mut a: &MultiAssign): str { + let mut obj = "std::tie(" + + for (_, mut l) in a.l { + if l == nil { + obj += CPP_IGNORE + } else { + obj += self.oc.ec.expr(l) + } + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + + obj += ") = " + obj += self.oc.ec.expr(a.r) + obj += ";" + ret obj + } + + fn match_expr(mut self, mut &m: &Match): str { + if !m.expr.is_const() { + ret MATCH_EXPR + } + if !m.expr.constant.is_bool() || !m.expr.constant.read_bool() { + ret self.oc.ec.model(m.expr.model) + } + ret "" + } + + fn case(mut self, mut m: &Match, mut c: &Case): str { + let mut obj = "" + + if c.exprs.len != 0 && !m.is_generic_type_match() { + if m.cases.len > 0 && m.cases[0] == c { + obj += "if (" + } else { + obj += "else if (" + } + for (i, mut expr) in c.exprs { + match { + | !m.type_match: + let case_expr = self.match_expr(m) + if m.expr.good_operand(expr) { + if case_expr.len != 0 { + obj += case_expr + obj += " == " + } + obj += self.oc.ec.expr(expr.model) + } else { + obj += self.oc.ec.expr(expr.model) + if case_expr.len != 0 { + obj += " == " + obj += case_expr + } + } + |: + obj += MATCH_EXPR + obj += ".type_is<" + obj += self.oc.ec.expr(expr.model) + obj += ">()" + } + + if i+1 < c.exprs.len { + obj += " || " + } + } + obj += ") " + } else if m.default == c && m.cases.len != 0 { + obj += self.oc.indent() + obj += "else " + } + + self.oc.add_indent() + + obj += "{\n" + obj += self.oc.indent() + obj += IdentCoder.case_begin(uintptr(c)) + obj += ":;\n" + if c.scope.stmts.len > 0 { + obj += self.oc.indent() + obj += self.scope(c.scope) + obj += "\n" + } + + self.oc.done_indent() + + obj += self.oc.indent() + obj += "}" + ret obj + } + + fn match_st(mut self, mut m: &Match): str { + if m.cases.len == 0 && m.default == nil { + ret "" + } + + let generic_type_match = m.is_generic_type_match() + if generic_type_match && (m.default == nil || m.default.scope.stmts.len == 0) { + ret "" + } + + let mut obj = "{\n" + + self.oc.add_indent() + + obj += self.oc.indent() + + // Constant expressions generated as literals in conditions. + if !generic_type_match && !m.expr.is_const() { + if env::OPT_COPY && is_copy_optimizable(m.expr) { + obj += "auto &_match_expr{ " + } else { + obj += "auto _match_expr{ " + } + obj += self.oc.ec.expr(m.expr.model) + obj += " };\n" + obj += self.oc.indent() + } + + if m.cases.len > 0 { + for (_, mut c) in m.cases { + if c == nil { + continue + } + obj += "\n" + obj += self.oc.indent() + obj += self.case(m, c) + } + } + + if m.default != nil { + obj += "\n" + obj += self.case(m, m.default) + } + + obj += "\n" + obj += self.oc.indent() + obj += IdentCoder.match_end(uintptr(m)) + obj += ":;" + obj += "\n" + + self.oc.done_indent() + + obj += self.oc.indent() + obj += "}" + + ret obj + } + + fn fall_st(self, f: &FallSt): str { + let mut obj = "goto " + obj += IdentCoder.case_begin(f.dest_case) + obj += ";" + ret obj + } + + fn break_st(self, b: &BreakSt): str { + let mut obj = "goto " + if b.it != 0 { + obj += IdentCoder.iter_end(b.it) + } else { + obj += IdentCoder.match_end(b.mtch) + } + obj += ";" + ret obj + } + + fn ret_with_vars(mut self, mut r: &RetSt): str { + let mut obj = "" + for (_, mut v) in r.vars { + if lex::is_ignore_ident(v.ident) { + obj += self.oc.ec.init_expr(v.kind.kind) + } else { + obj += IdentCoder.var(v) + } + obj += "," + } + + obj = obj[:obj.len-1] // Remove last comma. + + let mut oobj = "return " + + if r.func.decl.exceptional { + oobj += "jule::Exceptional<" + oobj += TypeCoder.kind(r.func.result) + oobj += ">(jule::Any(), " + } + + if r.vars.len > 1 { + oobj += "std::make_tuple(" + oobj += obj + oobj += ")" + } else { + oobj += obj + } + + if r.func.decl.exceptional { + oobj += ")" + } + + oobj += ";" + ret oobj + } + + fn ret_tuple(mut self, mut r: &RetSt): str { + let mut datas = (&TupleExprModel)(r.expr).datas + let mut obj = "" + + for (i, mut v) in r.vars { + if lex::is_ignore_ident(v.ident) { + continue + } + let mut model = datas[i].model + // Ignore self assignment. + if model == v { + continue + } + let ident = IdentCoder.var(v) + obj += ident + obj += " = " + obj += self.oc.ec.expr(model) + obj += ";\n" + obj += self.oc.indent() + } + + let mut oobj = "std::make_tuple(" + for (i, mut d) in datas { + let mut v = r.vars[i] + if lex::is_ignore_ident(v.ident) { + oobj += self.oc.ec.expr(d.model) + } else { + oobj += IdentCoder.var(v) + } + + oobj += "," + } + oobj = oobj[:oobj.len-1] // Remove last comma. + oobj += ")" + + if r.func.decl.exceptional { + obj += "return jule::Exceptional<" + obj += TypeCoder.kind(r.func.result) + obj += ">(jule::Any()," + obj += oobj + obj += ")" + } else { + obj += "return " + obj += oobj + } + + obj += ";" + ret obj + } + + fn ret_with_exprs(mut self, mut r: &RetSt): str { + if r.vars.len > 1 { + ret self.ret_tuple(r) + } + + // Ignore self assignments and ignored variables. + if r.vars.len > 0 { + let mut v = r.vars[0] + if !lex::is_ignore_ident(v.ident) && r.expr != v { + let ident = IdentCoder.var(v) + let mut obj = ident + obj += " = " + obj += self.oc.ec.expr(r.expr) + obj += ";\n" + obj += self.oc.indent() + if r.func.decl.exceptional { + obj += "return jule::Exceptional<" + obj += TypeCoder.kind(r.func.result) + obj += ">(jule::Any()," + obj += ident + obj += ")" + } else { + obj += "return " + obj += ident + } + obj += ";" + ret obj + } + } + + if r.func.decl.exceptional { + let mut obj = "return jule::Exceptional<" + obj += TypeCoder.kind(r.func.result) + obj += ">(jule::Any()," + obj += self.oc.ec.expr(r.expr) + obj += ")" + obj += ";" + ret obj + } + + let mut obj = "return " + obj += self.oc.ec.expr(r.expr) + obj += ";" + ret obj + } + + fn ret_st(mut self, mut r: &RetSt): str { + // Void. + if r.expr == nil && r.vars.len == 0 { + if r.func.decl.exceptional { + ret "return jule::VoidExceptional();" + } + ret "return;" + } + + if r.expr == nil { + ret self.ret_with_vars(r) + } + ret self.ret_with_exprs(r) + } + + fn ret_with_defaults(mut self, mut result: &TypeKind): str { + let mut obj = "return " + if result.tup() != nil { + obj += "std::make_tuple(" + for (_, mut t) in result.tup().types { + obj += self.oc.ec.init_expr(t) + obj += "," + } + obj = obj[:obj.len-1] // Remove last comma. + obj += ")" + } else { + obj += self.oc.ec.init_expr(result) + } + obj += ";" + ret obj + } + + fn var(mut self, mut v: &Var): str { + if v.constant { + ret "" + } + ret self.oc.var(v) + } + + // Generates C++ code of statement. + fn st(mut self, mut st: St): str { + if st == nil { + ret "" + } + match type st { + | &Scope: + ret self.scope((&Scope)(st)) + | &Var: + ret self.var((&Var)(st)) + | &Data: + ret self.oc.ec.expr((&Data)(st)) + ";" + | &Conditional: + ret self.conditional((&Conditional)(st)) + | &InfIter: + ret self.inf_iter((&InfIter)(st)) + | &WhileIter: + ret self.while_iter((&WhileIter)(st)) + | &RangeIter: + ret self.range_iter((&RangeIter)(st)) + | &ContSt: + ret self.cont((&ContSt)(st)) + | &Label: + ret self.label((&Label)(st)) + | &GotoSt: + ret self.goto_st((&GotoSt)(st)) + | &Postfix: + ret self.postfix((&Postfix)(st)) + | &Assign: + ret self.assign((&Assign)(st)) + | &MultiAssign: + ret self.multi_assign((&MultiAssign)(st)) + | &Match: + ret self.match_st((&Match)(st)) + | &FallSt: + ret self.fall_st((&FallSt)(st)) + | &BreakSt: + ret self.break_st((&BreakSt)(st)) + | &RetSt: + ret self.ret_st((&RetSt)(st)) + | &PushToSliceExprModel: + ret self.oc.ec.push_to_slice((&PushToSliceExprModel)(st)) + | &MutSlicingExprModel: + ret self.oc.ec.mut_slicing((&MutSlicingExprModel)(st)) + | &StrInsertBeginExprModel: + ret self.oc.ec.str_insert_begin((&StrInsertBeginExprModel)(st)) + |: + ret "" + } + } + + fn scope_end(mut self, mut &obj: str, mut &s: &Scope) { + for (_, mut st) in s.stmts { + obj += self.oc.indent() + obj += self.st(st) + obj += "\n" + } + + self.oc.done_indent() + obj += self.oc.indent() + obj += "}" + + if s.deferred { + obj = "__JULE_DEFER(" + obj + ");" + } + } + + // Generates C++ code of scope. + fn scope(mut self, mut s: &Scope): str { + self.oc.add_indent() + let mut obj = "{\n" + self.scope_end(obj, s) + ret obj + } + + // Generates C++ code of function's scope. + fn func_scope(mut self, mut f: &FnIns): str { + if f.scope == nil { + ret "" + } + let mut obj = "{\n" + self.oc.add_indent() + if !f.decl.is_void() { + let mut types = f.types() + for i, ident in f.decl.result.idents { + if lex::is_ignore_ident(ident.kind) || + lex::is_anon_ident(ident.kind) { + continue + } + obj += self.oc.indent() + obj += TypeCoder.kind(types[i]) + obj += " " + obj += IdentCoder.to_local(ident.row, ident.column, ident.kind) + obj += " = " + obj += self.oc.ec.init_expr(types[i]) + obj += ";\n" + } + } + self.scope_end(obj, f.scope) + if f.decl.exceptional && f.decl.is_void() { + // Just for void exceptionals. + // Other cases checked by semantic analsis and disallowed + // if they are not returns. + obj = obj[:obj.len-2] + " return jule::VoidExceptional(); }" + } + ret obj + } } fn is_copy_optimizable(&expr: &Data): bool { @@ -71,4 +788,4 @@ fn is_iter_copy_optimizable(&expr: &Data, &v: &Var): bool { ret true } ret !v.mutable && !expr.mutable -} \ No newline at end of file +} From 0d0531d1c677d284355144c971fd2fa98c1a0bcf Mon Sep 17 00:00:00 2001 From: mertcandav Date: Thu, 4 Apr 2024 03:20:10 +0300 Subject: [PATCH 15/17] compiler: implement all algorithms to common write functionality --- src/julec/obj/cxx/expr.jule | 1171 +++++++++++++++++---------------- src/julec/obj/cxx/object.jule | 117 ++-- src/julec/obj/cxx/scope.jule | 788 +++++++++++----------- 3 files changed, 1030 insertions(+), 1046 deletions(-) diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule index 161046cdc..4d839b20f 100644 --- a/src/julec/obj/cxx/expr.jule +++ b/src/julec/obj/cxx/expr.jule @@ -92,863 +92,870 @@ impl ExprCoder { } } - fn string(self, &c: &Const): str { + fn string(mut &self, &c: &Const) { let content = c.read_str() if content.len == 0 { // Empty. - ret TypeCoder.Str + "()" + self.oc.write(TypeCoder.Str + "()") + ret } let bytes = []byte(content) let len = conv::fmt_int(i64(bytes.len), 10) let lit = cstr_lit(bytes) - ret TypeCoder.Str + "(" + lit + ", " + len + ")" + self.oc.write(TypeCoder.Str) + self.oc.write("(") + self.oc.write(lit) + self.oc.write(", ") + self.oc.write(len) + self.oc.write(")") } - fn boolean(self, &c: &Const): str { + fn boolean(mut &self, &c: &Const) { if c.read_bool() { - ret "true" + self.oc.write("true") + ret } - ret "false" + self.oc.write("false") } - fn nil_lit(self): str { - ret "nullptr" + fn nil_lit(mut &self) { + self.oc.write("nullptr") } - fn ftoa_special_cases(self, &x: f64): str { + fn ftoa_special_cases(mut &self, &x: f64): bool { match { | math::is_nan(x): - ret "NAN" + self.oc.write("NAN") | math::is_inf(x, 1): - ret "INFINITY" + self.oc.write("INFINITY") | math::is_inf(x, -1): - ret "-INFINITY" + self.oc.write("-INFINITY") |: - ret "" + ret false } + ret true } - fn float32(self, &c: &Const): str { + fn float32(mut &self, &c: &Const) { let x = c.as_f64() // Special cases. - let f = self.ftoa_special_cases(x) - if f != "" { - ret f + if self.ftoa_special_cases(x) { + ret } match { | x == MAX_F32: - ret "jule::MAX_F32" + self.oc.write("jule::MAX_F32") | x == MIN_F32: - ret "jule::MIN_F32" + self.oc.write("jule::MIN_F32") |: - ret ftoa(x, 32) + "f" + self.oc.write(ftoa(x, 1 << 5)) + self.oc.write("f") } } - fn float64(self, &c: &Const): str { + fn float64(mut &self, &c: &Const) { let x = c.as_f64() // Special cases. - let f = self.ftoa_special_cases(x) - if f != "" { - ret f + if self.ftoa_special_cases(x) { + ret } match { | x == MAX_F64: - ret "jule::MAX_F64" + self.oc.write("jule::MAX_F64") | x == MIN_F64: - ret "jule::MIN_F64" + self.oc.write("jule::MIN_F64") |: - ret ftoa(x, 64) + self.oc.write(ftoa(x, 1 << 6)) } } // fx32: 32-bit floating-point - fn constant(self, mut c: &Const, fx32: bool): str { + fn constant(mut &self, mut c: &Const, fx32: bool) { match { | c.is_str(): - ret self.string(c) + self.string(c) | c.is_bool(): - ret self.boolean(c) + self.boolean(c) | c.is_f64(): match { | fx32: - ret self.float32(c) + self.float32(c) |: - ret self.float64(c) + self.float64(c) } | c.is_i64(): - ret itoa(c.read_i64()) + self.oc.write(itoa(c.read_i64())) | c.is_u64(): - ret utoa(c.read_u64()) + self.oc.write(utoa(c.read_u64())) | c.is_nil(): - ret self.nil_lit() + self.nil_lit() |: - ret "" + self.oc.write("") } } - fn div_by_zero_binary(mut self, &op: &Token, mut &l: &OperandExprModel, mut &r: &OperandExprModel): str { - let mut op_func = "" + fn div_by_zero_binary(mut &self, &op: &Token, mut &l: &OperandExprModel, mut &r: &OperandExprModel) { + self.oc.write("jule::") match op.kind { | TokenKind.Solidus | TokenKind.SolidusEq: - op_func = "div" + self.oc.write("div(") | TokenKind.Percent | TokenKind.PercentEq: - op_func = "mod" + self.oc.write("mod(") } - let mut obj = "jule::" - obj += op_func - obj += "(" if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(op) - obj += "\"," + self.oc.write("\"") + self.oc.loc_info(op) + self.oc.write("\",") } - obj += self.expr(l.model) - obj += "," - obj += self.expr(r.model) - obj += ")" - ret obj + self.expr(l.model) + self.oc.write(",") + self.expr(r.model) + self.oc.write(")") } - fn unsafe_binary(mut self, mut m: &BinopExprModel): str { - let mut obj = "(" - obj += self.model(m.left.model) - obj += " " - obj += m.op.kind - obj += " " - obj += self.model(m.right.model) - obj += ")" - ret obj + fn unsafe_binary(mut &self, mut m: &BinopExprModel) { + self.oc.write("(") + self.model(m.left.model) + self.oc.write(" ") + self.oc.write(m.op.kind) + self.oc.write(" ") + self.model(m.right.model) + self.oc.write(")") } - fn binary(mut self, mut m: &BinopExprModel): str { + fn binary(mut &self, mut m: &BinopExprModel) { match m.op.kind { | TokenKind.Solidus | TokenKind.Percent: // Do not check division of structures safety. if m.left.kind.strct() == nil { - ret self.div_by_zero_binary(m.op, m.left, m.right) + self.div_by_zero_binary(m.op, m.left, m.right) + ret } } - ret self.unsafe_binary(m) + self.unsafe_binary(m) } - fn var(self, mut m: &Var): str { + fn var(mut &self, mut m: &Var) { if m.cpp_linked { let d = find_directive(m.directives, Directive.Namespace) if d != nil { - let mut obj = concat_all_parts(d.args...) - obj += "::" - obj += IdentCoder.var(m) - ret obj + self.oc.write(concat_all_parts(d.args...)) + self.oc.write("::") } } - ret IdentCoder.var(m) + self.oc.write(IdentCoder.var(m)) } - fn structure(self, m: &Struct): str { - ret TypeCoder.structure(m) + fn structure(mut &self, m: &Struct) { + self.oc.write(TypeCoder.structure(m)) } - fn structure_ins(self, mut m: &StructIns): str { - ret TypeCoder.structure_ins(m) + fn structure_ins(mut &self, mut m: &StructIns) { + self.oc.write(TypeCoder.structure_ins(m)) } - fn unary(mut self, mut m: &UnaryExprModel): str { + fn unary(mut &self, mut m: &UnaryExprModel) { match m.op.kind { | TokenKind.Caret: - let mut obj = "(~(" - obj += self.expr(m.expr.model) - obj += "))" - ret obj + self.oc.write("(~(") + self.expr(m.expr.model) + self.oc.write("))") + ret | TokenKind.Star: if env::PRODUCTION || m.expr.kind.sptr() == nil { break } - let mut obj = self.expr(m.expr.model) - obj += ".get(\"" - obj += self.oc.loc_info(m.op) - obj += "\")" - ret obj + self.expr(m.expr.model) + self.oc.write(".get(\"") + self.oc.loc_info(m.op) + self.oc.write("\")") + ret } - - let mut obj = "(" - obj += m.op.kind - obj += "(" - obj += self.expr(m.expr.model) - obj += "))" - ret obj + self.oc.write("(") + self.oc.write(m.op.kind) + self.oc.write("(") + self.expr(m.expr.model) + self.oc.write("))") } - fn cpp_structure_lit(mut self, mut m: &StructLitExprModel): str { - let mut obj = "(" + TypeCoder.structure_ins(m.strct) - obj += "){" + fn cpp_structure_lit(mut &self, mut m: &StructLitExprModel) { + self.oc.write("(") + self.oc.write(TypeCoder.structure_ins(m.strct)) + self.oc.write("){") if m.args.len > 0 { iter: for (_, mut f) in m.strct.fields { if m.strct.decl.cpp_linked { - for (_, mut arg) in m.args { + for (i, mut arg) in m.args { if arg.field == f { - obj += "." - obj += IdentCoder.field(f.decl) - obj += "=" - obj += self.expr(arg.expr) - obj += "," + self.oc.write(".") + self.oc.write(IdentCoder.field(f.decl)) + self.oc.write("=") + self.expr(arg.expr) + if m.args.len-i > 1 { + self.oc.write(",") + } continue iter } } continue } - obj += IdentCoder.field(f.decl) - obj += ": " - for (_, mut arg) in m.args { + self.oc.write(IdentCoder.field(f.decl)) + self.oc.write(": ") + for (i, mut arg) in m.args { if arg.field == f { - obj += self.expr(arg.expr) - obj += "," + self.expr(arg.expr) + if m.args.len-i > 1 { + self.oc.write(",") + } continue iter } } - obj += self.init_expr(f.kind) - obj += "," + self.init_expr(f.kind) + self.oc.write(",") } - obj = obj[:obj.len-1] // Remove last comma. } - obj += "}" - ret obj + self.oc.write("}") } - fn structure_lit(mut self, mut m: &StructLitExprModel): str { + fn structure_lit(mut &self, mut m: &StructLitExprModel) { if m.strct.decl.cpp_linked { - ret self.cpp_structure_lit(m) + self.cpp_structure_lit(m) + ret } - let mut obj = IdentCoder.structure_ins(m.strct) - obj += "(" + self.oc.write(IdentCoder.structure_ins(m.strct)) + self.oc.write("(") if m.args.len > 0 { iter: - for (_, mut f) in m.strct.fields { + for (i, mut f) in m.strct.fields { for (_, mut arg) in m.args { if arg.field == f { - obj += self.expr(arg.expr) - obj += "," + self.expr(arg.expr) + if m.strct.fields.len-i > 1 { + self.oc.write(",") + } continue iter } } - obj += self.init_expr(f.kind) - obj += "," + self.init_expr(f.kind) + if m.strct.fields.len-i > 1 { + self.oc.write(",") + } } - obj = obj[:obj.len-1] // Remove last comma. } - obj += ")" - ret obj + self.oc.write(")") } - fn alloc_structure(mut self, mut m: &AllocStructLitExprModel): str { - let mut obj = "jule::new_ptr<" - obj += IdentCoder.structure_ins(m.lit.strct) - obj += ">(" - obj += self.structure_lit(m.lit) - obj += ")" - ret obj + fn alloc_structure(mut &self, mut m: &AllocStructLitExprModel) { + self.oc.write("jule::new_ptr<") + self.oc.write(IdentCoder.structure_ins(m.lit.strct)) + self.oc.write(">(") + self.structure_lit(m.lit) + self.oc.write(")") } - fn casting(mut self, mut m: &CastingExprModel): str { - let mut obj = "" + fn casting(mut &self, mut m: &CastingExprModel) { match { | m.kind.prim() != nil && m.kind.prim().is_any(): - obj += TypeCoder.kind(m.kind) - obj += "(" - obj += self.model(m.expr) - obj += ")" + self.oc.write(TypeCoder.kind(m.kind)) + self.oc.write("(") + self.model(m.expr) + self.oc.write(")") | m.expr_kind.ptr() != nil | m.kind.ptr() != nil: - obj += "((" - obj += TypeCoder.kind(m.kind) - obj += ")(" - obj += self.expr(m.expr) - obj += "))" + self.oc.write("((") + self.oc.write(TypeCoder.kind(m.kind)) + self.oc.write(")(") + self.expr(m.expr) + self.oc.write("))") | m.expr_kind.trt() != nil | m.expr_kind.prim() != nil && m.expr_kind.prim().is_any(): - obj += self.model(m.expr) - obj += "." + self.model(m.expr) + self.oc.write(".") if env::PRODUCTION { - obj += "operator " - obj += TypeCoder.kind(m.kind) - obj += "()" + self.oc.write("operator ") + self.oc.write(TypeCoder.kind(m.kind)) + self.oc.write("()") } else { if m.expr_kind.trt() != nil && m.kind.sptr() != nil { - obj += "cast_ptr<" - obj += TypeCoder.kind(m.kind.sptr().elem) + self.oc.write("cast_ptr<") + self.oc.write(TypeCoder.kind(m.kind.sptr().elem)) } else { - obj += "cast<" - obj += TypeCoder.kind(m.kind) + self.oc.write("cast<") + self.oc.write(TypeCoder.kind(m.kind)) } - obj += ">(\"" - obj += self.oc.loc_info(m.token) - obj += "\")" + self.oc.write(">(\"") + self.oc.loc_info(m.token) + self.oc.write("\")") } | m.kind.trt() != nil: - obj += TypeCoder.kind(m.kind) - obj += "(" - obj += self.expr(m.expr) - obj += ", " - obj += conv::itoa(self.oc.find_type_offset(m.kind.trt(), m.expr_kind)) - obj += ")" + self.oc.write(TypeCoder.kind(m.kind)) + self.oc.write("(") + self.expr(m.expr) + self.oc.write(", ") + self.oc.write(conv::itoa(self.oc.find_type_offset(m.kind.trt(), m.expr_kind))) + self.oc.write(")") |: - obj += "static_cast<" - obj += TypeCoder.kind(m.kind) - obj += ">(" - obj += self.expr(m.expr) - obj += ")" + self.oc.write("static_cast<") + self.oc.write(TypeCoder.kind(m.kind)) + self.oc.write(">(") + self.expr(m.expr) + self.oc.write(")") } - ret obj } - fn args(mut self, mut args: []ExprModel): str { + fn args(mut &self, mut args: []ExprModel) { if args.len == 0 { - ret "" + ret } - let mut obj = "" - for (_, mut a) in args { - obj += self.expr(a) - obj += "," + for (i, mut a) in args { + self.expr(a) + if args.len-i > 1 { + self.oc.write(",") + } } - obj = obj[:obj.len-1] // Remove last comma. - ret obj } - fn model_for_call(mut self, mut expr: ExprModel): str { + fn model_for_call(mut &self, mut expr: ExprModel) { match type expr { | &FnIns: - ret self.func_ins((&FnIns)(expr)) + self.func_ins((&FnIns)(expr)) + ret | &StructSubIdentExprModel: let mut ssie = (&StructSubIdentExprModel)(expr) if ssie.method != nil { - ret self.func_ins(ssie.method) + self.func_ins(ssie.method) + ret } } - ret self.model(expr) + self.model(expr) } - fn push_call_inf(mut self, mut &obj: str, &m: &FnCallExprModel) { + fn push_call_inf(mut &self, &m: &FnCallExprModel) { if env::PRODUCTION || (!m.func.anon && !is_builtin_call_has_debuginf(m)) { - obj += "(" + self.oc.write("(") ret } if m.func.anon { match type m.expr { | &StructSubIdentExprModel: if (&StructSubIdentExprModel)(m.expr).field.decl.owner.cpp_linked { - obj += "(" + self.oc.write("(") ret } fall |: - obj += ".call" + self.oc.write(".call") } } - obj += "(\"" - obj += self.oc.loc_info(m.token) - obj += "\"" + self.oc.write("(\"") + self.oc.loc_info(m.token) + self.oc.write("\"") if m.args.len != 0 { - obj += "," + self.oc.write(",") } } - fn pure_func_call(mut self, mut &m: &FnCallExprModel): str { - let mut obj = self.model_for_call(m.expr) + fn is_wrapped(mut &self, mut &m: &FnCallExprModel): bool { + if !m.func.is_builtin() && m.func.decl.params.len > 0 && m.func.decl.params[0].is_self() { + match type m.expr { + | &StructSubIdentExprModel: + let mut ssie = (&StructSubIdentExprModel)(m.expr) + match { + | m.func.decl.params[0].is_ref() + | ssie.expr_kind.sptr() != nil: + break + |: + if ssie.expr.kind.strct() != nil { + if !ssie.expr.lvalue { + self.oc.write("({ auto _wrap_copy = ") + self.model(ssie.expr) + self.oc.write("; ") + ret true + } + } + } + } + } + ret false + } + + fn pure_func_call(mut &self, mut &m: &FnCallExprModel) { + let wrapped = self.is_wrapped(m) + if m.is_co { + self.oc.write("__JULE_CO(") + } + self.model_for_call(m.expr) if !m.func.is_builtin() { if m.func.decl.cpp_linked && m.func.generics.len > 0 { if !has_directive(m.func.decl.directives, Directive.Cdef) { - obj += "<" - for (_, mut g) in m.func.generics { - obj += TypeCoder.kind(g) - obj += "," + self.oc.write("<") + for (i, mut g) in m.func.generics { + self.oc.write(TypeCoder.kind(g)) + if m.func.generics.len-i > 1 { + self.oc.write(",") + } } - obj = obj[:obj.len-1] // Remove last comma. - obj += ">" + self.oc.write(">") } } } - self.push_call_inf(obj, m) + self.push_call_inf(m) let mut locinfo = false - let mut wrap_receiver = "" if !m.func.is_builtin() && m.func.decl.params.len > 0 && m.func.decl.params[0].is_self() { match type m.expr { | &StructSubIdentExprModel: let mut ssie = (&StructSubIdentExprModel)(m.expr) match { | m.func.decl.params[0].is_ref(): - obj += self.model(ssie.expr) + self.model(ssie.expr) | ssie.expr_kind.sptr() != nil: - obj += self.model(ssie.expr) - obj += ".ptr(" + self.model(ssie.expr) + self.oc.write(".ptr(") if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"" + self.oc.write("\"") + self.oc.loc_info(m.token) + self.oc.write("\"") } - obj += ")" + self.oc.write(")") |: if ssie.expr.kind.strct() != nil { // Add address taking operation for non-pointers. - obj += "&" - if !ssie.expr.lvalue { - wrap_receiver = self.model(ssie.expr) - } + self.oc.write("&") } - if wrap_receiver != "" { - obj += "_wrap_copy" + if wrapped { + self.oc.write("_wrap_copy") } else { - obj += self.model(ssie.expr) + self.model(ssie.expr) } } if m.args.len > 0 { - obj += ", " + self.oc.write(", ") } | &TraitSubIdentExprModel: - obj += self.model((&TraitSubIdentExprModel)(m.expr).expr) + self.model((&TraitSubIdentExprModel)(m.expr).expr) if !env::PRODUCTION { locinfo = true } if m.args.len > 0 { - obj += ", " + self.oc.write(", ") } } } - obj += self.args(m.args) + self.args(m.args) if locinfo { - obj += ", \"" - obj += self.oc.loc_info(m.token) - obj += "\"" + self.oc.write(", \"") + self.oc.loc_info(m.token) + self.oc.write("\"") } - obj += ")" + self.oc.write(")") - if wrap_receiver != "" { - obj = "({ auto _wrap_copy = " + wrap_receiver + "; " + obj - obj += "; })" + if wrapped { + self.oc.write("; })") } if m.is_co { - obj = "__JULE_CO(" + obj - obj += ")" + self.oc.write(")") } - - ret obj } - fn func_call(mut self, mut m: &FnCallExprModel): str { + fn func_call(mut &self, mut m: &FnCallExprModel) { if m.func.is_builtin() || !m.func.decl.exceptional || m.except != nil && m.except.stmts.len == 0 { - ret self.pure_func_call(m) + self.pure_func_call(m) + ret } // Generate code for exceptional. - let mut obj = "({\n" + self.oc.write("({\n") self.oc.add_indent() - obj += self.oc.indent() - obj += "auto except = " - obj += self.pure_func_call(m) - obj += ";\n" - obj += self.oc.indent() + self.oc.indent() + self.oc.write("auto except = ") + self.pure_func_call(m) + self.oc.write(";\n") + self.oc.indent() if m.except != nil { if m.func.result == nil || !m.assigned { - obj += "if (!except.ok()) " - obj += self.oc.sc.scope(m.except) - obj += "\n" + self.oc.write("if (!except.ok()) ") + self.oc.sc.scope(m.except) + self.oc.write("\n") } else { let forwarded = is_forwarded(m.except) - obj += "(except.ok()) ? (except.result) : (" + self.oc.write("(except.ok()) ? (except.result) : (") if forwarded { - obj += "{" + self.oc.write("{") } - obj += self.oc.sc.scope(m.except) + self.oc.sc.scope(m.except) if forwarded { - obj += " " - obj += self.init_expr(m.func.result) - obj += ";}" + self.oc.write(" ") + self.init_expr(m.func.result) + self.oc.write(";}") } - obj += ");\n" + self.oc.write(");\n") } self.oc.done_indent() } else { - obj += `if (!except.ok()) jule::panic(jule::Str("` - obj += `unhandled exceptional: ") + except.error.type->to_str(except.error.data) + jule::Str("\nlocation: ` - obj += self.oc.loc_info(m.token) - obj += "\"));\n" + self.oc.write(`if (!except.ok()) jule::panic(jule::Str("unhandled exceptional: ") + except.error.type->to_str(except.error.data) + jule::Str("\nlocation: `) + self.oc.loc_info(m.token) + self.oc.write("\"));\n") if !m.func.decl.is_void() { - obj += self.oc.indent() - obj += "(except.result);\n" + self.oc.indent() + self.oc.write("(except.result);\n") } self.oc.done_indent() } - obj += self.oc.indent() - obj += "})" - ret obj + self.oc.indent() + self.oc.write("})") } - fn slice(mut self, mut m: &SliceExprModel): str { + fn slice(mut &self, mut m: &SliceExprModel) { if m.elems.len == 0 { - ret TypeCoder.as_slice(m.elem_kind) + "()" + self.oc.write(TypeCoder.as_slice(m.elem_kind)) + self.oc.write("()") + ret } - let mut obj = TypeCoder.as_slice(m.elem_kind) - obj += "({" - obj += self.args(m.elems) - obj += "})" - ret obj + self.oc.write(TypeCoder.as_slice(m.elem_kind)) + self.oc.write("({") + self.args(m.elems) + self.oc.write("})") } - fn indexing(mut self, mut m: &IndexingExprModel): str { - let mut obj = self.model(m.expr.model) + fn indexing(mut &self, mut m: &IndexingExprModel) { + self.model(m.expr.model) // Index access with safety measures. match { | env::PRODUCTION | m.expr.kind.ptr() != nil | m.expr.kind.map() != nil: - obj += "[" - obj += self.expr(m.index.model) - obj += "]" + self.oc.write("[") + self.expr(m.index.model) + self.oc.write("]") |: - obj += ".at(\"" - obj += self.oc.loc_info(m.token) - obj += "\"," - obj += self.expr(m.index.model) - obj += ")" + self.oc.write(".at(\"") + self.oc.loc_info(m.token) + self.oc.write("\",") + self.expr(m.index.model) + self.oc.write(")") } - ret obj } - fn unsafe_indexing(mut self, mut m: &UnsafeIndexingExprModel): str { - let mut obj = self.model(m.node.expr.model) + fn unsafe_indexing(mut &self, mut m: &UnsafeIndexingExprModel) { + self.model(m.node.expr.model) // Index access with safety measures. match { | env::PRODUCTION | m.node.expr.kind.ptr() != nil | m.node.expr.kind.map() != nil: - obj += "[" - obj += self.expr(m.node.index.model) - obj += "]" + self.oc.write("[") + self.expr(m.node.index.model) + self.oc.write("]") |: - obj += ".__at(" - obj += self.expr(m.node.index.model) - obj += ")" - } - ret obj - } - - fn anon_func(mut self, mut m: &AnonFnExprModel): str { - let mut obj = TypeCoder.func(m.func) - obj += "([=]" - obj += self.oc.params_ins(m.func.params) - obj += " mutable -> " - obj += TypeCoder.func_ins_result(m.func) - obj += " " - obj += self.oc.sc.func_scope(m.func) - obj += ")" - ret obj - } - - fn map(mut self, mut m: &MapExprModel): str { - let mut obj = TypeCoder.Map + "<" - obj += TypeCoder.kind(m.key_kind) - obj += "," - obj += TypeCoder.kind(m.val_kind) - obj += ">({" + self.oc.write("__at(") + self.expr(m.node.index.model) + self.oc.write(")") + } + } + + fn anon_func(mut &self, mut m: &AnonFnExprModel) { + self.oc.write(TypeCoder.func(m.func)) + self.oc.write("([=]") + self.oc.params_ins(m.func.params) + self.oc.write(" mutable -> ") + self.oc.write(TypeCoder.func_ins_result(m.func)) + self.oc.write(" ") + self.oc.sc.func_scope(m.func) + self.oc.write(")") + } + + fn map(mut &self, mut m: &MapExprModel) { + self.oc.write(TypeCoder.Map + "<") + self.oc.write(TypeCoder.kind(m.key_kind)) + self.oc.write(",") + self.oc.write(TypeCoder.kind(m.val_kind)) + self.oc.write(">({") if m.entries.len > 0 { - for (_, mut pair) in m.entries { - let mut pair_obj = "{" - pair_obj += self.expr(pair.key) - pair_obj += "," - pair_obj += self.expr(pair.val) - pair_obj += "}" - obj += pair_obj - obj += "," + for (i, mut pair) in m.entries { + self.oc.write("{") + self.expr(pair.key) + self.oc.write(",") + self.expr(pair.val) + self.oc.write("}") + if m.entries.len-i > 1 { + self.oc.write(",") + } } - obj = obj[:obj.len-1] // Remove last comma. } - obj += "})" - ret obj + self.oc.write("})") } - fn slicing(mut self, mut m: &SlicingExprModel): str { - let mut obj = self.model(m.expr) - obj += ".slice(" + fn slicing(mut &self, mut m: &SlicingExprModel) { + self.model(m.expr) + self.oc.write(".slice(") if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"," + self.oc.write("\"") + self.oc.loc_info(m.token) + self.oc.write("\",") } - obj += self.expr(m.left) + self.expr(m.left) if m.right != nil { - obj += "," - obj += self.expr(m.right) + self.oc.write(",") + self.expr(m.right) } - obj += ")" - ret obj + self.oc.write(")") } - fn trait_sub(mut self, mut m: &TraitSubIdentExprModel): str { - let mut obj = IdentCoder.trait_decl(m.trt) - obj += "_mptr_data" - obj += "[(" - obj += self.model(m.expr) - obj += ").type_offset]." - obj += IdentCoder.func(m.method) - ret obj + fn trait_sub(mut &self, mut m: &TraitSubIdentExprModel) { + self.oc.write(IdentCoder.trait_decl(m.trt)) + self.oc.write("_mptr_data") + self.oc.write("[(") + self.model(m.expr) + self.oc.write(").type_offset].") + self.oc.write(IdentCoder.func(m.method)) } - fn structure_sub(mut self, mut m: &StructSubIdentExprModel): str { - let mut obj = self.model(m.expr) + fn structure_sub(mut &self, mut m: &StructSubIdentExprModel) { + self.model(m.expr) if m.field != nil { if m.expr_kind.ptr() != nil { - obj += "->" + self.oc.write("->") } else if m.expr_kind.sptr() != nil { - obj += ".get(" + self.oc.write(".get(") if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"" + self.oc.write("\"") + self.oc.loc_info(m.token) + self.oc.write("\"") } - obj += ")." + self.oc.write(").") } else { - obj += "." + self.oc.write(".") } - obj += IdentCoder.field(m.field.decl) + self.oc.write(IdentCoder.field(m.field.decl)) } - ret obj } - fn common_ident(self, m: &CommonIdentExprModel): str { - ret m.ident + fn common_ident(mut &self, m: &CommonIdentExprModel) { + self.oc.write(m.ident) } - fn common_sub(mut self, mut m: &CommonSubIdentExprModel): str { - let mut obj = self.model(m.expr) + fn common_sub(mut &self, mut m: &CommonSubIdentExprModel) { + self.model(m.expr) match { | m.expr_kind.ptr() != nil: - obj += "->" + self.oc.write("->") | m.expr_kind.sptr() != nil: - obj += ".get(" + self.oc.write(".get(") if !env::PRODUCTION { - obj += "\n" - obj += self.oc.loc_info(m.token) - obj += "\n" + self.oc.write("\n") + self.oc.loc_info(m.token) + self.oc.write("\n") } - obj += ")." + self.oc.write(").") |: - obj += "." + self.oc.write(".") } - obj += m.ident - ret obj + self.oc.write(m.ident) } - fn array(mut self, mut m: &ArrayExprModel): str { - let mut obj = TypeCoder.array(m.kind) + fn array(mut &self, mut m: &ArrayExprModel) { + self.oc.write(TypeCoder.array(m.kind)) if m.elems.len == 0 { - obj += "()" - ret obj + self.oc.write("()") + ret } // Filled. if m.elems.len == 2 && m.elems[1] == nil { - obj += "(" - obj += self.expr(m.elems[0]) - obj += ")" - ret obj + self.oc.write("(") + self.expr(m.elems[0]) + self.oc.write(")") + ret } - obj += "({" - obj += self.args(m.elems) - obj += "})" - ret obj + self.oc.write("({") + self.args(m.elems) + self.oc.write("})") + ret } - // Returns complete expression model of function instance. + // Writes complete expression model of function instance. // Usefull for strict type safety. - fn func_ins_common(self, mut m: &FnIns): str { - let mut obj = TypeCoder.func(m) - obj += "(" - obj += self.func_ins(m) - obj += ")" - ret obj + fn func_ins_common(mut &self, mut m: &FnIns) { + self.oc.write(TypeCoder.func(m)) + self.oc.write("(") + self.func_ins(m) + self.oc.write(")") } - // Returns elementary expression model of function instance. - fn func_ins(self, mut m: &FnIns): str { + fn func_ins(mut &self, mut m: &FnIns) { if m.decl != nil && m.decl.cpp_linked { let d = find_directive(m.decl.directives, Directive.Namespace) if d != nil { - let mut obj = concat_all_parts(d.args...) - obj += "::" - obj += IdentCoder.func_ins(m) - ret obj + self.oc.write(concat_all_parts(d.args...)) + self.oc.write("::") } } - ret IdentCoder.func_ins(m) + self.oc.write(IdentCoder.func_ins(m)) } - fn tuple(mut self, mut m: &TupleExprModel): str { - let mut obj = "std::make_tuple(" - for (_, mut d) in m.datas { - obj += self.expr(d.model) - obj += "," + fn tuple(mut &self, mut m: &TupleExprModel) { + self.oc.write("std::make_tuple(") + for (i, mut d) in m.datas { + self.expr(d.model) + if m.datas.len-i > 1 { + self.oc.write(",") + } } - obj = obj[:obj.len-1] // Remove last comma. - obj += ")" - ret obj + self.oc.write(")") } - fn new_call(mut self, mut m: &BuiltinNewCallExprModel): str { - let mut obj = "jule::new_ptr<" - obj += TypeCoder.kind(m.kind) - obj += ">(" + fn new_call(mut &self, mut m: &BuiltinNewCallExprModel) { + self.oc.write("jule::new_ptr<") + self.oc.write(TypeCoder.kind(m.kind)) + self.oc.write(">(") if m.init != nil { - obj += self.expr(m.init) + self.expr(m.init) } - obj += ")" - ret obj + self.oc.write(")") } - fn out_call(mut self, mut m: &BuiltinOutCallExprModel): str { + fn out_call(mut &self, mut m: &BuiltinOutCallExprModel) { if m.debug && env::PRODUCTION { - ret "" + ret } - let mut obj = "jule::out(" - obj += self.expr(m.expr) - obj += ")" - ret obj + self.oc.write("jule::out(") + self.expr(m.expr) + self.oc.write(")") } - fn outln_call(mut self, mut m: &BuiltinOutlnCallExprModel): str { + fn outln_call(mut &self, mut m: &BuiltinOutlnCallExprModel) { if m.debug && env::PRODUCTION { - ret "" + ret } - let mut obj = "jule::outln(" - obj += self.expr(m.expr) - obj += ")" - ret obj + self.oc.write("jule::outln(") + self.expr(m.expr) + self.oc.write(")") } - fn panic_call(mut self, mut m: &BuiltinPanicCallExprModel): str { - let mut obj = "jule::panic(" - obj += self.expr(m.expr) - obj += ` + jule::Str("\nlocation: ` - obj += self.oc.loc_info(m.token) - obj += "\"));" - ret obj + fn panic_call(mut &self, mut m: &BuiltinPanicCallExprModel) { + self.oc.write("jule::panic(") + self.expr(m.expr) + self.oc.write(` + jule::Str("\nlocation: `) + self.oc.loc_info(m.token) + self.oc.write("\"));") } - fn assert_call(mut self, mut m: &BuiltinAssertCallExprModel): str { + fn assert_call(mut &self, mut m: &BuiltinAssertCallExprModel) { if env::PRODUCTION { - ret "" + ret } - let mut obj = "if (!(" - obj += self.expr(m.expr) - obj += ")) jule::panic(jule::Str(" - obj += cstr_lit([]byte(m.log)) - obj += `) + jule::Str("\nlocation: ` - obj += self.oc.loc_info(m.token) - obj += "\"));" - ret obj + self.oc.write("if (!(") + self.expr(m.expr) + self.oc.write(")) jule::panic(jule::Str(") + self.oc.write(cstr_lit([]byte(m.log))) + self.oc.write(`) + jule::Str("\nlocation: `) + self.oc.loc_info(m.token) + self.oc.write("\"));") } - fn error_call(mut self, mut m: &BuiltinErrorCallExprModel): str { - let mut obj = "return " + fn error_call(mut &self, mut m: &BuiltinErrorCallExprModel) { + self.oc.write("return ") if m.func.decl.is_void() { - obj += "jule::VoidExceptional(" + self.oc.write("jule::VoidExceptional(") } else { - obj += "jule::Exceptional<" - obj += TypeCoder.kind(m.func.result) - obj += ">(" + self.oc.write("jule::Exceptional<") + self.oc.write(TypeCoder.kind(m.func.result)) + self.oc.write(">(") } - obj += self.expr(m.err) - obj += ")" - ret obj + self.expr(m.err) + self.oc.write(")") } - fn make_call(mut self, mut m: &BuiltinMakeCallExprModel): str { - let mut obj = "" + fn make_call(mut &self, mut m: &BuiltinMakeCallExprModel) { + self.oc.write(TypeCoder.kind(m.kind)) + if m.kind.slc().elem.enm() != nil { + if m.cap != nil { + self.oc.write("::alloc(") + } else { + self.oc.write("::alloc_def(") + } + } else { + self.oc.write("::alloc(") + } + if m.len != nil { - obj += self.expr(m.len) + self.expr(m.len) } else { - obj += "0" + self.oc.write("0") } if m.cap != nil { - obj += "," + self.expr(m.cap) + self.oc.write(",") + self.expr(m.cap) } if m.kind.slc().elem.enm() != nil { - obj += "," - obj += self.init_expr(m.kind.slc().elem) - if m.cap != nil { - obj = TypeCoder.kind(m.kind) + "::alloc(" + obj - } else { - obj = TypeCoder.kind(m.kind) + "::alloc_def(" + obj - } - } else { - obj = TypeCoder.kind(m.kind) + "::alloc(" + obj + self.oc.write(",") + self.init_expr(m.kind.slc().elem) } - - obj += ")" - ret obj + self.oc.write(")") } - fn push_to_slice(mut self, mut m: &PushToSliceExprModel): str { - let dest = self.model(m.dest) - let mut obj = dest - obj += " = jule::alloc_for_append(" - obj += dest - obj += "," - obj += conv::itoa(m.elems.elems.len) - obj += ");" + fn push_to_slice(mut &self, mut m: &PushToSliceExprModel) { + self.oc.open_buf_mode() + self.model(m.dest) + let dest = *self.oc.buf + self.oc.close_buf_mode() + + self.oc.write(dest) + self.oc.write(" = jule::alloc_for_append(") + self.oc.write(dest) + self.oc.write(",") + self.oc.write(conv::itoa(m.elems.elems.len)) + self.oc.write(");") for (_, mut e) in m.elems.elems { - obj += dest - // Use the "__push" function to skip allocation boundary checking. - obj += ".__push(" - obj += self.model(e) - obj += ");" + self.oc.write(dest) + // Use the "__push" method to skip allocation boundary checking. + self.oc.write(".__push(") + self.model(e) + self.oc.write(");") } - ret obj } - fn append_call(mut self, mut m: &BuiltinAppendCallExprModel): str { - let mut obj = "jule::append(" - obj += self.model(m.dest) - obj += "," - obj += self.model(m.elements) - obj += ")" - ret obj + fn append_call(mut &self, mut m: &BuiltinAppendCallExprModel) { + self.oc.write("jule::append(") + self.model(m.dest) + self.oc.write(",") + self.model(m.elements) + self.oc.write(")") } - fn clone_call(mut self, mut m: &BuiltinCloneCallExprModel): str { - let mut obj = "jule::clone(" - obj += self.model(m.expr) - obj += ")" - ret obj + fn clone_call(mut &self, mut m: &BuiltinCloneCallExprModel) { + self.oc.write("jule::clone(") + self.model(m.expr) + self.oc.write(")") } - fn sizeof(mut self, mut m: &SizeofExprModel): str { - let mut obj = "sizeof(" - obj += self.expr(m.expr) - obj += ")" - ret obj + fn sizeof(mut &self, mut m: &SizeofExprModel) { + self.oc.write("sizeof(") + self.model(m.expr) + self.oc.write(")") } - fn alignof(mut self, mut m: &AlignofExprModel): str { - let mut obj = "alignof(" - obj += self.expr(m.expr) - obj += ")" - ret obj + fn alignof(mut &self, mut m: &AlignofExprModel) { + self.oc.write("alignof(") + self.model(m.expr) + self.oc.write(")") } - fn rune_lit(self, m: &RuneExprModel): str { + fn rune_lit(mut &self, m: &RuneExprModel): str { if m.code <= 127 { // ASCII let mut b = sbtoa(byte(m.code)) if b == "'" { @@ -959,186 +966,186 @@ impl ExprCoder { ret itoa(i64(m.code)) } - fn structure_static(self, mut m: &StructStaticIdentExprModel): str { - ret IdentCoder.func_ins(m.method) + fn structure_static(mut &self, mut m: &StructStaticIdentExprModel) { + self.oc.write(IdentCoder.func_ins(m.method)) } - fn integrated_to_str(mut self, mut m: &IntegratedToStrExprModel): str { - let mut obj = "jule::to_str(" - obj += self.model(m.expr) - obj += ")" - ret obj + fn integrated_to_str(mut &self, mut m: &IntegratedToStrExprModel) { + self.oc.write("jule::to_str(") + self.model(m.expr) + self.oc.write(")") } - fn backend_emit(mut self, mut m: &BackendEmitExprModel): str { + fn backend_emit(mut &self, mut m: &BackendEmitExprModel) { if m.exprs.len == 0 { - ret m.code + self.oc.write(m.code) + ret } + self.oc.open_buf_mode() for (i, mut expr) in m.exprs { - m.exprs[i] = self.expr(expr) + self.expr(expr) + m.exprs[i] = *self.oc.buf + *self.oc.buf = "" } - ret fmt::format(m.code, m.exprs...) + self.oc.close_buf_mode() + self.oc.write(fmt::format(m.code, m.exprs...)) } - fn free(mut self, mut m: &FreeExprModel): str { + fn free(mut &self, mut m: &FreeExprModel) { + self.expr(m.expr) if env::RC { - ret self.expr(m.expr) + ".dealloc()" + self.oc.write(".dealloc()") + ret } - ret self.expr(m.expr) + ".__free()" + self.oc.write(".__free()") } - fn mut_slicing(mut self, mut m: &MutSlicingExprModel): str { - let mut obj = "(" - obj += self.model(m.expr) - obj += ").mut_slice(" + fn mut_slicing(mut &self, mut m: &MutSlicingExprModel) { + self.oc.write("(") + self.model(m.expr) + self.oc.write(").mut_slice(") if !env::PRODUCTION { - obj += "\"" - obj += self.oc.loc_info(m.token) - obj += "\"," + self.oc.write("\"") + self.oc.loc_info(m.token) + self.oc.write("\",") } - obj += self.expr(m.left) + self.expr(m.left) if m.right != nil { - obj += "," - obj += self.expr(m.right) + self.oc.write(",") + self.expr(m.right) } - obj += ");" - ret obj + self.oc.write(");") } - fn str_insert_begin(mut self, mut m: &StrInsertBeginExprModel): str { - let mut obj = "(" - obj += self.model(m.dest) - obj += ").buffer.insert(0, (" - obj += self.model(m.expr) - obj += "));" - ret obj + fn str_insert_begin(mut &self, mut m: &StrInsertBeginExprModel) { + self.oc.write("(") + self.model(m.dest) + self.oc.write(").buffer.insert(0, (") + self.model(m.expr) + self.oc.write("));") } - fn model(mut self, mut m: ExprModel): str { + fn model(mut &self, mut m: ExprModel) { match type m { | &Data: - ret self.model((&Data)(m).model) + self.model((&Data)(m).model) | &TypeKind: - ret TypeCoder.kind((&TypeKind)(m)) + self.oc.write(TypeCoder.kind((&TypeKind)(m))) | &Const: - ret self.constant((&Const)(m), false) + self.constant((&Const)(m), false) | &Var: - ret self.var((&Var)(m)) + self.var((&Var)(m)) | &Trait: - ret IdentCoder.trait_decl((&Trait)(m)) + IdentCoder.trait_decl((&Trait)(m)) | &Struct: - ret self.structure((&Struct)(m)) + self.structure((&Struct)(m)) | &StructIns: - ret self.structure_ins((&StructIns)(m)) + self.structure_ins((&StructIns)(m)) | &FnIns: - ret self.func_ins_common((&FnIns)(m)) + self.func_ins_common((&FnIns)(m)) | &UnsafeBinopExprModel: - ret self.unsafe_binary((&UnsafeBinopExprModel)(m).node) + self.unsafe_binary((&UnsafeBinopExprModel)(m).node) | &BinopExprModel: - ret self.binary((&BinopExprModel)(m)) + self.binary((&BinopExprModel)(m)) | &UnaryExprModel: - ret self.unary((&UnaryExprModel)(m)) + self.unary((&UnaryExprModel)(m)) | &StructLitExprModel: - ret self.structure_lit((&StructLitExprModel)(m)) + self.structure_lit((&StructLitExprModel)(m)) | &AllocStructLitExprModel: - ret self.alloc_structure((&AllocStructLitExprModel)(m)) + self.alloc_structure((&AllocStructLitExprModel)(m)) | &CastingExprModel: - ret self.casting((&CastingExprModel)(m)) + self.casting((&CastingExprModel)(m)) | &FnCallExprModel: - ret self.func_call((&FnCallExprModel)(m)) + self.func_call((&FnCallExprModel)(m)) | &SliceExprModel: - ret self.slice((&SliceExprModel)(m)) + self.slice((&SliceExprModel)(m)) | &ArrayExprModel: - ret self.array((&ArrayExprModel)(m)) + self.array((&ArrayExprModel)(m)) | &UnsafeIndexingExprModel: - ret self.unsafe_indexing((&UnsafeIndexingExprModel)(m)) + self.unsafe_indexing((&UnsafeIndexingExprModel)(m)) | &IndexingExprModel: - ret self.indexing((&IndexingExprModel)(m)) + self.indexing((&IndexingExprModel)(m)) | &AnonFnExprModel: - ret self.anon_func((&AnonFnExprModel)(m)) + self.anon_func((&AnonFnExprModel)(m)) | &MapExprModel: - ret self.map((&MapExprModel)(m)) + self.map((&MapExprModel)(m)) | &SlicingExprModel: - ret self.slicing((&SlicingExprModel)(m)) + self.slicing((&SlicingExprModel)(m)) | &TraitSubIdentExprModel: - ret self.trait_sub((&TraitSubIdentExprModel)(m)) + self.trait_sub((&TraitSubIdentExprModel)(m)) | &StructSubIdentExprModel: - ret self.structure_sub((&StructSubIdentExprModel)(m)) + self.structure_sub((&StructSubIdentExprModel)(m)) | &CommonIdentExprModel: - ret self.common_ident((&CommonIdentExprModel)(m)) + self.common_ident((&CommonIdentExprModel)(m)) | &CommonSubIdentExprModel: - ret self.common_sub((&CommonSubIdentExprModel)(m)) + self.common_sub((&CommonSubIdentExprModel)(m)) | &TupleExprModel: - ret self.tuple((&TupleExprModel)(m)) + self.tuple((&TupleExprModel)(m)) | &BuiltinOutCallExprModel: - ret self.out_call((&BuiltinOutCallExprModel)(m)) + self.out_call((&BuiltinOutCallExprModel)(m)) | &BuiltinOutlnCallExprModel: - ret self.outln_call((&BuiltinOutlnCallExprModel)(m)) + self.outln_call((&BuiltinOutlnCallExprModel)(m)) | &BuiltinNewCallExprModel: - ret self.new_call((&BuiltinNewCallExprModel)(m)) + self.new_call((&BuiltinNewCallExprModel)(m)) | &BuiltinPanicCallExprModel: - ret self.panic_call((&BuiltinPanicCallExprModel)(m)) + self.panic_call((&BuiltinPanicCallExprModel)(m)) | &BuiltinAssertCallExprModel: - ret self.assert_call((&BuiltinAssertCallExprModel)(m)) + self.assert_call((&BuiltinAssertCallExprModel)(m)) | &BuiltinErrorCallExprModel: - ret self.error_call((&BuiltinErrorCallExprModel)(m)) + self.error_call((&BuiltinErrorCallExprModel)(m)) | &BuiltinMakeCallExprModel: - ret self.make_call((&BuiltinMakeCallExprModel)(m)) + self.make_call((&BuiltinMakeCallExprModel)(m)) | &BuiltinAppendCallExprModel: - ret self.append_call((&BuiltinAppendCallExprModel)(m)) + self.append_call((&BuiltinAppendCallExprModel)(m)) | &BuiltinCloneCallExprModel: - ret self.clone_call((&BuiltinCloneCallExprModel)(m)) + self.clone_call((&BuiltinCloneCallExprModel)(m)) | &SizeofExprModel: - ret self.sizeof((&SizeofExprModel)(m)) + self.sizeof((&SizeofExprModel)(m)) | &AlignofExprModel: - ret self.alignof((&AlignofExprModel)(m)) + self.alignof((&AlignofExprModel)(m)) | &RuneExprModel: - ret self.rune_lit((&RuneExprModel)(m)) + self.oc.write(self.rune_lit((&RuneExprModel)(m))) | &StructStaticIdentExprModel: - ret self.structure_static((&StructStaticIdentExprModel)(m)) + self.structure_static((&StructStaticIdentExprModel)(m)) | &IntegratedToStrExprModel: - ret self.integrated_to_str((&IntegratedToStrExprModel)(m)) + self.integrated_to_str((&IntegratedToStrExprModel)(m)) | &BackendEmitExprModel: - ret self.backend_emit((&BackendEmitExprModel)(m)) + self.backend_emit((&BackendEmitExprModel)(m)) | &FreeExprModel: - ret self.free((&FreeExprModel)(m)) + self.free((&FreeExprModel)(m)) | &MutSlicingExprModel: - ret self.mut_slicing((&MutSlicingExprModel)(m)) + self.mut_slicing((&MutSlicingExprModel)(m)) | &StrInsertBeginExprModel: - ret self.str_insert_begin((&StrInsertBeginExprModel)(m)) + self.str_insert_begin((&StrInsertBeginExprModel)(m)) |: - ret "" + self.oc.write("") } } - fn expr(mut self, mut e: ExprModel): str { - let mut obj = self.model(e) - if obj.len == 0 || obj[0] != '(' { - ret obj - } - match type e { - | &BinopExprModel: - obj = obj[1:obj.len-1] - } - ret obj + fn expr(mut &self, mut e: ExprModel) { + self.model(e) } - fn val(mut self, mut v: &Value): str { + fn val(mut &self, mut v: &Value) { if v.data.is_const() { - ret self.constant(v.data.constant, v.data.kind != nil && v.data.kind.prim().is_f32()) + self.constant(v.data.constant, v.data.kind != nil && v.data.kind.prim().is_f32()) + ret } - ret self.expr(v.data.model) + self.expr(v.data.model) } - fn init_expr(mut self, mut t: &TypeKind): str { + fn init_expr(mut &self, mut t: &TypeKind) { if t.ptr() != nil { - ret "nullptr" + self.oc.write("nullptr") + ret } let mut enm = t.enm() if enm != nil { - ret self.val(enm.items[0].value) + self.val(enm.items[0].value) + ret } - ret TypeCoder.kind(t) + "()" + self.oc.write(TypeCoder.kind(t)) + self.oc.write("()") } } @@ -1271,4 +1278,4 @@ fn is_builtin_call_has_debuginf(&m: &FnCallExprModel): bool { |: ret false } -} +} \ No newline at end of file diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 495bf1a3c..579828dd7 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -59,6 +59,10 @@ pub struct ObjectCoder { // Current indentation. indent_buffer: []byte + // Internal buffer which is preferred to write if not nil. + // It might be useful to get some part of content which will generate. + buf: &str + ec: &ExprCoder sc: &ScopeCoder } @@ -75,8 +79,25 @@ impl ObjectCoder { ret oc } - fn write(mut &self, mut s: str) { - _ = self.f.write([]byte(s))! + fn open_buf_mode(mut &self) { + static mut buf = "" + if self.buf == nil { + self.buf = unsafe { (&str)(&buf) } + } + } + + fn close_buf_mode(mut &self) { + *self.buf = "" + self.buf = nil + } + + fn write(mut &self, s: str) { + if self.buf != nil { + *self.buf += s + ret + } + let bytes = []byte(s) + _ = self.f.write(bytes)! } // Increase indentation. @@ -91,31 +112,10 @@ impl ObjectCoder { } // Writes indention string by indent_buffer. - fn indent(mut &self): str { - ret str(self.indent_buffer) + fn indent(mut &self) { _ = self.f.write(self.indent_buffer)! } - fn var_init_expr(mut &self, mut &v: &Var, init: str): str { - let mut obj = "" - if v.statically { - obj += "static " - } - - obj += TypeCoder.kind(v.kind.kind) - obj += " " - if v.reference { - obj += "&" - } - obj += IdentCoder.var(v) - if init != "" { - obj += " = " - obj += init - } - obj += ";" - ret obj - } - fn find_type_offset(self, t: &Trait, mut k: &TypeKind): int { let mut s: &StructIns = nil if k.sptr() != nil { @@ -287,9 +287,9 @@ impl ObjectCoder { if f.default == nil { // No default expression. // Use default expression of data-type. - self.write(self.ec.init_expr(f.kind)) + self.ec.init_expr(f.kind) } else { - self.write(self.ec.expr(f.default.model)) + self.ec.expr(f.default.model) } self.write(";") } @@ -661,47 +661,66 @@ impl ObjectCoder { }) } - fn param_ins(mut &self, mut &p: &ParamIns): str { - let mut obj = TypeCoder.param_ins(p) - obj += " " - obj += IdentCoder.param(p.decl) - ret obj + fn param_ins(mut &self, mut &p: &ParamIns) { + self.write(TypeCoder.param_ins(p)) + self.write(" ") + self.write(IdentCoder.param(p.decl)) } - fn params_ins(mut &self, mut ¶ms: []&ParamIns): str { + fn params_ins(mut &self, mut ¶ms: []&ParamIns) { if params.len == 0 { - ret "(void)" + self.write("(void)") + ret } - let mut obj = "(" + self.write("(") for (i, mut p) in params { - obj += self.param_ins(p) + self.param_ins(p) if params.len-i > 1 { - obj += ", " + self.write(", ") } } - obj += ")" - ret obj + self.write(")") } - fn var(mut &self, mut v: &Var): str { + fn var_init_expr(mut &self, mut &v: &Var, init: fn()) { + if v.statically { + self.write("static ") + } + + self.write(TypeCoder.kind(v.kind.kind)) + self.write(" ") + if v.reference { + self.write("&") + } + self.write(IdentCoder.var(v)) + if init != nil { + self.write(" = ") + init() + } + self.write(";") + } + + fn var(mut &self, mut v: &Var) { if is_ignore_ident(v.ident) { - ret "" + ret } if v.value != nil && v.value.expr != nil { if v.value.data.model != nil { - ret self.var_init_expr(v, self.ec.val(v.value)) + self.var_init_expr(v, fn() { self.ec.val(v.value) }) + ret } - ret self.var_init_expr(v, "") + self.var_init_expr(v, nil) + ret } - ret self.var_init_expr(v, self.ec.init_expr(v.kind.kind)) + self.var_init_expr(v, fn() { self.ec.init_expr(v.kind.kind) }) } fn func(mut &self, mut &f: &Fn) { for (_, mut ins) in f.instances { self.func_head(ins, false) - self.write(self.params_ins(ins.params)) + self.params_ins(ins.params) self.write(" ") - self.write(self.sc.func_scope(ins)) + self.sc.func_scope(ins) if ins.scope != nil { self.write("\n\n") } @@ -802,7 +821,7 @@ impl ObjectCoder { iter_files(pkg, fn(mut &file: &SymbolTable) { for (_, mut v) in file.vars { if v.token == nil || v.cpp_linked || v.constant { - ret + continue } self.write(TypeCoder.kind(v.kind.kind)) self.write(" ") @@ -970,18 +989,18 @@ impl ObjectCoder { iter_files(pkg, fn(mut &file: &SymbolTable) { for (_, mut v) in file.vars { if v.token == nil || v.cpp_linked || v.constant { - ret + continue } self.indent() self.write(IdentCoder.var(v)) if v.value != nil && v.value.expr != nil { if v.value.data.model != nil { self.write(" = ") - self.write(self.ec.val(v.value)) + self.ec.val(v.value) } } else { self.write(" = ") - self.write(self.ec.init_expr(v.kind.kind)) + self.ec.init_expr(v.kind.kind) } self.write(";\n") } diff --git a/src/julec/obj/cxx/scope.jule b/src/julec/obj/cxx/scope.jule index b8a578b49..33909b82f 100644 --- a/src/julec/obj/cxx/scope.jule +++ b/src/julec/obj/cxx/scope.jule @@ -50,397 +50,371 @@ impl ScopeCoder { } } - fn range_index_iter(mut self, mut &it: &RangeIter): str { + fn range_index_iter(mut &self, mut &it: &RangeIter) { let begin = IdentCoder.iter_begin(uintptr(it)) let next = IdentCoder.iter_next(uintptr(it)) - let mut obj = "{\n" + self.oc.write("{\n") self.oc.add_indent() - obj += self.oc.indent() - obj += "auto " + self.oc.indent() + self.oc.write("auto ") if env::OPT_COPY && is_copy_optimizable(it.expr) { - obj += "&" - } - obj += "expr = " - obj += self.oc.ec.model(it.expr.model) - obj += ";\n" - obj += self.oc.indent() - obj += "auto it = expr.begin();\n" - obj += self.oc.indent() - obj += begin - obj += ":;\n" - obj += self.oc.indent() - obj += "if (it != expr.end()) {\n" + self.oc.write("&") + } + self.oc.write("expr = ") + self.oc.ec.model(it.expr.model) + self.oc.write(";\n") + self.oc.indent() + self.oc.write("auto it = expr.begin();\n") + self.oc.indent() + self.oc.write(begin) + self.oc.write(":;\n") + self.oc.indent() + self.oc.write("if (it != expr.end()) {\n") self.oc.add_indent() - obj += self.oc.indent() + self.oc.indent() if it.key_a != nil { - obj += self.oc.var_init_expr(it.key_a, "it - expr.begin()") - obj += "\n" - obj += self.oc.indent() + self.oc.var_init_expr(it.key_a, fn() { self.oc.write("it - expr.begin()") }) + self.oc.write("\n") + self.oc.indent() } if it.key_b != nil { if env::OPT_COPY { it.key_b.reference = is_iter_copy_optimizable(it.expr, it.key_b) } - obj += self.oc.var_init_expr(it.key_b, "*it") - obj += "\n" - obj += self.oc.indent() - } - obj += self.scope(it.scope) - obj += "\n" - obj += self.oc.indent() - obj += next - obj += ":;\n" - obj += self.oc.indent() - obj += "++it;\n" - obj += self.oc.indent() + self.oc.var_init_expr(it.key_b, fn() { self.oc.write("*it") }) + self.oc.write("\n") + self.oc.indent() + } + self.scope(it.scope) + self.oc.write("\n") + self.oc.indent() + self.oc.write(next) + self.oc.write(":;\n") + self.oc.indent() + self.oc.write("++it;\n") + self.oc.indent() if it.key_a != nil { - obj += IdentCoder.var(it.key_a) - obj += "++;\n" - obj += self.oc.indent() + self.oc.write(IdentCoder.var(it.key_a)) + self.oc.write("++;\n") + self.oc.indent() } - obj += "goto " - obj += begin - obj += ";\n" + self.oc.write("goto ") + self.oc.write(begin) + self.oc.write(";\n") // Close if. self.oc.done_indent() - obj += self.oc.indent() - obj += "}\n" + self.oc.indent() + self.oc.write("}\n") - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;\n" + self.oc.indent() + self.oc.write(IdentCoder.iter_end(uintptr(it))) + self.oc.write(":;\n") // Close scope. self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - ret obj + self.oc.indent() + self.oc.write("}") } - fn range_hashmap_iter(mut self, mut &it: &RangeIter): str { + fn range_hashmap_iter(mut &self, mut &it: &RangeIter) { let begin = IdentCoder.iter_begin(uintptr(it)) let next = IdentCoder.iter_next(uintptr(it)) - let mut obj = "{\n" + self.oc.write("{\n") self.oc.add_indent() - obj += self.oc.indent() - obj += "auto " + self.oc.indent() + self.oc.write("auto ") if env::OPT_COPY && is_copy_optimizable(it.expr) { - obj += "&" - } - obj += "expr = " - obj += self.oc.ec.model(it.expr.model) - obj += ";\n" - obj += self.oc.indent() - obj += "auto it = expr.begin();\n" - obj += self.oc.indent() - obj += begin - obj += ":;\n" - obj += self.oc.indent() - obj += "if (it != expr.end()) {\n" + self.oc.write("&") + } + self.oc.write("expr = ") + self.oc.ec.model(it.expr.model) + self.oc.write(";\n") + self.oc.indent() + self.oc.write("auto it = expr.begin();\n") + self.oc.indent() + self.oc.write(begin) + self.oc.write(":;\n") + self.oc.indent() + self.oc.write("if (it != expr.end()) {\n") self.oc.add_indent() - obj += self.oc.indent() + self.oc.indent() if it.key_a != nil { if env::OPT_COPY { it.key_a.reference = is_iter_copy_optimizable(it.expr, it.key_a) } - obj += self.oc.var_init_expr(it.key_a, "it->first") - obj += "\n" - obj += self.oc.indent() + self.oc.var_init_expr(it.key_a, fn() { self.oc.write("it->first") }) + self.oc.write("\n") + self.oc.indent() } if it.key_b != nil { if env::OPT_COPY { it.key_b.reference = is_iter_copy_optimizable(it.expr, it.key_b) } - obj += self.oc.var_init_expr(it.key_b, "it->second") - obj += "\n" - obj += self.oc.indent() - } - obj += self.scope(it.scope) - obj += "\n" - obj += self.oc.indent() - obj += next - obj += ":;\n" - obj += self.oc.indent() - obj += "++it;\n" - obj += self.oc.indent() - obj += "goto " - obj += begin - obj += ";\n" + self.oc.var_init_expr(it.key_b, fn() { self.oc.write("it->second") }) + self.oc.write("\n") + self.oc.indent() + } + self.scope(it.scope) + self.oc.write("\n") + self.oc.indent() + self.oc.write(next) + self.oc.write(":;\n") + self.oc.indent() + self.oc.write("++it;\n") + self.oc.indent() + self.oc.write("goto ") + self.oc.write(begin) + self.oc.write(";\n") // Close if. self.oc.done_indent() - obj += self.oc.indent() - obj += "}\n" + self.oc.indent() + self.oc.write("}\n") - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;\n" + self.oc.indent() + self.oc.write(IdentCoder.iter_end(uintptr(it))) + self.oc.write(":;\n") // Close scope. self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - ret obj + self.oc.indent() + self.oc.write("}") } - fn if_case(mut self, mut i: &If): str { - let mut obj = "" + fn if_case(mut &self, mut i: &If) { if i.expr != nil { - obj += "if (" - obj += self.oc.ec.expr(i.expr) - obj += ") " + self.oc.write("if (") + self.oc.ec.expr(i.expr) + self.oc.write(") ") } - obj += self.scope(i.scope) - ret obj + self.scope(i.scope) } - fn conditional(mut self, mut c: &Conditional): str { - let mut obj = "" + fn conditional(mut &self, mut c: &Conditional) { + let mut writed = false for (_, mut elif) in c.elifs { if elif == nil { continue } - if obj.len != 0 { - obj += " else " + if writed { + self.oc.write(" else ") } - obj += self.if_case(elif) + writed = true + self.if_case(elif) } if c.default != nil { - if obj.len != 0 { - obj += " else " + if writed { + self.oc.write(" else ") } - obj += self.scope(c.default.scope) + self.scope(c.default.scope) } - ret obj } - fn inf_iter(mut self, mut it: &InfIter): str { - let mut obj = "for (;;) {\n" - + fn inf_iter(mut &self, mut it: &InfIter) { + self.oc.write("for (;;) {\n") self.oc.add_indent() // Indent scope. - obj += self.oc.indent() - obj += self.scope(it.scope) + self.oc.indent() + self.scope(it.scope) self.oc.done_indent() - - obj += "\n" - obj += self.oc.indent() - obj += IdentCoder.iter_next(uintptr(it)) - obj += ":;\n" - obj += self.oc.indent() - obj += "}\n" - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;" - - ret obj - } - - fn while_iter(mut self, mut it: &WhileIter): str { - let mut obj = "" + self.oc.write("\n") + self.oc.indent() + self.oc.write(IdentCoder.iter_next(uintptr(it))) + self.oc.write(":;\n") + self.oc.indent() + self.oc.write("}\n") + self.oc.indent() + self.oc.write(IdentCoder.iter_end(uintptr(it))) + self.oc.write(":;") + } + + fn while_iter(mut &self, mut it: &WhileIter) { if it.expr != nil && it.next == nil { - obj += "while (" - obj += self.oc.ec.expr(it.expr) - obj += ") {\n" + self.oc.write("while (") + self.oc.ec.expr(it.expr) + self.oc.write(") {\n") } else { - obj += "for (; " + self.oc.write("for (; ") if it.expr != nil { - obj += self.oc.ec.expr(it.expr) + self.oc.ec.expr(it.expr) } - obj += "; " + self.oc.write("; ") if it.next != nil { - let st = self.st(it.next) - obj += st[:st.len-1] + self.st(it.next) } - obj += ") {\n" + self.oc.write(") {\n") } self.oc.add_indent() - obj += self.oc.indent() - obj += self.scope(it.scope) - obj += "\n" + self.oc.indent() + self.scope(it.scope) + self.oc.write("\n") self.oc.done_indent() - obj += self.oc.indent() + self.oc.indent() - obj += IdentCoder.iter_next(uintptr(it)) - obj += ":;\n" - obj += self.oc.indent() - obj += "}\n" - obj += self.oc.indent() - obj += IdentCoder.iter_end(uintptr(it)) - obj += ":;" - ret obj + self.oc.write(IdentCoder.iter_next(uintptr(it))) + self.oc.write(":;\n") + self.oc.indent() + self.oc.write("}\n") + self.oc.indent() + self.oc.write(IdentCoder.iter_end(uintptr(it))) + self.oc.write(":;") } - fn range_iter(mut self, mut it: &RangeIter): str { + fn range_iter(mut &self, mut it: &RangeIter) { match { | it.expr.kind.slc() != nil: - ret self.range_index_iter(it) + self.range_index_iter(it) | it.expr.kind.arr() != nil: - ret self.range_index_iter(it) + self.range_index_iter(it) | it.expr.kind.map() != nil: - ret self.range_hashmap_iter(it) + self.range_hashmap_iter(it) |: - ret self.range_index_iter(it) // Str + self.range_index_iter(it) // Str } } - fn cont(self, c: &ContSt): str { - let mut obj = "goto " - obj += IdentCoder.iter_next(c.it) - obj += ";" - ret obj + fn cont(mut &self, c: &ContSt) { + self.oc.write("goto ") + self.oc.write(IdentCoder.iter_next(c.it)) } - fn label(self, l: &Label): str { - ret IdentCoder.label(l.ident) + ":;" + fn label(mut &self, l: &Label) { + self.oc.write(IdentCoder.label(l.ident)) + self.oc.write(":") } - fn goto_st(self, gt: &GotoSt): str { - let mut obj = "goto " - obj += IdentCoder.label(gt.ident) - obj += ";" - ret obj + fn goto_st(mut &self, gt: &GotoSt) { + self.oc.write("goto ") + self.oc.write(IdentCoder.label(gt.ident)) } - fn postfix(mut self, mut p: &Postfix): str { - let mut obj = "(" - obj += self.oc.ec.expr(p.expr) - obj += ")" - obj += p.op - obj += ";" - ret obj + fn postfix(mut &self, mut p: &Postfix) { + self.oc.write("(") + self.oc.ec.expr(p.expr) + self.oc.write(")") + self.oc.write(p.op) } - fn assign(mut self, mut a: &Assign): str { - let mut obj = self.oc.ec.expr(a.l.model) - obj += a.op.kind - obj += self.oc.ec.expr(a.r.model) - obj += ";" - ret obj + fn assign(mut &self, mut a: &Assign) { + self.oc.ec.expr(a.l.model) + self.oc.write(a.op.kind) + self.oc.ec.expr(a.r.model) } - fn multi_assign(mut self, mut a: &MultiAssign): str { - let mut obj = "std::tie(" - - for (_, mut l) in a.l { + fn multi_assign(mut &self, mut a: &MultiAssign) { + self.oc.write("std::tie(") + for (i, mut l) in a.l { if l == nil { - obj += CPP_IGNORE + self.oc.write(CPP_IGNORE) } else { - obj += self.oc.ec.expr(l) + self.oc.ec.expr(l) + } + if a.l.len-i > 1 { + self.oc.write(",") } - obj += "," } - obj = obj[:obj.len-1] // Remove last comma. - - obj += ") = " - obj += self.oc.ec.expr(a.r) - obj += ";" - ret obj + self.oc.write(") = ") + self.oc.ec.expr(a.r) } - fn match_expr(mut self, mut &m: &Match): str { + fn match_expr(mut &self, mut m: &Match): fn() { if !m.expr.is_const() { - ret MATCH_EXPR + ret fn() { self.oc.write(MATCH_EXPR) } } if !m.expr.constant.is_bool() || !m.expr.constant.read_bool() { - ret self.oc.ec.model(m.expr.model) + ret fn() { self.oc.ec.model(m.expr.model) } } - ret "" + ret nil } - fn case(mut self, mut m: &Match, mut c: &Case): str { - let mut obj = "" - + fn case(mut &self, mut m: &Match, mut c: &Case) { if c.exprs.len != 0 && !m.is_generic_type_match() { if m.cases.len > 0 && m.cases[0] == c { - obj += "if (" + self.oc.write("if (") } else { - obj += "else if (" + self.oc.write("else if (") } for (i, mut expr) in c.exprs { match { | !m.type_match: let case_expr = self.match_expr(m) if m.expr.good_operand(expr) { - if case_expr.len != 0 { - obj += case_expr - obj += " == " + if case_expr != nil { + case_expr() + self.oc.write(" == ") } - obj += self.oc.ec.expr(expr.model) + self.oc.ec.expr(expr.model) } else { - obj += self.oc.ec.expr(expr.model) - if case_expr.len != 0 { - obj += " == " - obj += case_expr + self.oc.ec.expr(expr.model) + if case_expr != nil { + self.oc.write(" == ") + case_expr() } } |: - obj += MATCH_EXPR - obj += ".type_is<" - obj += self.oc.ec.expr(expr.model) - obj += ">()" + self.oc.write(MATCH_EXPR) + self.oc.write(".type_is<") + self.oc.ec.expr(expr.model) + self.oc.write(">()") } - if i+1 < c.exprs.len { - obj += " || " + if c.exprs.len-i > 1 { + self.oc.write(" || ") } } - obj += ") " + self.oc.write(") ") } else if m.default == c && m.cases.len != 0 { - obj += self.oc.indent() - obj += "else " + self.oc.indent() + self.oc.write("else ") } self.oc.add_indent() - obj += "{\n" - obj += self.oc.indent() - obj += IdentCoder.case_begin(uintptr(c)) - obj += ":;\n" + self.oc.write("{\n") + self.oc.indent() + self.oc.write(IdentCoder.case_begin(uintptr(c))) + self.oc.write(":;\n") if c.scope.stmts.len > 0 { - obj += self.oc.indent() - obj += self.scope(c.scope) - obj += "\n" + self.oc.indent() + self.scope(c.scope) + self.oc.write("\n") } self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - ret obj + self.oc.indent() + self.oc.write("}") } - fn match_st(mut self, mut m: &Match): str { + fn match_st(mut &self, mut m: &Match) { if m.cases.len == 0 && m.default == nil { - ret "" + ret } let generic_type_match = m.is_generic_type_match() if generic_type_match && (m.default == nil || m.default.scope.stmts.len == 0) { - ret "" + ret } - let mut obj = "{\n" + self.oc.write("{\n") self.oc.add_indent() - obj += self.oc.indent() + self.oc.indent() // Constant expressions generated as literals in conditions. if !generic_type_match && !m.expr.is_const() { if env::OPT_COPY && is_copy_optimizable(m.expr) { - obj += "auto &_match_expr{ " + self.oc.write("auto &_match_expr{ ") } else { - obj += "auto _match_expr{ " + self.oc.write("auto _match_expr{ ") } - obj += self.oc.ec.expr(m.expr.model) - obj += " };\n" - obj += self.oc.indent() + self.oc.ec.expr(m.expr.model) + self.oc.write(" };\n") + self.oc.indent() } if m.cases.len > 0 { @@ -448,90 +422,75 @@ impl ScopeCoder { if c == nil { continue } - obj += "\n" - obj += self.oc.indent() - obj += self.case(m, c) + self.oc.write("\n") + self.oc.indent() + self.case(m, c) } } if m.default != nil { - obj += "\n" - obj += self.case(m, m.default) + self.oc.write("\n") + self.case(m, m.default) } - obj += "\n" - obj += self.oc.indent() - obj += IdentCoder.match_end(uintptr(m)) - obj += ":;" - obj += "\n" + self.oc.write("\n") + self.oc.indent() + self.oc.write(IdentCoder.match_end(uintptr(m))) + self.oc.write(":;") + self.oc.write("\n") self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - ret obj + self.oc.indent() + self.oc.write("}") } - fn fall_st(self, f: &FallSt): str { - let mut obj = "goto " - obj += IdentCoder.case_begin(f.dest_case) - obj += ";" - ret obj + fn fall_st(mut &self, f: &FallSt) { + self.oc.write("goto ") + self.oc.write(IdentCoder.case_begin(f.dest_case)) } - fn break_st(self, b: &BreakSt): str { - let mut obj = "goto " + fn break_st(mut &self, b: &BreakSt) { + self.oc.write("goto ") if b.it != 0 { - obj += IdentCoder.iter_end(b.it) + self.oc.write(IdentCoder.iter_end(b.it)) } else { - obj += IdentCoder.match_end(b.mtch) + self.oc.write(IdentCoder.match_end(b.mtch)) } - obj += ";" - ret obj } - fn ret_with_vars(mut self, mut r: &RetSt): str { - let mut obj = "" - for (_, mut v) in r.vars { + fn ret_with_vars(mut &self, mut r: &RetSt) { + self.oc.write("return ") + if r.func.decl.exceptional { + self.oc.write("jule::Exceptional<") + self.oc.write(TypeCoder.kind(r.func.result)) + self.oc.write(">(jule::Any(), ") + } + if r.vars.len > 1 { + self.oc.write("std::make_tuple(") + } + for (i, mut v) in r.vars { if lex::is_ignore_ident(v.ident) { - obj += self.oc.ec.init_expr(v.kind.kind) + self.oc.ec.init_expr(v.kind.kind) } else { - obj += IdentCoder.var(v) + self.oc.write(IdentCoder.var(v)) + } + if r.vars.len-i > 1 { + self.oc.write(",") } - obj += "," - } - - obj = obj[:obj.len-1] // Remove last comma. - - let mut oobj = "return " - - if r.func.decl.exceptional { - oobj += "jule::Exceptional<" - oobj += TypeCoder.kind(r.func.result) - oobj += ">(jule::Any(), " } if r.vars.len > 1 { - oobj += "std::make_tuple(" - oobj += obj - oobj += ")" - } else { - oobj += obj + self.oc.write(")") } if r.func.decl.exceptional { - oobj += ")" + self.oc.write(")") } - - oobj += ";" - ret oobj } - fn ret_tuple(mut self, mut r: &RetSt): str { + fn ret_tuple(mut &self, mut r: &RetSt) { let mut datas = (&TupleExprModel)(r.expr).datas - let mut obj = "" - for (i, mut v) in r.vars { if lex::is_ignore_ident(v.ident) { continue @@ -541,46 +500,44 @@ impl ScopeCoder { if model == v { continue } - let ident = IdentCoder.var(v) - obj += ident - obj += " = " - obj += self.oc.ec.expr(model) - obj += ";\n" - obj += self.oc.indent() + self.oc.write(IdentCoder.var(v)) + self.oc.write(" = ") + self.oc.ec.expr(model) + self.oc.write(";\n") + self.oc.indent() + } + + if r.func.decl.exceptional { + self.oc.write("return jule::Exceptional<") + self.oc.write(TypeCoder.kind(r.func.result)) + self.oc.write(">(jule::Any(),") + } else { + self.oc.write("return ") } - let mut oobj = "std::make_tuple(" + self.oc.write("std::make_tuple(") for (i, mut d) in datas { let mut v = r.vars[i] if lex::is_ignore_ident(v.ident) { - oobj += self.oc.ec.expr(d.model) + self.oc.ec.expr(d.model) } else { - oobj += IdentCoder.var(v) + self.oc.write(IdentCoder.var(v)) + } + if datas.len-i > 1 { + self.oc.write(",") } - - oobj += "," } - oobj = oobj[:oobj.len-1] // Remove last comma. - oobj += ")" + self.oc.write(")") if r.func.decl.exceptional { - obj += "return jule::Exceptional<" - obj += TypeCoder.kind(r.func.result) - obj += ">(jule::Any()," - obj += oobj - obj += ")" - } else { - obj += "return " - obj += oobj + self.oc.write(")") } - - obj += ";" - ret obj } - fn ret_with_exprs(mut self, mut r: &RetSt): str { + fn ret_with_exprs(mut &self, mut r: &RetSt) { if r.vars.len > 1 { - ret self.ret_tuple(r) + self.ret_tuple(r) + ret } // Ignore self assignments and ignored variables. @@ -588,162 +545,161 @@ impl ScopeCoder { let mut v = r.vars[0] if !lex::is_ignore_ident(v.ident) && r.expr != v { let ident = IdentCoder.var(v) - let mut obj = ident - obj += " = " - obj += self.oc.ec.expr(r.expr) - obj += ";\n" - obj += self.oc.indent() + self.oc.write(ident) + self.oc.write(" = ") + self.oc.ec.expr(r.expr) + self.oc.write(";\n") + self.oc.indent() if r.func.decl.exceptional { - obj += "return jule::Exceptional<" - obj += TypeCoder.kind(r.func.result) - obj += ">(jule::Any()," - obj += ident - obj += ")" + self.oc.write("return jule::Exceptional<") + self.oc.write(TypeCoder.kind(r.func.result)) + self.oc.write(">(jule::Any(),") + self.oc.write(ident) + self.oc.write(")") } else { - obj += "return " - obj += ident + self.oc.write("return ") + self.oc.write(ident) } - obj += ";" - ret obj + ret } } if r.func.decl.exceptional { - let mut obj = "return jule::Exceptional<" - obj += TypeCoder.kind(r.func.result) - obj += ">(jule::Any()," - obj += self.oc.ec.expr(r.expr) - obj += ")" - obj += ";" - ret obj + self.oc.write("return jule::Exceptional<") + self.oc.write(TypeCoder.kind(r.func.result)) + self.oc.write(">(jule::Any(),") + self.oc.ec.expr(r.expr) + self.oc.write(")") + ret } - let mut obj = "return " - obj += self.oc.ec.expr(r.expr) - obj += ";" - ret obj + self.oc.write("return ") + self.oc.ec.expr(r.expr) + ret } - fn ret_st(mut self, mut r: &RetSt): str { + fn ret_st(mut &self, mut r: &RetSt) { // Void. if r.expr == nil && r.vars.len == 0 { if r.func.decl.exceptional { - ret "return jule::VoidExceptional();" + self.oc.write("return jule::VoidExceptional();") + ret } - ret "return;" + self.oc.write("return;") + ret } if r.expr == nil { - ret self.ret_with_vars(r) + self.ret_with_vars(r) + ret } - ret self.ret_with_exprs(r) + self.ret_with_exprs(r) } - fn ret_with_defaults(mut self, mut result: &TypeKind): str { - let mut obj = "return " + fn ret_with_defaults(mut &self, mut result: &TypeKind) { + self.oc.write("return ") if result.tup() != nil { - obj += "std::make_tuple(" - for (_, mut t) in result.tup().types { - obj += self.oc.ec.init_expr(t) - obj += "," + self.oc.write("std::make_tuple(") + let mut types = result.tup().types + for (i, mut t) in types { + self.oc.ec.init_expr(t) + if types.len-i > 1 { + self.oc.write(",") + } } - obj = obj[:obj.len-1] // Remove last comma. - obj += ")" + self.oc.write(")") } else { - obj += self.oc.ec.init_expr(result) + self.oc.ec.init_expr(result) } - obj += ";" - ret obj } - fn var(mut self, mut v: &Var): str { - if v.constant { - ret "" + fn var(mut &self, mut v: &Var) { + if !v.constant { + self.oc.var(v) } - ret self.oc.var(v) } // Generates C++ code of statement. - fn st(mut self, mut st: St): str { + fn st(mut &self, mut st: St) { if st == nil { - ret "" + ret } match type st { | &Scope: - ret self.scope((&Scope)(st)) + self.scope((&Scope)(st)) | &Var: - ret self.var((&Var)(st)) + self.var((&Var)(st)) | &Data: - ret self.oc.ec.expr((&Data)(st)) + ";" + self.oc.ec.expr((&Data)(st)) | &Conditional: - ret self.conditional((&Conditional)(st)) + self.conditional((&Conditional)(st)) | &InfIter: - ret self.inf_iter((&InfIter)(st)) + self.inf_iter((&InfIter)(st)) | &WhileIter: - ret self.while_iter((&WhileIter)(st)) + self.while_iter((&WhileIter)(st)) | &RangeIter: - ret self.range_iter((&RangeIter)(st)) + self.range_iter((&RangeIter)(st)) | &ContSt: - ret self.cont((&ContSt)(st)) + self.cont((&ContSt)(st)) | &Label: - ret self.label((&Label)(st)) + self.label((&Label)(st)) | &GotoSt: - ret self.goto_st((&GotoSt)(st)) + self.goto_st((&GotoSt)(st)) | &Postfix: - ret self.postfix((&Postfix)(st)) + self.postfix((&Postfix)(st)) | &Assign: - ret self.assign((&Assign)(st)) + self.assign((&Assign)(st)) | &MultiAssign: - ret self.multi_assign((&MultiAssign)(st)) + self.multi_assign((&MultiAssign)(st)) | &Match: - ret self.match_st((&Match)(st)) + self.match_st((&Match)(st)) | &FallSt: - ret self.fall_st((&FallSt)(st)) + self.fall_st((&FallSt)(st)) | &BreakSt: - ret self.break_st((&BreakSt)(st)) + self.break_st((&BreakSt)(st)) | &RetSt: - ret self.ret_st((&RetSt)(st)) + self.ret_st((&RetSt)(st)) | &PushToSliceExprModel: - ret self.oc.ec.push_to_slice((&PushToSliceExprModel)(st)) + self.oc.ec.push_to_slice((&PushToSliceExprModel)(st)) | &MutSlicingExprModel: - ret self.oc.ec.mut_slicing((&MutSlicingExprModel)(st)) + self.oc.ec.mut_slicing((&MutSlicingExprModel)(st)) | &StrInsertBeginExprModel: - ret self.oc.ec.str_insert_begin((&StrInsertBeginExprModel)(st)) + self.oc.ec.str_insert_begin((&StrInsertBeginExprModel)(st)) |: - ret "" + self.oc.write("") } } - fn scope_end(mut self, mut &obj: str, mut &s: &Scope) { + fn scope_stmts(mut &self, mut &s: &Scope) { for (_, mut st) in s.stmts { - obj += self.oc.indent() - obj += self.st(st) - obj += "\n" - } - - self.oc.done_indent() - obj += self.oc.indent() - obj += "}" - - if s.deferred { - obj = "__JULE_DEFER(" + obj + ");" + self.oc.indent() + self.st(st) + self.oc.write(";\n") } } // Generates C++ code of scope. - fn scope(mut self, mut s: &Scope): str { + fn scope(mut &self, mut s: &Scope) { self.oc.add_indent() - let mut obj = "{\n" - self.scope_end(obj, s) - ret obj + if s.deferred { + self.oc.write("__JULE_DEFER(") + } + self.oc.write("{\n") + self.scope_stmts(s) + self.oc.done_indent() + self.oc.indent() + self.oc.write("}") + if s.deferred { + self.oc.write(");") + } } // Generates C++ code of function's scope. - fn func_scope(mut self, mut f: &FnIns): str { + fn func_scope(mut &self, mut f: &FnIns) { if f.scope == nil { - ret "" + ret } - let mut obj = "{\n" + self.oc.write("{\n") self.oc.add_indent() if !f.decl.is_void() { let mut types = f.types() @@ -752,23 +708,25 @@ impl ScopeCoder { lex::is_anon_ident(ident.kind) { continue } - obj += self.oc.indent() - obj += TypeCoder.kind(types[i]) - obj += " " - obj += IdentCoder.to_local(ident.row, ident.column, ident.kind) - obj += " = " - obj += self.oc.ec.init_expr(types[i]) - obj += ";\n" + self.oc.indent() + self.oc.write(TypeCoder.kind(types[i])) + self.oc.write(" ") + self.oc.write(IdentCoder.to_local(ident.row, ident.column, ident.kind)) + self.oc.write(" = ") + self.oc.ec.init_expr(types[i]) + self.oc.write(";\n") } } - self.scope_end(obj, f.scope) + self.scope_stmts(f.scope) if f.decl.exceptional && f.decl.is_void() { // Just for void exceptionals. // Other cases checked by semantic analsis and disallowed // if they are not returns. - obj = obj[:obj.len-2] + " return jule::VoidExceptional(); }" + self.oc.write(" return jule::VoidExceptional();\n") } - ret obj + self.oc.done_indent() + self.oc.indent() + self.oc.write("}") } } @@ -788,4 +746,4 @@ fn is_iter_copy_optimizable(&expr: &Data, &v: &Var): bool { ret true } ret !v.mutable && !expr.mutable -} +} \ No newline at end of file From 19810c72b0e31c5d17151445895e344fdd061b21 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Thu, 4 Apr 2024 03:52:14 +0300 Subject: [PATCH 16/17] compiler: minor improvements for code generation --- src/julec/compile.jule | 10 +++++---- src/julec/obj/cxx/expr.jule | 14 ++++++------- src/julec/obj/cxx/object.jule | 39 ++++++++--------------------------- 3 files changed, 21 insertions(+), 42 deletions(-) diff --git a/src/julec/compile.jule b/src/julec/compile.jule index 41ba9b856..150dd02e6 100644 --- a/src/julec/compile.jule +++ b/src/julec/compile.jule @@ -425,15 +425,17 @@ fn compile_command(mut &args: []str) { let (compiler, compiler_cmd) = gen_compile_cmd(get_compile_path(), ir) - let path = get_compile_path() - let mut file = open_output(path) - - let mut oc = cxx::ObjectCoder.new(ir, file, cxx::SerializationInfo{ + let mut oc = cxx::ObjectCoder.new(ir, cxx::SerializationInfo{ compiler: compiler, compiler_command: compiler_cmd, }) oc.serialize() + let path = get_compile_path() + let mut file = open_output(path) + file.write([]byte(oc.obj)) else { + throw("object code could not write") + } file.close()! if !env::TRANSPILATION { diff --git a/src/julec/obj/cxx/expr.jule b/src/julec/obj/cxx/expr.jule index 4d839b20f..e2845e414 100644 --- a/src/julec/obj/cxx/expr.jule +++ b/src/julec/obj/cxx/expr.jule @@ -909,12 +909,10 @@ impl ExprCoder { } fn push_to_slice(mut &self, mut m: &PushToSliceExprModel) { - self.oc.open_buf_mode() + let n = self.oc.obj.len self.model(m.dest) - let dest = *self.oc.buf - self.oc.close_buf_mode() + let dest = self.oc.obj[n:] - self.oc.write(dest) self.oc.write(" = jule::alloc_for_append(") self.oc.write(dest) self.oc.write(",") @@ -981,13 +979,13 @@ impl ExprCoder { self.oc.write(m.code) ret } - self.oc.open_buf_mode() + let n = self.oc.obj.len for (i, mut expr) in m.exprs { self.expr(expr) - m.exprs[i] = *self.oc.buf - *self.oc.buf = "" + let expr = self.oc.obj[n:] + m.exprs[i] = expr + self.oc.obj = self.oc.obj[:n] } - self.oc.close_buf_mode() self.oc.write(fmt::format(m.code, m.exprs...)) } diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 579828dd7..9cd96f627 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -5,7 +5,6 @@ use env use obj::{IR} use conv for std::conv -use std::fs::{File} use jule for std::jule use build for std::jule::build::{ Directive, @@ -51,59 +50,39 @@ struct TraitHash { } pub struct ObjectCoder { + // Internal buffer which is commonly used. + pub obj: str + ir: &IR info: SerializationInfo - f: &File tmap: []&TraitHash // Current indentation. - indent_buffer: []byte - - // Internal buffer which is preferred to write if not nil. - // It might be useful to get some part of content which will generate. - buf: &str + indent_buffer: str ec: &ExprCoder sc: &ScopeCoder } impl ObjectCoder { - pub static fn new(mut &ir: &IR, mut &f: &File, info: SerializationInfo): &ObjectCoder { + pub static fn new(mut &ir: &IR, info: SerializationInfo): &ObjectCoder { let mut oc = &ObjectCoder{ ir: ir, info: info, - f: f, } oc.ec = ExprCoder.new(oc) oc.sc = ScopeCoder.new(oc) ret oc } - fn open_buf_mode(mut &self) { - static mut buf = "" - if self.buf == nil { - self.buf = unsafe { (&str)(&buf) } - } - } - - fn close_buf_mode(mut &self) { - *self.buf = "" - self.buf = nil - } - fn write(mut &self, s: str) { - if self.buf != nil { - *self.buf += s - ret - } - let bytes = []byte(s) - _ = self.f.write(bytes)! + self.obj += s } // Increase indentation. fn add_indent(mut &self) { - const INDENT_KIND = '\t' - self.indent_buffer = append(self.indent_buffer, INDENT_KIND) + const INDENT_KIND = "\t" + self.indent_buffer += INDENT_KIND } // Decrase indentation. @@ -113,7 +92,7 @@ impl ObjectCoder { // Writes indention string by indent_buffer. fn indent(mut &self) { - _ = self.f.write(self.indent_buffer)! + self.obj += self.indent_buffer } fn find_type_offset(self, t: &Trait, mut k: &TypeKind): int { From 22e77391f5c1ff64ae36fb9e6df79de958c228c3 Mon Sep 17 00:00:00 2001 From: mertcandav Date: Thu, 4 Apr 2024 04:03:41 +0300 Subject: [PATCH 17/17] compiler: add testing code generation --- src/julec/compile.jule | 7 +- src/julec/obj/cxx/object.jule | 6 +- src/julec/obj/cxx/test.jule | 158 ++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 src/julec/obj/cxx/test.jule diff --git a/src/julec/compile.jule b/src/julec/compile.jule index 150dd02e6..3a0fac8bd 100644 --- a/src/julec/compile.jule +++ b/src/julec/compile.jule @@ -429,7 +429,12 @@ fn compile_command(mut &args: []str) { compiler: compiler, compiler_command: compiler_cmd, }) - oc.serialize() + if env::TEST { + let mut tc = cxx::TestCoder.new(oc) + tc.serialize() + } else { + oc.serialize() + } let path = get_compile_path() let mut file = open_output(path) diff --git a/src/julec/obj/cxx/object.jule b/src/julec/obj/cxx/object.jule index 9cd96f627..e9c1319b7 100644 --- a/src/julec/obj/cxx/object.jule +++ b/src/julec/obj/cxx/object.jule @@ -1018,7 +1018,7 @@ impl ObjectCoder { }`) } - pub fn serialize(mut &self) { + fn serialize_head(mut &self) { self.prepare_structures() self.build_trait_map() self.head() @@ -1030,6 +1030,10 @@ impl ObjectCoder { self.funcs() self.init_caller() self.write("\n\n") + } + + pub fn serialize(mut &self) { + self.serialize_head() self.end() } } diff --git a/src/julec/obj/cxx/test.jule b/src/julec/obj/cxx/test.jule new file mode 100644 index 000000000..0c1c93176 --- /dev/null +++ b/src/julec/obj/cxx/test.jule @@ -0,0 +1,158 @@ +// Copyright 2024 The Jule Programming Language. +// Use of this source code is governed by a BSD 3-Clause +// license that can be found in the LICENSE file. + +use env +use obj::{IR} +use std::jule::build::{ + Directive, +} +use std::jule::sema::{ + ImportInfo, + Package, + Fn, + FnIns, + StructIns, +} + +pub struct TestCoder { + t: &StructIns + tm_reset: &Fn + tm_failed: &Fn + tm_skipped: &Fn + + oc: &ObjectCoder +} + +impl TestCoder { + pub static fn new(mut &oc: &ObjectCoder): &TestCoder { + ret &TestCoder{ + oc: oc, + } + } + + fn find_testing_package(mut &self): &ImportInfo { + for (_, mut imp) in self.oc.ir.used { + if imp.link_path == "std::testing" { + ret imp + } + } + ret nil + } + + fn append_test(mut &self, mut f: &FnIns) { + self.oc.indent() + self.call_tm_reset() + self.oc.write(";\n") + self.oc.indent() + self.oc.write("std::cout << \">>> TEST RUNNING: \";\n") + self.oc.indent() + self.oc.write("jule::outln(") + self.oc.write(cstr_lit([]byte(f.decl.ident))) + self.oc.write(");\n") + self.oc.indent() + self.oc.write(IdentCoder.func_ins(f)) + self.oc.write("(_t);\n") + self.oc.indent() + self.oc.write("post_test();\n") + } + + fn append_package_tests(mut &self, mut &p: &Package) { + for (_, mut file) in p.files { + for (_, mut f) in file.funcs { + if has_directive(f.directives, Directive.Test) { + self.append_test(f.instances[0]) + } + } + } + } + + fn ready_testing_package(mut &self): bool { + let mut p = self.find_testing_package() + if p == nil { + // std::testing is not used. + // So, developers cannot write valid test functions. + ret false + } + + self.t = p.find_struct("T", false).instances[0] + + self.tm_reset = self.t.find_method("reset", false) + self.tm_failed = self.t.find_method("failed", false) + self.tm_skipped = self.t.find_method("skipped", false) + ret true + } + + fn call_tm_reset(mut &self) { + self.oc.write(IdentCoder.func(self.tm_reset)) + self.oc.write("(_t)") + } + + fn call_tm_failed(mut &self) { + self.oc.write(IdentCoder.func(self.tm_failed)) + self.oc.write("(_t)") + } + + fn call_tm_skipped(mut &self) { + self.oc.write(IdentCoder.func(self.tm_skipped)) + self.oc.write("(_t)") + } + + // Serialize tests and test point. + // Appends to object code. + pub fn serialize(mut &self) { + self.oc.serialize_head() + defer { + self.oc.end() + } + + self.oc.write("\nvoid test_point(void) {\n") + self.oc.add_indent() + self.oc.indent() + + if !self.ready_testing_package() { + self.oc.write("}") + self.oc.done_indent() + ret + } + + self.oc.write(TypeCoder.as_sptr(TypeCoder.structure_ins(self.t))) + self.oc.write(" _t = jule::new_ptr<") + self.oc.write(TypeCoder.structure_ins(self.t)) + self.oc.write(">(); _t.ref = nullptr;\n") + + self.oc.indent() + self.oc.write("jule::Uint total = 0, failed = 0, skipped = 0;\n") + self.oc.indent() + + self.oc.write("auto post_test = [&](void) {\n") + self.oc.add_indent() + self.oc.indent() + self.oc.write("++total;\n") + self.oc.indent() + self.oc.write("if (") + self.call_tm_failed() + self.oc.write(") { ++failed; std::cout << \" [*] FAILED\" << std::endl; }\n") + self.oc.indent() + self.oc.write("else if (") + self.call_tm_skipped() + self.oc.write(") { ++skipped; std::cout << \" [*] SKIPPED\" << std::endl; }\n") + self.oc.indent() + self.oc.write("else { std::cout << \" [*] PASSED\" << std::endl; }\n") + self.oc.done_indent() + self.oc.indent() + self.oc.write("};\n") + + self.append_package_tests(self.oc.ir.main) + + self.oc.write("\n\n") + self.oc.indent() + self.oc.write("std::cout << std::endl << \"total tests: \" << total << \" skipped: \" << skipped << \" failed: \" << failed << \" pass: \" << total-failed-skipped << std::endl;\n") + self.oc.indent() + self.oc.write("if (failed != 0) std::exit(1);\n") + + self.oc.done_indent() + self.oc.indent() + self.oc.write("}\n") + } +} \ No newline at end of file