diff --git a/pxtcompiler/emitter/emitter.ts b/pxtcompiler/emitter/emitter.ts index d90a671c02f6..462faf1728f9 100644 --- a/pxtcompiler/emitter/emitter.ts +++ b/pxtcompiler/emitter/emitter.ts @@ -1914,7 +1914,14 @@ ${lbl}: .short 0xffff return emitCallCore(node, node, [], null, decl as any, node.expression) } else { let idx = fieldIndex(node) - return ir.op(EK.FieldAccess, [emitExpr(node.expression)], idx) + const fld = getFieldInfo(idx.classInfo, idx.name) + const attrs = parseComments(fld); + if (attrs.shim) { + // Reading a shimmed property + return emitShim(fld, decl, [node.expression]) + } else { + return ir.op(EK.FieldAccess, [emitExpr(node.expression)], idx) + } } } else if (isClassFunction(decl) || decl.kind == SK.MethodSignature) { // TODO this is now supported in runtime; can be probably relaxed (by using GetAccessor code path above) @@ -2124,10 +2131,10 @@ ${lbl}: .short 0xffff return m } - function emitShim(decl: Declaration, node: Node, args: Expression[]): ir.Expr { + function emitShim(decl: Declaration, node: Node, args: Expression[], shimOverride: string = null): ir.Expr { let attrs = parseComments(decl) let hasRet = !(typeOf(node).flags & TypeFlags.Void) - let nm = attrs.shim + let nm = shimOverride || attrs.shim if (nm.indexOf('(') >= 0) { let parse = /(.*)\((.*)\)$/.exec(nm) @@ -2421,7 +2428,12 @@ ${lbl}: .short 0xffff } if (attrs.shim && !hasShimDummy(decl)) { - return emitShim(decl, node, args); + let shimOverride: string = undefined; + if (node.kind === SK.PropertyAccessExpression && args.length > 1) { + // Assigning a value to a shimmed property, append "_set" to the shim name. + shimOverride = attrs.shim + "_set"; + } + return emitShim(decl, node, args, shimOverride); } else if (attrs.helper) { let syms = checker.getSymbolsInScope(node, SymbolFlags.Module) let helperStmt: Statement @@ -3329,8 +3341,21 @@ ${lbl}: .short 0xffff } else if (decl && (decl.kind == SK.PropertySignature || decl.kind == SK.PropertyAssignment || isSlowField(decl))) { proc.emitExpr(emitCallCore(trg, trg, [src], null, decl as FunctionLikeDeclaration)) } else { - let trg2 = emitExpr(trg) - proc.emitExpr(ir.op(EK.Store, [trg2, emitExpr(src)])) + for (;;) { + if (trg.kind == SK.PropertyAccessExpression) { + const idx = fieldIndex(trg as PropertyAccessExpression) + const fld = getFieldInfo(idx.classInfo, idx.name) + const attrs = parseComments(fld); + if (attrs.shim) { + // Reading a shimmed property + proc.emitExpr(emitCallCore(trg, trg, [src], null, decl as FunctionLikeDeclaration)) + break; + } + } + let trg2 = emitExpr(trg) + proc.emitExpr(ir.op(EK.Store, [trg2, emitExpr(src)])) + break; + } } } else if (trg.kind == SK.ElementAccessExpression) { proc.emitExpr(emitIndexedAccess(trg as ElementAccessExpression, src))