Skip to content

Commit

Permalink
jule: update operator overloading rules
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Feb 29, 2024
1 parent 9e077ad commit 82b5c07
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 167 deletions.
86 changes: 47 additions & 39 deletions src/julec/obj/cxx/object.jule
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,7 @@ impl ObjectCoder {
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, "==", "bool")
self.structure_operator(obj, ident, s.operators.eq, "==")
ret
}

Expand Down Expand Up @@ -542,38 +542,47 @@ impl ObjectCoder {
}

// Write operator overloading forwarding for reserved function.
// If the ident parameter is empty, writes operator overloading for unary.
// If the result parameter is empty, writes operator overloading for assignment.
fn structure_operator(mut self, mut &obj: str, &ident: str, mut &f: &FnIns, op: str, result: str) {
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 result == "" {
if assignment {
obj += ident
obj += "&"
} else {
obj += result
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 ident != "" {
obj += ident
if !unary {
let mut p = f.params[1]
obj += TypeCoder.param_ins(p)
obj += " _other"
}
obj += ") { "
if result != "" {
if !assignment {
obj += "return "
}
obj += "this->"
obj += IdentCoder.func_ins(f)
if ident != "" {
if !unary {
obj += "(_other); "
if result == "" {
if assignment {
obj += "return *this; "
}
obj += "}"
Expand All @@ -584,44 +593,43 @@ impl ObjectCoder {
}

fn structure_operators(mut self, mut &s: &StructIns): str {
let unary = "" // To write unary operators.
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, ">", "bool")
self.structure_operator(obj, ident, s.operators.gt_eq, ">=", "bool")
self.structure_operator(obj, ident, s.operators.lt, "<", "bool")
self.structure_operator(obj, ident, s.operators.lt_eq, "<=", "bool")
self.structure_operator(obj, ident, s.operators.shl, "<<", ident)
self.structure_operator(obj, ident, s.operators.shr, ">>", ident)
self.structure_operator(obj, ident, s.operators.add, "+", ident)
self.structure_operator(obj, ident, s.operators.sub, "-", ident)
self.structure_operator(obj, ident, s.operators.div, "/", ident)
self.structure_operator(obj, ident, s.operators.mul, "*", ident)
self.structure_operator(obj, ident, s.operators.mod, "%", ident)
self.structure_operator(obj, ident, s.operators.bit_and, "&", ident)
self.structure_operator(obj, ident, s.operators.bit_or, "|", ident)
self.structure_operator(obj, ident, s.operators.bit_xor, "^", ident)
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, unary, s.operators.neg, "-", ident)
self.structure_operator(obj, unary, s.operators.pos, "+", ident)
self.structure_operator(obj, unary, s.operators.bit_not, "~", ident)
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, "^=", "")
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
}

Expand Down
1 change: 1 addition & 0 deletions src/julec/obj/cxx/type.jule
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ impl TypeCoder {
const Trait = "jule::Trait"
const Array = "jule::Array"
const Fn = "jule::Fn"
const Bool = "jule::Bool"

// Returns given identifier as Jule type identifier.
static fn to_type(mut id: str): str {
Expand Down
2 changes: 1 addition & 1 deletion std/jule/sema/builtin.jule
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ fn builtin_caller_new(mut &e: &Eval, mut &fc: &FnCallExpr, mut &d: &Data): &Data
const REFERENCE = false
e.s.check_validity_for_init_expr(
!e.immutable, REFERENCE, t.kind, init, token)
e.s.check_assign_type(false, t.kind, init, token)
_ = e.s.check_assign_type(false, t.kind, init, token)

d.model = &BuiltinNewCallExprModel{
kind: t.kind,
Expand Down
118 changes: 48 additions & 70 deletions std/jule/sema/eval.jule
Original file line number Diff line number Diff line change
Expand Up @@ -1055,7 +1055,7 @@ impl Eval {
continue
}

self.s.check_assign_type(false, arr.elem, d, s.token)
_ = self.s.check_assign_type(false, arr.elem, d, s.token)
model.elems = append(model.elems, d.model)
}
self.prefix = prefix
Expand Down Expand Up @@ -1092,7 +1092,7 @@ impl Eval {
continue
}

self.s.check_assign_type(false, slc.elem, d, s.token)
_ = self.s.check_assign_type(false, slc.elem, d, s.token)
model.elems = append(model.elems, d.model)
}
self.prefix = prefix
Expand Down Expand Up @@ -3103,8 +3103,8 @@ impl Eval {
ret nil
}

self.s.check_assign_type(false, m.key, key, pair.colon)
self.s.check_assign_type(false, m.val, val, pair.colon)
_ = self.s.check_assign_type(false, m.key, key, pair.colon)
_ = self.s.check_assign_type(false, m.val, val, pair.colon)

model.entries = append(model.entries, &KeyValPairExprModel{
key: key.model,
Expand Down Expand Up @@ -3678,6 +3678,43 @@ impl BinaryEval {
ret self.e.s.check_type_compatibility(self.l.kind, self.r.kind, self.op)
}

fn check_struct_common_operator_compatibility(mut self): bool {
let mut overload: &FnIns = nil
match self.op.kind {
| TokenKind.Lshift:
overload = self.l.kind.strct().operators.shl
| TokenKind.Rshift:
overload = self.l.kind.strct().operators.shr
| TokenKind.Plus:
overload = self.l.kind.strct().operators.add
| TokenKind.Minus:
overload = self.l.kind.strct().operators.sub
| TokenKind.Solidus:
overload = self.l.kind.strct().operators.div
| TokenKind.Star:
overload = self.l.kind.strct().operators.mul
| TokenKind.Percent:
overload = self.l.kind.strct().operators.mod
| TokenKind.Amper:
overload = self.l.kind.strct().operators.bit_and
| TokenKind.Vline:
overload = self.l.kind.strct().operators.bit_or
| TokenKind.Caret:
overload = self.l.kind.strct().operators.bit_xor
|:
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret false
}

if overload == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret false
}

let mut p = overload.params[1]
ret self.e.s.check_assign_type(p.decl.reference, p.kind, self.r, self.op)
}

fn eval_nil(mut self): &Data {
if !self.r.kind.nil_compatible() {
self.e.push_err(self.op, LogMsg.IncompatibleTypes, TokenKind.Nil, self.r.kind.to_str())
Expand Down Expand Up @@ -3861,10 +3898,6 @@ impl BinaryEval {
}

fn eval_struct(mut self): &Data {
if !self.check_type_compatibility() {
ret nil
}

match self.op.kind {
| TokenKind.Gt:
if self.l.kind.strct().operators.gt == nil {
Expand Down Expand Up @@ -3906,77 +3939,22 @@ impl BinaryEval {
kind: build_prim_type(PrimKind.Bool),
},
}
| TokenKind.Lshift:
if self.l.kind.strct().operators.shl == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Rshift:
if self.l.kind.strct().operators.shr == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Plus:
if self.l.kind.strct().operators.add == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Minus:
if self.l.kind.strct().operators.sub == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Solidus:
if self.l.kind.strct().operators.div == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Star:
if self.l.kind.strct().operators.mul == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Percent:
if self.l.kind.strct().operators.mod == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Amper:
if self.l.kind.strct().operators.bit_and == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Vline:
if self.l.kind.strct().operators.bit_or == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Caret:
if self.l.kind.strct().operators.bit_xor == nil {
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
ret nil
}
ret self.l
| TokenKind.Eqs
| TokenKind.NotEq:
if !self.check_type_compatibility() {
ret nil
}
ret &Data{
kind: &TypeKind{
kind: build_prim_type(PrimKind.Bool),
},
}
|:
self.e.push_err(self.op, LogMsg.OperatorNotForJuleType, self.op.kind, self.l.kind.to_str())
}

if !self.check_struct_common_operator_compatibility() {
ret nil
}
ret self.l
}

fn eval_trait(mut self): &Data {
Expand Down
9 changes: 2 additions & 7 deletions std/jule/sema/pattern.jule
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,7 @@ impl FuncPattern {
}

let mut ins = unsafe { *(&f.instances[0]) }
if ins.result.strct() != ins.owner {
ret false
}
ret ins.owner == ins.params[1].kind.strct()
ret ins.result.strct() == ins.owner
}

// Reports whether function is the reserved shl function.
Expand Down Expand Up @@ -223,9 +220,7 @@ impl FuncPattern {
f.params[1].reference {
ret false
}

let mut ins = unsafe { *(&f.instances[0]) }
ret ins.owner == ins.params[1].kind.strct()
ret true
}

// Reports whether function is the reserved add_assign function.
Expand Down
Loading

0 comments on commit 82b5c07

Please sign in to comment.