Skip to content

Commit

Permalink
Allow (rtl) ?? overloading
Browse files Browse the repository at this point in the history
imagine rtl multiplication op with this, i'm not sure...
  • Loading branch information
RblSb committed Dec 16, 2021
1 parent d2b5851 commit 48320b6
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 15 deletions.
3 changes: 3 additions & 0 deletions src/context/typecore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ let unify_min_for_type_source_ref : (typer -> texpr list -> WithType.with_type_s
let analyzer_run_on_expr_ref : (Common.context -> texpr -> texpr) ref = ref (fun _ _ -> die "" __LOC__)
let cast_or_unify_raise_ref : (typer -> ?uctx:unification_context option -> Type.t -> texpr -> pos -> texpr) ref = ref (fun _ ?uctx _ _ _ -> assert false)
let type_generic_function_ref : (typer -> field_access -> (unit -> texpr) field_call_candidate -> WithType.t -> pos -> texpr) ref = ref (fun _ _ _ _ _ -> assert false)
let make_if_then_else_ref : (typer ->
Type.texpr ->
Type.texpr -> Type.texpr -> WithType.t -> Common.pos -> Type.texpr) ref = ref (fun _ _ -> die "" __LOC__)

let pass_name = function
| PBuildModule -> "build-module"
Expand Down
10 changes: 9 additions & 1 deletion src/typing/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,15 @@ let make_binop ctx op e1 e2 is_assign_op with_type p =
typing_error "Unexpected =>" p
| OpIn ->
typing_error "Unexpected in" p
| OpNullCoal
| OpNullCoal ->
let vr = new value_reference ctx in
let e1 = vr#as_var "tmp" {e1 with etype = ctx.t.tnull e1.etype} in
let e_null = Builder.make_null e1.etype e1.epos in
let e_cond = mk (TBinop(OpNotEq,e1,e_null)) ctx.t.tbool e1.epos in
let iftype = WithType.WithType(e2.etype,None) in
let e_if = (!make_if_then_else_ref) ctx e_cond e1 e2 iftype p in
let e = vr#to_texpr e_if in
BinopSpecial (e,false)
| OpAssign
| OpAssignOp _ ->
die "" __LOC__
Expand Down
5 changes: 2 additions & 3 deletions src/typing/typeloadFields.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1091,9 +1091,8 @@ let check_abstract (ctx,cctx,fctx) c cf fd t ret p =
allow_no_expr();
| (Meta.Op,[EBinop(OpAssign,_,_),_],_) :: _ ->
typing_error (cf.cf_name ^ ": Assignment overloading is not supported") p;
| (Meta.Op,[EBinop(OpAssignOp OpNullCoal,_,_),_],_) :: _
| (Meta.Op,[EBinop(OpNullCoal,_,_),_],_) :: _ ->
typing_error (cf.cf_name ^ ": Null coalescing overloading is not supported") p;
| (Meta.Op,[EBinop(OpAssignOp OpNullCoal,_,_),_],_) :: _ ->
typing_error (cf.cf_name ^ ": Null coalescing assignment overloading is not supported") p;
| (Meta.Op,[ETernary(_,_,_),_],_) :: _ ->
typing_error (cf.cf_name ^ ": Ternary overloading is not supported") p;
| (Meta.Op,[EBinop(op,_,_),_],_) :: _ ->
Expand Down
13 changes: 2 additions & 11 deletions src/typing/typer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1678,16 +1678,6 @@ and type_expr ?(mode=MGet) ctx (e,p) (with_type:WithType.t) =
type_expr ctx (format_string ctx s p) with_type
| EConst c ->
Texpr.type_constant ctx.com.basic c p
| EBinop (OpNullCoal,e1,e2) ->
let vr = new value_reference ctx in
let e1 = type_expr ctx (Expr.ensure_block e1) with_type in
let e2 = type_expr ctx (Expr.ensure_block e2) with_type in
let e1 = vr#as_var "tmp" {e1 with etype = ctx.t.tnull e1.etype} in
let e_null = Builder.make_null e1.etype e1.epos in
let e_cond = mk (TBinop(OpNotEq,e1,e_null)) ctx.t.tbool e1.epos in
let iftype = WithType.WithType(e2.etype,None) in
let e_if = make_if_then_else ctx e_cond e1 e2 iftype p in
vr#to_texpr e_if
| EBinop (OpAssignOp OpNullCoal,e1,e2) ->
let e_cond = EBinop(OpNotEq,e1,(EConst(Ident "null"), p)) in
let e_if = EIf ((e_cond, p),e1,Some e2) in
Expand Down Expand Up @@ -2000,4 +1990,5 @@ unify_min_for_type_source_ref := unify_min_for_type_source;
make_call_ref := make_call;
type_call_target_ref := type_call_target;
type_access_ref := type_access;
type_block_ref := type_block
type_block_ref := type_block;
make_if_then_else_ref := make_if_then_else
19 changes: 19 additions & 0 deletions tests/unit/src/unit/TestNullCoalescing.hx
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,24 @@ class TestNullCoalescing extends Test {

eq(1 ?? 2, 1);
eq("1" ?? "2", "1");

var a = new MyAbstract(1);
eq(a ?? 2, 3);
// ?? is right-associative
eq((a ?? 10 * 10) ?? 1 * 10, 111);

final arr = [];
function item(n) {
arr.push(n);
return n;
}
eq(item(1) ?? item(2) ?? item(3), 1);
eq(arr.length, 1);
for (i => v in [1]) eq(arr[i], v);
}
}

abstract MyAbstract(Int) from Int {
public function new(a) this = a;
@:op(a ?? b) function plus(b):MyAbstract return this + b;
}

0 comments on commit 48320b6

Please sign in to comment.