using compiler using magic ** ** Dummy class ** class ActorLocal {} class ActorLocalDsl : MagicPlugin { new make(Compiler c) : super(c) {} override Void doMagic(TypeDef t, SlotDef? slot, Loc loc, Str src) { if(slot == null || !(slot is FieldDef)) { throw err("ActorLocal can be applied only to field", loc) } FieldDef field := slot //clear storage flag field.flags = field.flags.and(FConst.Storage.not) getter := field.get //clear synthetic flag getter.flags = getter.flags.and(FConst.Synthetic.not) getter.code.stmts = [createGetter(field, loc)] setter := field.set //clear synthetic flag setter.flags = setter.flags.and(FConst.Synthetic.not) setter.code.stmts = createSetter(field, loc) if(field.init != null) { //need to remove initialization from instance init or static init init := getInit(field) init.code.stmts = init.code.stmts.exclude |st| { isFieldInit(st, field) } } } private Bool isFieldInit(Stmt stmt, FieldDef f) { if(stmt isnot ExprStmt) return false expr := (stmt as ExprStmt).expr if(expr isnot BinaryExpr || expr.id != ExprId.assign) return false lhs := (expr as BinaryExpr).lhs if(lhs isnot FieldExpr) return false field := (lhs as FieldExpr).field return f === field } private MethodDef getInit(FieldDef f) { f.parentDef.method(f.isStatic ? "static\$init" : "instance\$init\$$f.parent.pod.name\$$f.parent.name") } private CType actorType() { ns.resolveType("concurrent::Actor") } private CType localsType() { locals.returnType } private CMethod localsContainsKey() { localsType.method("containsKey") } private CMethod localsGet() { localsType.method("get") } private CMethod localsSet() { localsType.method("set") } private CMethod locals() { actorType.method("locals") } private CField? defValField(CType t) { t.field("defVal") } ** ** CallExpr for Actor.locals ** private Expr localsCall(Loc loc) { CallExpr.makeWithMethod(loc, StaticTargetExpr.make(loc, actorType), locals) } private Expr localsContainsKeyCall(Loc loc, Str key) { CallExpr.makeWithMethod(loc, localsCall(loc), localsContainsKey, [LiteralExpr.makeStr(loc, ns, key)]) } private Expr localsGetCall(Loc loc, Str key) { CallExpr.makeWithMethod(loc, localsCall(loc), localsGet, [LiteralExpr.makeStr(loc, ns, key)]) } private CallExpr localsSetCall(Loc loc, CType t, Str key) { CallExpr.makeWithMethod(loc, localsCall(loc), localsSet, [LiteralExpr.makeStr(loc, ns, key), ItExpr.make(loc, t)]) } private Expr defValCall(Loc loc, CType t) { FieldExpr.make(loc, StaticTargetExpr.make(loc, t), defValField(t), false) } private Stmt createGetter(FieldDef field, Loc loc) { ReturnStmt.make(loc, TernaryExpr.make( localsContainsKeyCall(loc, field.name), localsGetCall(loc, field.name), field.init ?: defValCall(loc, field.fieldType))) } private Stmt[] createSetter(FieldDef field, Loc loc) { [localsSetCall(loc, field.fieldType, field.name).toStmt, ReturnStmt.make(loc)] } }