Skip to content

Commit

Permalink
[hl] Support taking reference to fields of Dynamic.
Browse files Browse the repository at this point in the history
  • Loading branch information
Apprentice-Alchemist committed Jun 8, 2024
1 parent 849cf61 commit 572e45b
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/generators/genhl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2076,12 +2076,13 @@ and eval_expr ctx e =
op ctx (ORef (r,rv));
r
| TField (obj, access) ->
let r = alloc_tmp ctx (HRef (to_type ctx (field_type ctx access e.epos))) in
let r = alloc_tmp ctx (to_type ctx e.etype) in
(match get_access ctx v with
| AStaticVar (g,t,fid) ->
let o = alloc_tmp ctx t in
op ctx (OGetGlobal (o,g));
op ctx (OFieldRef (r,o,fid));
| ADynamic (ethis, fid)
| AInstanceField (ethis,fid) ->
let robj = eval_null_check ctx ethis in
op ctx (OFieldRef (r,robj,fid));
Expand Down
5 changes: 3 additions & 2 deletions src/generators/hl2c.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1115,17 +1115,18 @@ let generate_function ctx f =
| OAsm _ ->
sexpr "UNSUPPORTED ASM OPCODE";
| OFieldRef (r, obj, fid) ->
let val_type = (match (rtype r) with HRef t -> t | _ -> Globals.die "" __LOC__) in
match rtype obj with
| HObj o | HStruct o ->
let name, t = resolve_field o fid in
sexpr "%s &%s->%s" (rassign r (HRef t)) (reg obj) (obj_field fid name)
| HVirtual v ->
let name, nid, t = v.vfields.(fid) in
let dget = sprintf "hl_dyn_get_ref(%s->value,%ld/*%s*/)" (reg obj) (hash ctx nid) name in
let dget = sprintf "hl_dyn_get_ref(%s->value,%ld/*%s*/,%s)" (reg obj) (hash ctx nid) name (type_value val_type) in
sexpr "%shl_vfields(%s)[%d] ? ((%s*)(hl_vfields(%s)[%d])) : %s" (rassign r (HRef t)) (reg obj) fid (ctype t) (reg obj) fid dget
| HDyn ->
let h = hash ctx fid in
sexpr "%s = hl_dyn_get_ref((vdynamic*)%s,%ld/*%s*/)" (reg r) (reg obj) h code.strings.(fid)
sexpr "%s = hl_dyn_get_ref((vdynamic*)%s,%ld/*%s*/,%s)" (reg r) (reg obj) h code.strings.(fid) (type_value val_type)
| _ ->
Globals.die "" __LOC__
) f.code;
Expand Down
20 changes: 18 additions & 2 deletions std/hl/Ref.macro.hx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,26 @@ import haxe.macro.Expr;

final pos:Position = Context.currentPos();
final typedFieldExpr:TypedExpr = Context.typeExpr(expr);
final valType:Type = typedFieldExpr.t;
final refType:Type = switch Context.getType("hl.Ref") {

var valType:Type = typedFieldExpr.t;
var refType:Type = switch Context.getType("hl.Ref") {
case TAbstract(t, _): TAbstract(t, [valType]);
case _: Context.error("hl.Ref is not an abstract", pos);
};

switch typedFieldExpr.expr {
case TField(e, FDynamic(s)):
final expectedType = Context.getExpectedType();
switch expectedType {
case TAbstract(_.get() => {pack: ["hl"], name: "Ref"}, [param]):
refType = expectedType;
valType = param;
case null, TMono(_):
Context.error("Taking reference to a field of a dynamic requires an explicit type hint", pos);
case _:
// this case will fail later
}
case _:
}

final typedExpr:TypedExpr = {
Expand Down

0 comments on commit 572e45b

Please sign in to comment.