Skip to content

Commit

Permalink
jule: remove operator overloading
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Oct 23, 2024
1 parent 5bbe6f1 commit b154053
Show file tree
Hide file tree
Showing 18 changed files with 57 additions and 755 deletions.
63 changes: 11 additions & 52 deletions src/julec/obj/cxx/expr.jule
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,6 @@ impl exprCoder {
}
}

fn operatorOverloadingUnary(mut &self, mut &s: &sema::StructIns, op: token::Id, mut e: compExpr) {
const Unary = true
mut f := obj::FindOperator(s, op, Unary)
if f == nil {
panic("cxx: unary operator overloading is not exist, this is an implementation mistake")
}
identCoder.funcIns(self.oc.Buf, f)
self.oc.write("(&")
self.possibleRefExpr(e)
self.oc.write(")")
}

fn divByZeroBinary(mut &self, &op: &token::Token, mut &l: &sema::OperandExpr, mut &r: &sema::OperandExpr) {
const xVar = "__jule_x"
const yVar = "__jule_y"
Expand Down Expand Up @@ -208,10 +196,9 @@ impl exprCoder {

fn _unsafeBinary(mut &self, mut &buf: strings::Builder, &l: str, &r: str,
mut &lk: &sema::Type, mut &rk: &sema::Type, op: token::Id, kind: str) {
// Operator overloading.
if lk.Struct() != nil {
mut s := lk.Struct()
operatorOverloadingBinary(buf, s, l, r, op, kind)
structBinary(buf, s, l, r, op, kind)
ret
}

Expand Down Expand Up @@ -347,23 +334,16 @@ impl exprCoder {
fn binary(mut &self, mut m: &sema::BinaryExpr) {
match m.Op.Id {
| token::Id.Solidus | token::Id.Percent:
// Do not check division safety of structures and skip if safety disabled.
if env::Safety && m.Left.Type.Struct() == nil {
if env::Safety {
self.divByZeroBinary(m.Op, m.Left, m.Right)
ret
}
| token::Id.Shl:
// Do not check shifting of structures.
if m.Left.Type.Struct() == nil {
self.shl(m.Left, m.Right)
ret
}
self.shl(m.Left, m.Right)
ret
| token::Id.Shr:
// Do not check shifting of structures.
if m.Left.Type.Struct() == nil {
self.shr(m.Left, m.Right)
ret
}
self.shr(m.Left, m.Right)
ret
}
self.unsafeBinary(m)
}
Expand All @@ -389,13 +369,6 @@ impl exprCoder {
}

fn unary(mut &self, mut m: &sema::UnaryExpr) {
// Operator overloading.
if m.Expr.Type.Struct() != nil {
mut s := m.Expr.Type.Struct()
self.operatorOverloadingUnary(s, m.Op.Id, m.Expr.Model)
ret
}

match m.Op.Id {
| token::Id.Caret:
self.oc.write("(~(")
Expand Down Expand Up @@ -2048,27 +2021,13 @@ fn utoa(mut &s: strings::Builder, x: u64) {
s.WriteStr("LU")!
}

fn operatorOverloadingBinary(mut &buf: strings::Builder, mut &s: &sema::StructIns, &l: str,
fn structBinary(mut &buf: strings::Builder, mut &s: &sema::StructIns, &l: str,
&r: str, op: token::Id, kind: str) {
const Unary = false
mut f := (&sema::FnIns)(nil)
if op == token::Id.NotEq {
f = obj::FindOperator(s, token::Id.Eqs, Unary)
buf.WriteByte('!')!
} else {
f = obj::FindOperator(s, op, Unary)
}
if f == nil {
if op == token::Id.Eqs || op == token::Id.NotEq {
// Equal method not exist. Compiler will create, use default method.
identCoder.structureIns(buf, s)
buf.WriteStr(structDefaultEqMethodSuffix)!
goto common
}
panic("cxx: binary operator overloading is not exist, this is an implementation mistake")
if op != token::Id.Eqs && op != token::Id.NotEq {
panic("cxx: unsupported token occurred for structure binary, this is an implementation mistake")
}
identCoder.funcIns(buf, f)
common:
identCoder.structureIns(buf, s)
buf.WriteStr(structDefaultEqMethodSuffix)!
buf.WriteStr("(&")!
buf.WriteStr(l)!
buf.WriteStr(", ")!
Expand Down
28 changes: 3 additions & 25 deletions src/julec/obj/cxx/object.jule
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ impl ObjectCoder {
}

fn structureOperatorEq(mut &self, ident: str, mut &s: &sema::StructIns, decl: bool) {
if !defaultEq(s) {
if !s.Comparable {
ret
}
self.write("\n")
Expand Down Expand Up @@ -729,12 +729,6 @@ impl ObjectCoder {
}

fn structureInsDecl(mut &self, mut &s: &sema::StructIns) {
for (_, mut m) in s.Methods {
// Operator methods are declared by [structureDecl].
if isHeadDecl(m) {
self.funcDecl(m, false)
}
}
self.write("struct ")
identCoder.structureIns(self.Buf, s)
self.write(" {\n")
Expand Down Expand Up @@ -774,11 +768,8 @@ impl ObjectCoder {
if s.Token != nil {
for (_, mut ins) in s.Instances {
for (_, mut m) in ins.Methods {
// Operator methods are declared by [structureDecl].
if !isHeadDecl(m) {
self.pushResult(m)
self.funcDecl(m, false)
}
self.pushResult(m)
self.funcDecl(m, false)
}
}
}
Expand Down Expand Up @@ -1384,17 +1375,4 @@ fn concatAllParts(parts: ...&token::Token): []byte {
s.WriteStr(p.Kind)!
}
ret unsafe { s.Buf() }
}

// Reports whether the m is a method which is declarated top of the struct.
fn isHeadDecl(mut &m: &sema::Fn): bool {
if len(m.Generics) > 0 || len(m.Instances) == 0 {
ret false
}
ret obj::IsOpMethod(m)
}

// Reports whether structure needs default compare method.
fn defaultEq(&s: &sema::StructIns): bool {
ret s.Comparable && s.Operators.Eq == nil
}
38 changes: 5 additions & 33 deletions src/julec/obj/cxx/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -519,41 +519,19 @@ impl scopeCoder {
self.oc.ec.divByZeroBinary(a.Op, a.Left, a.Right)
}

fn operatorOverloadingAssign(mut &self, mut &s: &sema::StructIns, mut &l: &sema::OperandExpr,
mut &r: &sema::OperandExpr, op: token::Id) {
const Unary = false
mut f := obj::FindOperator(s, op, Unary)
if f == nil {
panic("cxx: binary operator overloading is not exist, this is an implementation mistake")
}
identCoder.funcIns(self.oc.Buf, f)
self.oc.write("(&")
self.assignLeft(l.Model)
self.oc.write(", ")
self.oc.ec.possibleRefExpr(r.Model)
self.oc.write(")")
}

fn assign(mut &self, mut a: &sema::Assign) {
match a.Op.Id {
| token::Id.SolidusEq | token::Id.PercentEq:
// Do not check division safety of structures and skip if safety disabled.
if env::Safety && a.Left.Type.Struct() == nil {
if env::Safety {
self.divByZeroAssign(a)
ret
}
| token::Id.ShlEq:
// Do not check shifting of structures.
if a.Left.Type.Struct() == nil {
self.shl(a)
ret
}
self.shl(a)
ret
| token::Id.ShrEq:
// Do not check shifting of structures.
if a.Left.Type.Struct() == nil {
self.shr(a)
ret
}
self.shr(a)
ret
}

// optimize may optimize multi-assign statements
Expand All @@ -567,12 +545,6 @@ impl scopeCoder {
kind = token::Kind.Eq
}

if op != token::Id.Eq && a.Left.Type.Struct() != nil {
mut s := a.Left.Type.Struct()
self.operatorOverloadingAssign(s, a.Left, a.Right, op)
ret
}

self.assignLeft(a.Left.Model)
self.oc.write(kind)
self.oc.ec.possibleRefExpr(a.Right.Model)
Expand Down
19 changes: 1 addition & 18 deletions src/julec/obj/determine.jule
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD 3-Clause
// license that can be found in the LICENSE file.

use "std/comptime"
use "std/jule/build"
use "std/jule/sema"
use "std/os/filepath"
Expand Down Expand Up @@ -48,22 +47,6 @@ fn IsAny(mut &t: &sema::Type): bool {
// Reports whether anonymous function is closure.
fn IsClosure(&m: &sema::AnonFnExpr): bool { ret len(m.Captured) > 0 }

// Reports whether the m is operator overloading method.
fn IsOpMethod(&m: &sema::Fn): bool {
if len(m.Generics) > 0 || len(m.Instances) == 0 {
ret false
}
mi := m.Instances[0]
const tableT = comptime::TypeOf(mi.Owner.Operators).Decl()
const tableV = comptime::ValueOf(mi.Owner.Operators)
const for _, field in tableT.Fields() {
if mi == tableV.Field(field.Name()).Unwrap() {
ret true
}
}
ret false
}

// Reports the f function of owner is implements a trait's method.
fn IsTraitMethod(mut &owner: &sema::StructIns, &f: &sema::FnIns): bool {
for (_, mut t) in owner.Decl.Implements {
Expand All @@ -86,7 +69,7 @@ fn IsStdPackage(f: str, p: str): bool {
}

// Reports whether imp is implicitly imported.
// See developer reference (9).
// See "std/jule/sema" developer reference (8).
fn IsImplicitImport(imp: &sema::ImportInfo): bool {
ret imp.Decl.Token == nil
}
2 changes: 1 addition & 1 deletion src/julec/obj/ir.jule
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ fn buildCompileInfo(): importer::CompileInfo {
ret info
}

// See "std/jule" developer reference (9).
// See "std/jule" developer reference (8).
fn pushRuntimeToAST(mut &f: &ast::AST) {
mut decl := &ast::UseDecl{
Token: nil, // Nil token is a flag for implicit declaration.
Expand Down
69 changes: 0 additions & 69 deletions src/julec/obj/lookup.jule
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD 3-Clause
// license that can be found in the LICENSE file.

use "std/comptime"
use "std/jule/ast"
use "std/jule/sema"
use "std/jule/token"

// Returns directive if exist.
fn FindDirective(mut &directives: []&ast::Directive, tag: str): &ast::Directive {
Expand Down Expand Up @@ -74,73 +72,6 @@ fn FindTraitTypeOffset(t: &sema::Trait, mut k: &sema::Type): int {
ret FindTraitTypeOffsetS(t, s)
}

// Returns overloaded operator method by operator id.
fn FindOperator(mut &s: &sema::StructIns, op: token::Id, unary: bool): &sema::FnIns {
match op {
| token::Id.Eqs:
ret s.Operators.Eq
| token::Id.Gt:
ret s.Operators.Gt
| token::Id.GtEq:
ret s.Operators.GtEq
| token::Id.Lt:
ret s.Operators.Lt
| token::Id.LtEq:
ret s.Operators.LtEq
| token::Id.Shl:
ret s.Operators.Shl
| token::Id.Shr:
ret s.Operators.Shr
| token::Id.Plus:
if unary {
ret s.Operators.Pos
}
ret s.Operators.Add
| token::Id.Minus:
if unary {
ret s.Operators.Neg
}
ret s.Operators.Sub
| token::Id.Solidus:
ret s.Operators.Div
| token::Id.Star:
ret s.Operators.Mul
| token::Id.Percent:
ret s.Operators.Mod
| token::Id.Amper:
ret s.Operators.BitAnd
| token::Id.Vline:
ret s.Operators.BitOr
| token::Id.Caret:
if unary {
ret s.Operators.BitNot
}
ret s.Operators.BitXor
| token::Id.PlusEq:
ret s.Operators.AddAssign
| token::Id.MinusEq:
ret s.Operators.SubAssign
| token::Id.SolidusEq:
ret s.Operators.DivAssign
| token::Id.StarEq:
ret s.Operators.MulAssign
| token::Id.PercentEq:
ret s.Operators.ModAssign
| token::Id.ShlEq:
ret s.Operators.ShlAssign
| token::Id.ShrEq:
ret s.Operators.ShrAssign
| token::Id.VlineEq:
ret s.Operators.BitOrAssign
| token::Id.AmperEq:
ret s.Operators.BitAndAssign
| token::Id.CaretEq:
ret s.Operators.BitXorAssign
|:
ret nil
}
}

// Returns function instance by generics.
// Assumes generics parameter have enough and same size with generic count of f.
// Panics if not exist any instance.
Expand Down
13 changes: 0 additions & 13 deletions src/julec/opt/deadcode/define.jule
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use "env"
use "obj"
use "std/comptime"
use "std/jule"
use "std/jule/ast"
use "std/jule/build"
Expand Down Expand Up @@ -91,18 +90,6 @@ impl ObjectDeadCode {
self.setReferencesAsLive(ins.Refers)
}

// Set operator overloading methods as alive.
// Just cannot trace whether operator overloading is used yet.
// So, removing these methods may cause compilation problems.
const vs = comptime::ValueOf(*s)
const om = vs.Field("Operators")
const for _, field in om.Type().Decl().Fields() {
if ins == om.Field(field.Name()).Unwrap() {
self.pushLive[&sema::FnIns](ins)
self.setReferencesAsLive(ins.Refers)
}
}

// Set reserved methods as alive.
// So, removing these methods may cause compilation problems,
// or unexpected program bavior.
Expand Down
Loading

0 comments on commit b154053

Please sign in to comment.