// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:dart2wasm/class_info.dart';
import 'package:dart2wasm/closures.dart';
import 'package:dart2wasm/dispatch_table.dart';
import 'package:dart2wasm/intrinsics.dart';
import 'package:dart2wasm/param_info.dart';
import 'package:dart2wasm/reference_extensions.dart';
import 'package:dart2wasm/translator.dart';

import 'package:kernel/ast.dart';
import 'package:kernel/type_environment.dart';

import 'package:wasm_builder/wasm_builder.dart' as w;

/// Main code generator for member bodies.
///
/// The [generate] method first collects all local functions and function
/// expressions in the body and then generates code for the body. Code for the
/// local functions and function expressions must be generated separately by
/// calling the [generateLambda] method on all lambdas in [closures].
///
/// A new [CodeGenerator] object must be created for each new member or lambda.
///
/// Every visitor method for an expression takes in the Wasm type that it is
/// expected to leave on the stack (or the special [voidMarker] to indicate that
/// it should leave nothing). It returns what it actually left on the stack. The
/// code generation for every expression or subexpression is done via the [wrap]
/// method, which emits appropriate conversion code if the produced type is not
/// a subtype of the expected type.
class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
    implements InitializerVisitor<void>, StatementVisitor<void> {
  final Translator translator;
  final w.DefinedFunction function;
  final Reference reference;
  late final List<w.Local> paramLocals;
  final w.Label? returnLabel;

  late final Intrinsifier intrinsifier;
  late final StaticTypeContext typeContext;
  late final w.Instructions b;

  late final Closures closures;

  final Map<VariableDeclaration, w.Local> locals = {};
  w.Local? thisLocal;
  w.Local? preciseThisLocal;
  w.Local? returnValueLocal;
  final Map<TypeParameter, w.Local> typeLocals = {};
  final List<TryBlockFinalizer> finalizers = [];
  final List<w.Label> tryLabels = [];
  final Map<LabeledStatement, w.Label> labels = {};
  final Map<SwitchCase, w.Label> switchLabels = {};

  /// Create a code generator for a member or one of its lambdas.
  ///
  /// The [paramLocals] and [returnLabel] parameters can be used to generate
  /// code for an inlined function by specifying the locals containing the
  /// parameters (instead of the function inputs) and the label to jump to on
  /// return (instead of emitting a `return` instruction).
  CodeGenerator(this.translator, this.function, this.reference,
      {List<w.Local>? paramLocals, this.returnLabel}) {
    this.paramLocals = paramLocals ?? function.locals;
    intrinsifier = Intrinsifier(this);
    typeContext = StaticTypeContext(member, translator.typeEnvironment);
    b = function.body;
  }

  Member get member => reference.asMember;

  w.ValueType get returnType => translator
      .outputOrVoid(returnLabel?.targetTypes ?? function.type.outputs);

  TranslatorOptions get options => translator.options;

  w.ValueType get voidMarker => translator.voidMarker;

  w.ValueType translateType(DartType type) => translator.translateType(type);

  w.Local addLocal(w.ValueType type) {
    return function.addLocal(translator.typeForLocal(type));
  }

  DartType dartTypeOf(Expression exp) {
    return exp.getStaticType(typeContext);
  }

  void _unimplemented(
      TreeNode node, Object message, List<w.ValueType> expectedTypes) {
    final text = "Not implemented: $message at ${node.location}";
    print(text);
    b.comment(text);
    b.block(const [], expectedTypes);
    b.unreachable();
    b.end();
  }

  @override
  void defaultInitializer(Initializer node) {
    _unimplemented(node, node.runtimeType, const []);
  }

  @override
  w.ValueType defaultExpression(Expression node, w.ValueType expectedType) {
    _unimplemented(node, node.runtimeType, [expectedType]);
    return expectedType;
  }

  @override
  void defaultStatement(Statement node) {
    _unimplemented(node, node.runtimeType, const []);
  }

  /// Generate code for the body of the member.
  void generate() {
    closures = Closures(this);

    Member member = this.member;

    if (reference.isTearOffReference) {
      // Tear-off getter
      w.DefinedFunction closureFunction =
          translator.getTearOffFunction(member as Procedure);

      int parameterCount = member.function.requiredParameterCount;
      w.DefinedGlobal global = translator.makeFunctionRef(closureFunction);

      ClassInfo info = translator.classInfo[translator.functionClass]!;
      translator.functions.allocateClass(info.classId);

      b.i32_const(info.classId);
      b.i32_const(initialIdentityHash);
      b.local_get(paramLocals[0]);
      b.global_get(global);
      translator.struct_new(b, parameterCount);
      b.end();
      return;
    }

    if (intrinsifier.generateMemberIntrinsic(
        reference, function, paramLocals, returnLabel)) {
      b.end();
      return;
    }

    if (member.isExternal) {
      final text =
          "Unimplemented external member $member at ${member.location}";
      print(text);
      b.comment(text);
      b.unreachable();
      b.end();
      return;
    }

    if (member is Field) {
      if (member.isStatic) {
        // Static field initializer function
        assert(reference == member.fieldReference);
        closures.findCaptures(member);
        closures.collectContexts(member);
        closures.buildContexts();

        w.Global global = translator.globals.getGlobal(member);
        w.Global? flag = translator.globals.getGlobalInitializedFlag(member);
        wrap(member.initializer!, global.type.type);
        b.global_set(global);
        if (flag != null) {
          b.i32_const(1);
          b.global_set(flag);
        }
        b.global_get(global);
        translator.convertType(
            function, global.type.type, function.type.outputs.single);
        b.end();
        return;
      }

      // Implicit getter or setter
      w.StructType struct =
          translator.classInfo[member.enclosingClass!]!.struct;
      int fieldIndex = translator.fieldIndex[member]!;
      w.ValueType fieldType = struct.fields[fieldIndex].type.unpacked;

      void getThis() {
        w.Local thisLocal = paramLocals[0];
        w.RefType structType = w.RefType.def(struct, nullable: true);
        b.local_get(thisLocal);
        translator.convertType(function, thisLocal.type, structType);
      }

      if (reference.isImplicitGetter) {
        // Implicit getter
        getThis();
        b.struct_get(struct, fieldIndex);
        translator.convertType(function, fieldType, returnType);
      } else {
        // Implicit setter
        w.Local valueLocal = paramLocals[1];
        getThis();
        b.local_get(valueLocal);
        translator.convertType(function, valueLocal.type, fieldType);
        b.struct_set(struct, fieldIndex);
      }
      b.end();
      return;
    }

    ParameterInfo paramInfo = translator.paramInfoFor(reference);
    bool hasThis = member.isInstanceMember || member is Constructor;
    int typeParameterOffset = hasThis ? 1 : 0;
    int implicitParams = typeParameterOffset + paramInfo.typeParamCount;
    List<VariableDeclaration> positional =
        member.function!.positionalParameters;
    for (int i = 0; i < positional.length; i++) {
      locals[positional[i]] = paramLocals[implicitParams + i];
    }
    List<VariableDeclaration> named = member.function!.namedParameters;
    for (var param in named) {
      locals[param] =
          paramLocals[implicitParams + paramInfo.nameIndex[param.name]!];
    }
    List<TypeParameter> typeParameters = member is Constructor
        ? member.enclosingClass.typeParameters
        : member.function!.typeParameters;
    for (int i = 0; i < typeParameters.length; i++) {
      typeLocals[typeParameters[i]] = paramLocals[typeParameterOffset + i];
    }

    closures.findCaptures(member);

    if (hasThis) {
      Class cls = member.enclosingClass!;
      ClassInfo info = translator.classInfo[cls]!;
      thisLocal = paramLocals[0];
      w.RefType thisType = info.nonNullableType;
      if (translator.needsConversion(paramLocals[0].type, thisType) &&
          !(cls == translator.ffiPointerClass ||
              translator.isFfiCompound(cls))) {
        preciseThisLocal = addLocal(thisType);
        b.local_get(paramLocals[0]);
        translator.ref_cast(b, info);
        b.local_set(preciseThisLocal!);
      } else {
        preciseThisLocal = paramLocals[0];
      }
    }

    closures.collectContexts(member);
    if (member is Constructor) {
      for (Field field in member.enclosingClass.fields) {
        if (field.isInstanceMember && field.initializer != null) {
          closures.collectContexts(field.initializer!,
              container: member.function);
        }
      }
    }
    closures.buildContexts();

    allocateContext(member.function!);
    captureParameters();

    if (member is Constructor) {
      Class cls = member.enclosingClass;
      ClassInfo info = translator.classInfo[cls]!;
      for (TypeParameter typeParam in cls.typeParameters) {
        b.local_get(thisLocal!);
        b.local_get(typeLocals[typeParam]!);
        b.struct_set(info.struct, translator.typeParameterIndex[typeParam]!);
      }
      for (Field field in cls.fields) {
        if (field.isInstanceMember && field.initializer != null) {
          int fieldIndex = translator.fieldIndex[field]!;
          b.local_get(thisLocal!);
          wrap(
              field.initializer!, info.struct.fields[fieldIndex].type.unpacked);
          b.struct_set(info.struct, fieldIndex);
        }
      }
      for (Initializer initializer in member.initializers) {
        initializer.accept(this);
      }
    }

    member.function!.body?.accept(this);
    _implicitReturn();
    b.end();
  }

  /// Generate code for the body of a lambda.
  void generateLambda(Lambda lambda, Closures closures) {
    this.closures = closures;

    final int implicitParams = 1;
    List<VariableDeclaration> positional =
        lambda.functionNode.positionalParameters;
    for (int i = 0; i < positional.length; i++) {
      locals[positional[i]] = paramLocals[implicitParams + i];
    }

    Context? context = closures.contexts[lambda.functionNode]?.parent;
    if (context != null) {
      b.local_get(paramLocals[0]);
      translator.ref_cast(b, context.struct);
      while (true) {
        w.Local contextLocal =
            addLocal(w.RefType.def(context!.struct, nullable: false));
        context.currentLocal = contextLocal;
        if (context.parent != null || context.containsThis) {
          b.local_tee(contextLocal);
        } else {
          b.local_set(contextLocal);
        }
        if (context.parent == null) break;

        b.struct_get(context.struct, context.parentFieldIndex);
        if (options.localNullability) {
          b.ref_as_non_null();
        }
        context = context.parent!;
      }
      if (context.containsThis) {
        thisLocal = addLocal(
            context.struct.fields[context.thisFieldIndex].type.unpacked);
        preciseThisLocal = thisLocal;
        b.struct_get(context.struct, context.thisFieldIndex);
        b.local_set(thisLocal!);
      }
    }
    allocateContext(lambda.functionNode);
    captureParameters();

    lambda.functionNode.body!.accept(this);
    _implicitReturn();
    b.end();
  }

  void _implicitReturn() {
    if (function.type.outputs.length > 0) {
      w.ValueType returnType = function.type.outputs[0];
      if (returnType is w.RefType && returnType.nullable) {
        // Dart body may have an implicit return null.
        b.ref_null(returnType.heapType);
      } else {
        // This point is unreachable, but the Wasm validator still expects the
        // stack to contain a value matching the Wasm function return type.
        b.block(const [], function.type.outputs);
        b.comment("Unreachable implicit return");
        b.unreachable();
        b.end();
      }
    }
  }

  void allocateContext(TreeNode node) {
    Context? context = closures.contexts[node];
    if (context != null && !context.isEmpty) {
      w.Local contextLocal =
          addLocal(w.RefType.def(context.struct, nullable: false));
      context.currentLocal = contextLocal;
      translator.struct_new_default(b, context.struct);
      b.local_set(contextLocal);
      if (context.containsThis) {
        b.local_get(contextLocal);
        b.local_get(preciseThisLocal!);
        b.struct_set(context.struct, context.thisFieldIndex);
      }
      if (context.parent != null) {
        w.Local parentLocal = context.parent!.currentLocal;
        b.local_get(contextLocal);
        b.local_get(parentLocal);
        b.struct_set(context.struct, context.parentFieldIndex);
      }
    }
  }

  void captureParameters() {
    locals.forEach((variable, local) {
      Capture? capture = closures.captures[variable];
      if (capture != null) {
        b.local_get(capture.context.currentLocal);
        b.local_get(local);
        translator.convertType(function, local.type, capture.type);
        b.struct_set(capture.context.struct, capture.fieldIndex);
      }
    });
  }

  /// Helper function to throw a Wasm ref downcast error.
  void throwWasmRefError(String expected) {
    wrap(
        StringLiteral(expected),
        translator
            .translateType(translator.coreTypes.stringNonNullableRawType));
    _call(translator.stackTraceCurrent.reference);
    _call(translator.throwWasmRefError.reference);
    b.unreachable();
  }

  /// Generates code for an expression plus conversion code to convert the
  /// result to the expected type if needed. All expression code generation goes
  /// through this method.
  w.ValueType wrap(Expression node, w.ValueType expectedType) {
    w.ValueType resultType = node.accept1(this, expectedType);
    translator.convertType(function, resultType, expectedType);
    return expectedType;
  }

  w.ValueType _call(Reference target) {
    w.BaseFunction targetFunction = translator.functions.getFunction(target);
    if (translator.shouldInline(target)) {
      List<w.Local> inlinedLocals =
          targetFunction.type.inputs.map((t) => addLocal(t)).toList();
      for (w.Local local in inlinedLocals.reversed) {
        b.local_set(local);
      }
      w.Label block = b.block(const [], targetFunction.type.outputs);
      b.comment("Inlined ${target.asMember}");
      CodeGenerator(translator, function, target,
              paramLocals: inlinedLocals, returnLabel: block)
          .generate();
    } else {
      String access =
          target.isGetter ? "get" : (target.isSetter ? "set" : "call");
      b.comment("Direct $access of '${target.asMember}'");
      b.call(targetFunction);
    }
    return translator.outputOrVoid(targetFunction.type.outputs);
  }

  @override
  void visitInvalidInitializer(InvalidInitializer node) {}

  @override
  void visitAssertInitializer(AssertInitializer node) {}

  @override
  void visitLocalInitializer(LocalInitializer node) {
    node.variable.accept(this);
  }

  @override
  void visitFieldInitializer(FieldInitializer node) {
    Class cls = (node.parent as Constructor).enclosingClass;
    w.StructType struct = translator.classInfo[cls]!.struct;
    int fieldIndex = translator.fieldIndex[node.field]!;

    b.local_get(thisLocal!);
    wrap(node.value, struct.fields[fieldIndex].type.unpacked);
    b.struct_set(struct, fieldIndex);
  }

  @override
  void visitRedirectingInitializer(RedirectingInitializer node) {
    Class cls = (node.parent as Constructor).enclosingClass;
    b.local_get(thisLocal!);
    if (options.parameterNullability && thisLocal!.type.nullable) {
      b.ref_as_non_null();
    }
    for (TypeParameter typeParam in cls.typeParameters) {
      _makeType(TypeParameterType(typeParam, Nullability.nonNullable), node);
    }
    _visitArguments(node.arguments, node.targetReference, 1);
    _call(node.targetReference);
  }

  @override
  void visitSuperInitializer(SuperInitializer node) {
    Supertype? supertype =
        (node.parent as Constructor).enclosingClass.supertype;
    if (supertype?.classNode.superclass == null) {
      return;
    }
    b.local_get(thisLocal!);
    if (options.parameterNullability && thisLocal!.type.nullable) {
      b.ref_as_non_null();
    }
    for (DartType typeArg in supertype!.typeArguments) {
      _makeType(typeArg, node);
    }
    _visitArguments(node.arguments, node.targetReference,
        1 + supertype.typeArguments.length);
    _call(node.targetReference);
  }

  @override
  void visitBlock(Block node) {
    for (Statement statement in node.statements) {
      statement.accept(this);
    }
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    w.Label label = b.block();
    labels[node] = label;
    node.body.accept(this);
    labels.remove(node);
    b.end();
  }

  @override
  void visitBreakStatement(BreakStatement node) {
    b.br(labels[node.target]!);
  }

  @override
  void visitVariableDeclaration(VariableDeclaration node) {
    if (node.type is VoidType) {
      if (node.initializer != null) {
        wrap(node.initializer!, voidMarker);
      }
      return;
    }
    w.ValueType type = translateType(node.type);
    w.Local? local;
    Capture? capture = closures.captures[node];
    if (capture == null || !capture.written) {
      local = addLocal(type);
      locals[node] = local;
    }
    if (node.initializer != null) {
      if (capture != null) {
        w.ValueType expectedType = capture.written ? capture.type : local!.type;
        b.local_get(capture.context.currentLocal);
        wrap(node.initializer!, expectedType);
        if (!capture.written) {
          b.local_tee(local!);
        }
        b.struct_set(capture.context.struct, capture.fieldIndex);
      } else {
        wrap(node.initializer!, local!.type);
        b.local_set(local);
      }
    } else if (local != null && !local.type.defaultable) {
      // Uninitialized variable
      translator.globals.instantiateDummyValue(b, local.type);
      b.local_set(local);
    }
  }

  @override
  void visitEmptyStatement(EmptyStatement node) {}

  @override
  void visitAssertStatement(AssertStatement node) {}

  @override
  void visitAssertBlock(AssertBlock node) {}

  @override
  void visitTryCatch(TryCatch node) {
    // It is not valid dart to have a try without a catch.
    assert(node.catches.isNotEmpty);

    // We lower a [TryCatch] to a wasm try block. If there are any [Catch]
    // nodes, we generate a single wasm catch instruction, and dispatch at
    // runtime based on the type of the caught exception.
    w.Label try_ = b.try_();
    node.body.accept(this);
    b.br(try_);

    // Insert a catch instruction which will catch any thrown Dart
    // exceptions.
    // Note: We must wait to add the try block to the [tryLabels] stack until
    // after we have visited the body of the try. This is to handle the case of
    // a rethrow nested within a try nested within a catch, that is we need the
    // rethrow to target the last try block with a catch.
    tryLabels.add(try_);
    b.catch_(translator.exceptionTag);

    // Stash the original exception in a local so we can push it back onto the
    // stack after each type test. Also, store the stack trace in a local.
    w.RefType stackTrace = translator.stackTraceInfo.nonNullableType;
    w.Local thrownStackTrace = addLocal(stackTrace);
    b.local_set(thrownStackTrace);

    w.RefType exception = translator.topInfo.nonNullableType;
    w.Local thrownException = addLocal(exception);
    b.local_set(thrownException);

    // For each catch node:
    //   1) Create a block for the catch.
    //   2) Push the caught exception onto the stack.
    //   3) Add a type test based on the guard of the catch.
    //   4) If the test fails, we jump to the next catch. Otherwise, we
    //      execute the body of the catch.
    for (Catch catch_ in node.catches) {
      w.Label catchBlock = b.block();
      DartType guard = catch_.guard;

      // Only emit the type test if the guard is not [Object].
      if (guard != translator.coreTypes.objectNonNullableRawType) {
        b.local_get(thrownException);
        emitTypeTest(
            guard, translator.coreTypes.objectNonNullableRawType, node);
        b.i32_eqz();
        b.br_if(catchBlock);
      }

      // If there is an exception declaration, create a local corresponding to
      // the catch's exception [VariableDeclaration] node.
      VariableDeclaration? exceptionDeclaration = catch_.exception;
      if (exceptionDeclaration != null) {
        w.Local guardedException = addLocal(exception);
        locals[exceptionDeclaration] = guardedException;
        b.local_get(thrownException);
        b.local_set(guardedException);
      }

      // If there is a stack trace declaration, then create a local
      // corresponding to the catch's stack trace [VariableDeclaration] node.
      VariableDeclaration? stackTraceDeclaration = catch_.stackTrace;
      if (stackTraceDeclaration != null) {
        w.Local guardedStackTrace = addLocal(stackTrace);
        locals[stackTraceDeclaration] = guardedStackTrace;
        b.local_get(thrownStackTrace);
        b.local_set(guardedStackTrace);
      }
      catch_.body.accept(this);

      // Jump out of the try entirely if we enter any catch block.
      b.br(try_);
      b.end(); // end catchBlock.
    }

    // We insert a rethrow just before the end of the try block to handle the
    // case where none of the catch blocks catch the type of the thrown
    // exception.
    b.rethrow_(try_);
    tryLabels.removeLast();
    b.end(); // end try_.
  }

  @override
  void visitTryFinally(TryFinally node) {
    // We lower a [TryFinally] to three nested blocks, and we emit the finalizer
    // up to three times. Once in a catch, to handle the case where the try
    // throws. Once outside of the catch, to handle the case where the try does
    // not throw. Finally, if there is a return within the try block, then we
    // emit the finalizer one more time along with logic to continue walking up
    // the stack.
    w.Label tryFinallyBlock = b.block();
    w.Label finalizerBlock = b.block();
    finalizers.add(TryBlockFinalizer(finalizerBlock));
    w.Label tryBlock = b.try_();
    node.body.accept(this);
    bool mustHandleReturn = finalizers.removeLast().mustHandleReturn;
    b.br(tryBlock);
    b.catch_(translator.exceptionTag);
    node.finalizer.accept(this);
    b.rethrow_(tryBlock);
    b.end(); // end tryBlock.
    node.finalizer.accept(this);
    b.br(tryFinallyBlock);
    b.end(); // end finalizerBlock.
    if (mustHandleReturn) {
      node.finalizer.accept(this);
      if (finalizers.isNotEmpty) {
        b.br(finalizers.last.label);
      } else {
        if (returnValueLocal != null) {
          b.local_get(returnValueLocal!);
          translator.convertType(function, returnValueLocal!.type, returnType);
        }
        _returnFromFunction();
      }
    }
    b.end(); // end tryFinallyBlock.
  }

  @override
  void visitExpressionStatement(ExpressionStatement node) {
    wrap(node.expression, voidMarker);
  }

  bool _hasLogicalOperator(Expression condition) {
    while (condition is Not) condition = condition.operand;
    return condition is LogicalExpression;
  }

  void _branchIf(Expression? condition, w.Label target,
      {required bool negated}) {
    if (condition == null) {
      if (!negated) b.br(target);
      return;
    }
    while (condition is Not) {
      negated = !negated;
      condition = condition.operand;
    }
    if (condition is LogicalExpression) {
      bool isConjunctive =
          (condition.operatorEnum == LogicalExpressionOperator.AND) ^ negated;
      if (isConjunctive) {
        w.Label conditionBlock = b.block();
        _branchIf(condition.left, conditionBlock, negated: !negated);
        _branchIf(condition.right, target, negated: negated);
        b.end();
      } else {
        _branchIf(condition.left, target, negated: negated);
        _branchIf(condition.right, target, negated: negated);
      }
    } else {
      wrap(condition!, w.NumType.i32);
      if (negated) {
        b.i32_eqz();
      }
      b.br_if(target);
    }
  }

  void _conditional(Expression condition, void then(), void otherwise()?,
      List<w.ValueType> result) {
    if (!_hasLogicalOperator(condition)) {
      // Simple condition
      wrap(condition, w.NumType.i32);
      b.if_(const [], result);
      then();
      if (otherwise != null) {
        b.else_();
        otherwise();
      }
      b.end();
    } else {
      // Complex condition
      w.Label ifBlock = b.block(const [], result);
      if (otherwise != null) {
        w.Label elseBlock = b.block();
        _branchIf(condition, elseBlock, negated: true);
        then();
        b.br(ifBlock);
        b.end();
        otherwise();
      } else {
        _branchIf(condition, ifBlock, negated: true);
        then();
      }
      b.end();
    }
  }

  @override
  void visitIfStatement(IfStatement node) {
    _conditional(
        node.condition,
        () => node.then.accept(this),
        node.otherwise != null ? () => node.otherwise!.accept(this) : null,
        const []);
  }

  @override
  void visitDoStatement(DoStatement node) {
    w.Label loop = b.loop();
    allocateContext(node);
    node.body.accept(this);
    _branchIf(node.condition, loop, negated: false);
    b.end();
  }

  @override
  void visitWhileStatement(WhileStatement node) {
    w.Label block = b.block();
    w.Label loop = b.loop();
    _branchIf(node.condition, block, negated: true);
    allocateContext(node);
    node.body.accept(this);
    b.br(loop);
    b.end();
    b.end();
  }

  @override
  void visitForStatement(ForStatement node) {
    Context? context = closures.contexts[node];
    allocateContext(node);
    for (VariableDeclaration variable in node.variables) {
      variable.accept(this);
    }
    w.Label block = b.block();
    w.Label loop = b.loop();
    _branchIf(node.condition, block, negated: true);
    node.body.accept(this);
    if (node.variables.any((v) => closures.captures.containsKey(v))) {
      w.Local oldContext = context!.currentLocal;
      allocateContext(node);
      w.Local newContext = context.currentLocal;
      for (VariableDeclaration variable in node.variables) {
        Capture? capture = closures.captures[variable];
        if (capture != null) {
          b.local_get(oldContext);
          b.struct_get(context.struct, capture.fieldIndex);
          b.local_get(newContext);
          b.struct_set(context.struct, capture.fieldIndex);
        }
      }
    } else {
      allocateContext(node);
    }
    for (Expression update in node.updates) {
      wrap(update, voidMarker);
    }
    b.br(loop);
    b.end();
    b.end();
  }

  @override
  void visitForInStatement(ForInStatement node) {
    throw "ForInStatement should have been desugared: $node";
  }

  /// Handle the return from this function, either by jumping to [returnLabel]
  /// in the case this function was inlined or just inserting a return
  /// instruction.
  void _returnFromFunction() {
    if (returnLabel != null) {
      b.br(returnLabel!);
    } else {
      b.return_();
    }
  }

  @override
  void visitReturnStatement(ReturnStatement node) {
    Expression? expression = node.expression;
    if (expression != null) {
      wrap(expression, returnType);
    } else {
      translator.convertType(function, voidMarker, returnType);
    }

    // If we are wrapped in a [TryFinally] node then we have to run finalizers
    // as the stack unwinds. When we get to the top of the finalizer stack, we
    // will handle the return using [returnValueLocal] if this function returns
    // a value.
    if (finalizers.isNotEmpty) {
      for (TryBlockFinalizer finalizer in finalizers) {
        finalizer.mustHandleReturn = true;
      }
      if (returnType != voidMarker) {
        returnValueLocal ??= addLocal(returnType);
        b.local_set(returnValueLocal!);
      }
      b.br(finalizers.last.label);
    } else {
      _returnFromFunction();
    }
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    bool check<L extends Expression, C extends Constant>() =>
        node.cases.expand((c) => c.expressions).every((e) =>
            e is L ||
            e is NullLiteral ||
            e is ConstantExpression &&
                (e.constant is C || e.constant is NullConstant));

    // Identify kind of switch
    w.ValueType valueType;
    w.ValueType nullableType;
    void Function() compare;
    if (check<BoolLiteral, BoolConstant>()) {
      // bool switch
      valueType = w.NumType.i32;
      nullableType =
          translator.classInfo[translator.boxedBoolClass]!.nullableType;
      compare = () => b.i32_eq();
    } else if (check<IntLiteral, IntConstant>()) {
      // int switch
      valueType = w.NumType.i64;
      nullableType =
          translator.classInfo[translator.boxedIntClass]!.nullableType;
      compare = () => b.i64_eq();
    } else if (check<StringLiteral, StringConstant>()) {
      // String switch
      valueType =
          translator.classInfo[translator.stringBaseClass]!.nonNullableType;
      nullableType = valueType.withNullability(true);
      compare = () => _call(translator.stringEquals.reference);
    } else {
      // Object switch
      assert(check<InvalidExpression, InstanceConstant>());
      valueType = w.RefType.eq(nullable: false);
      nullableType = w.RefType.eq(nullable: true);
      compare = () => b.ref_eq();
    }
    w.Local valueLocal = addLocal(valueType);

    // Special cases
    SwitchCase? defaultCase = node.cases
        .cast<SwitchCase?>()
        .firstWhere((c) => c!.isDefault, orElse: () => null);
    SwitchCase? nullCase = node.cases.cast<SwitchCase?>().firstWhere(
        (c) => c!.expressions.any((e) =>
            e is NullLiteral ||
            e is ConstantExpression && e.constant is NullConstant),
        orElse: () => null);

    // Set up blocks, in reverse order of cases so they end in forward order
    w.Label doneLabel = b.block();
    for (SwitchCase c in node.cases.reversed) {
      switchLabels[c] = b.block();
    }

    // Compute value and handle null
    bool isNullable = dartTypeOf(node.expression).isPotentiallyNullable;
    if (isNullable) {
      w.Label nullLabel = nullCase != null
          ? switchLabels[nullCase]!
          : defaultCase != null
              ? switchLabels[defaultCase]!
              : doneLabel;
      wrap(node.expression, nullableType);
      b.br_on_null(nullLabel);
      translator.convertType(
          function, nullableType.withNullability(false), valueType);
    } else {
      assert(nullCase == null);
      wrap(node.expression, valueType);
    }
    b.local_set(valueLocal);

    // Compare against all case values
    for (SwitchCase c in node.cases) {
      for (Expression exp in c.expressions) {
        if (exp is NullLiteral ||
            exp is ConstantExpression && exp.constant is NullConstant) {
          // Null already checked, skip
        } else {
          wrap(exp, valueType);
          b.local_get(valueLocal);
          translator.convertType(function, valueLocal.type, valueType);
          compare();
          b.br_if(switchLabels[c]!);
        }
      }
    }
    w.Label defaultLabel =
        defaultCase != null ? switchLabels[defaultCase]! : doneLabel;
    b.br(defaultLabel);

    // Emit case bodies
    for (SwitchCase c in node.cases) {
      switchLabels.remove(c);
      b.end();
      c.body.accept(this);
      b.br(doneLabel);
    }
    b.end();
  }

  @override
  void visitContinueSwitchStatement(ContinueSwitchStatement node) {
    w.Label? label = switchLabels[node.target];
    if (label != null) {
      b.br(label);
    } else {
      throw "Not supported: Backward jump to switch case at ${node.location}";
    }
  }

  @override
  void visitYieldStatement(YieldStatement node) => defaultStatement(node);

  @override
  w.ValueType visitBlockExpression(
      BlockExpression node, w.ValueType expectedType) {
    node.body.accept(this);
    return wrap(node.value, expectedType);
  }

  @override
  w.ValueType visitLet(Let node, w.ValueType expectedType) {
    node.variable.accept(this);
    return wrap(node.body, expectedType);
  }

  @override
  w.ValueType visitThisExpression(
      ThisExpression node, w.ValueType expectedType) {
    return _visitThis(expectedType);
  }

  w.ValueType _visitThis(w.ValueType expectedType) {
    w.ValueType thisType = thisLocal!.type.withNullability(false);
    w.ValueType preciseThisType = preciseThisLocal!.type.withNullability(false);
    if (!thisType.isSubtypeOf(expectedType) &&
        preciseThisType.isSubtypeOf(expectedType)) {
      b.local_get(preciseThisLocal!);
      return preciseThisLocal!.type;
    } else {
      b.local_get(thisLocal!);
      return thisLocal!.type;
    }
  }

  @override
  w.ValueType visitConstructorInvocation(
      ConstructorInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult =
        intrinsifier.generateConstructorIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    ClassInfo info = translator.classInfo[node.target.enclosingClass]!;
    translator.functions.allocateClass(info.classId);
    w.Local temp = addLocal(info.nonNullableType);
    translator.struct_new_default(b, info);
    b.local_tee(temp);
    b.local_get(temp);
    b.i32_const(info.classId);
    b.struct_set(info.struct, FieldIndex.classId);
    if (options.parameterNullability && temp.type.nullable) {
      b.ref_as_non_null();
    }
    _visitArguments(node.arguments, node.targetReference, 1);
    _call(node.targetReference);
    if (expectedType != voidMarker) {
      b.local_get(temp);
      return temp.type;
    } else {
      return voidMarker;
    }
  }

  @override
  w.ValueType visitStaticInvocation(
      StaticInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult = intrinsifier.generateStaticIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    _visitArguments(node.arguments, node.targetReference, 0);
    return _call(node.targetReference);
  }

  Member _lookupSuperTarget(Member interfaceTarget, {required bool setter}) {
    return translator.hierarchy.getDispatchTarget(
        member.enclosingClass!.superclass!, interfaceTarget.name,
        setter: setter)!;
  }

  @override
  w.ValueType visitSuperMethodInvocation(
      SuperMethodInvocation node, w.ValueType expectedType) {
    Reference target =
        _lookupSuperTarget(node.interfaceTarget!, setter: false).reference;
    w.BaseFunction targetFunction = translator.functions.getFunction(target);
    w.ValueType receiverType = targetFunction.type.inputs.first;
    w.ValueType thisType = _visitThis(receiverType);
    translator.convertType(function, thisType, receiverType);
    _visitArguments(node.arguments, target, 1);
    return _call(target);
  }

  @override
  w.ValueType visitInstanceInvocation(
      InstanceInvocation node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult = intrinsifier.generateInstanceIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    Procedure target = node.interfaceTarget;
    if (node.kind == InstanceAccessKind.Object) {
      switch (target.name.text) {
        case "toString":
          late w.Label done;
          w.ValueType resultType = _virtualCall(node, target, (signature) {
            done = b.block(const [], signature.outputs);
            w.Label nullString = b.block();
            wrap(node.receiver, translator.topInfo.nullableType);
            b.br_on_null(nullString);
          }, (_) {
            _visitArguments(node.arguments, node.interfaceTargetReference, 1);
          }, getter: false, setter: false);
          b.br(done);
          b.end();
          wrap(StringLiteral("null"), resultType);
          b.end();
          return resultType;
        default:
          _unimplemented(node, "Nullable invocation of ${target.name.text}",
              [if (expectedType != voidMarker) expectedType]);
          return expectedType;
      }
    }
    Member? singleTarget = translator.singleTarget(node);
    if (singleTarget != null) {
      w.BaseFunction targetFunction =
          translator.functions.getFunction(singleTarget.reference);
      wrap(node.receiver, targetFunction.type.inputs.first);
      _visitArguments(node.arguments, node.interfaceTargetReference, 1);
      return _call(singleTarget.reference);
    }
    return _virtualCall(node, target,
        (signature) => wrap(node.receiver, signature.inputs.first), (_) {
      _visitArguments(node.arguments, node.interfaceTargetReference, 1);
    }, getter: false, setter: false);
  }

  @override
  w.ValueType visitDynamicInvocation(
      DynamicInvocation node, w.ValueType expectedType) {
    if (node.name.text != "call") {
      _unimplemented(node, "Dynamic invocation of ${node.name.text}",
          [if (expectedType != voidMarker) expectedType]);
      return expectedType;
    }
    return _functionCall(
        node.arguments.positional.length, node.receiver, node.arguments);
  }

  @override
  w.ValueType visitEqualsCall(EqualsCall node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult = intrinsifier.generateEqualsIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    Member? singleTarget = translator.singleTarget(node);
    if (singleTarget == translator.coreTypes.objectEquals) {
      // Plain reference comparison
      wrap(node.left, w.RefType.eq(nullable: true));
      wrap(node.right, w.RefType.eq(nullable: true));
      b.ref_eq();
    } else {
      // Check operands for null, then call implementation
      bool leftNullable = dartTypeOf(node.left).isPotentiallyNullable;
      bool rightNullable = dartTypeOf(node.right).isPotentiallyNullable;
      w.RefType leftType = translator.topInfo.typeWithNullability(leftNullable);
      w.RefType rightType =
          translator.topInfo.typeWithNullability(rightNullable);
      w.Local leftLocal = addLocal(leftType);
      w.Local rightLocal = addLocal(rightType);
      w.Label? operandNull;
      w.Label? done;
      if (leftNullable || rightNullable) {
        done = b.block(const [], const [w.NumType.i32]);
        operandNull = b.block();
      }
      wrap(node.left, leftLocal.type);
      b.local_set(leftLocal);
      wrap(node.right, rightLocal.type);
      if (rightNullable) {
        b.local_tee(rightLocal);
        b.br_on_null(operandNull!);
        b.drop();
      } else {
        b.local_set(rightLocal);
      }

      void left([_]) {
        b.local_get(leftLocal);
        if (leftNullable) {
          b.br_on_null(operandNull!);
        } else if (leftLocal.type.nullable) {
          b.ref_as_non_null();
        }
      }

      void right([_]) {
        b.local_get(rightLocal);
        if (rightLocal.type.nullable) {
          b.ref_as_non_null();
        }
      }

      if (singleTarget != null) {
        left();
        right();
        _call(singleTarget.reference);
      } else {
        _virtualCall(node, node.interfaceTarget, left, right,
            getter: false, setter: false);
      }
      if (leftNullable || rightNullable) {
        b.br(done!);
        b.end(); // operandNull
        if (leftNullable && rightNullable) {
          // Both sides nullable - compare references
          b.local_get(leftLocal);
          b.local_get(rightLocal);
          b.ref_eq();
        } else {
          // Only one side nullable - not equal if one is null
          b.i32_const(0);
        }
        b.end(); // done
      }
    }
    return w.NumType.i32;
  }

  @override
  w.ValueType visitEqualsNull(EqualsNull node, w.ValueType expectedType) {
    wrap(node.expression, const w.RefType.any());
    b.ref_is_null();
    return w.NumType.i32;
  }

  w.ValueType _virtualCall(
      TreeNode node,
      Member interfaceTarget,
      void pushReceiver(w.FunctionType signature),
      void pushArguments(w.FunctionType signature),
      {required bool getter,
      required bool setter}) {
    SelectorInfo selector = translator.dispatchTable.selectorForTarget(
        interfaceTarget.referenceAs(getter: getter, setter: setter));
    assert(selector.name == interfaceTarget.name.text);

    pushReceiver(selector.signature);

    int? offset = selector.offset;
    if (offset == null) {
      // Singular target or unreachable call
      assert(selector.targetCount <= 1);
      if (selector.targetCount == 1) {
        pushArguments(selector.signature);
        return _call(selector.singularTarget!);
      } else {
        b.comment("Virtual call of ${selector.name} with no targets"
            " at ${node.location}");
        b.drop();
        b.block(const [], selector.signature.outputs);
        b.unreachable();
        b.end();
        return translator.outputOrVoid(selector.signature.outputs);
      }
    }

    // Receiver is already on stack.
    w.Local receiverVar = addLocal(selector.signature.inputs.first);
    b.local_tee(receiverVar);
    if (options.parameterNullability && receiverVar.type.nullable) {
      b.ref_as_non_null();
    }
    pushArguments(selector.signature);

    if (options.polymorphicSpecialization) {
      _polymorphicSpecialization(selector, receiverVar);
    } else {
      String access = getter ? "get" : (setter ? "set" : "call");
      b.comment("Instance $access of '${selector.name}'");
      b.local_get(receiverVar);
      b.struct_get(translator.topInfo.struct, FieldIndex.classId);
      if (offset != 0) {
        b.i32_const(offset);
        b.i32_add();
      }
      b.call_indirect(selector.signature);

      translator.functions.activateSelector(selector);
    }

    return translator.outputOrVoid(selector.signature.outputs);
  }

  void _polymorphicSpecialization(SelectorInfo selector, w.Local receiver) {
    Map<int, Reference> implementations = Map.from(selector.targets);
    implementations.removeWhere((id, target) => target.asMember.isAbstract);

    w.Local idVar = addLocal(w.NumType.i32);
    b.local_get(receiver);
    b.struct_get(translator.topInfo.struct, FieldIndex.classId);
    b.local_set(idVar);

    w.Label block =
        b.block(selector.signature.inputs, selector.signature.outputs);
    calls:
    while (Set.from(implementations.values).length > 1) {
      for (int id in implementations.keys) {
        Reference target = implementations[id]!;
        if (implementations.values.where((t) => t == target).length == 1) {
          // Single class id implements method.
          b.local_get(idVar);
          b.i32_const(id);
          b.i32_eq();
          b.if_(selector.signature.inputs, selector.signature.inputs);
          _call(target);
          b.br(block);
          b.end();
          implementations.remove(id);
          continue calls;
        }
      }
      // Find class id that separates remaining classes in two.
      List<int> sorted = implementations.keys.toList()..sort();
      int pivotId = sorted.firstWhere(
          (id) => implementations[id] != implementations[sorted.first]);
      // Fail compilation if no such id exists.
      assert(sorted.lastWhere(
              (id) => implementations[id] != implementations[pivotId]) ==
          pivotId - 1);
      Reference target = implementations[sorted.first]!;
      b.local_get(idVar);
      b.i32_const(pivotId);
      b.i32_lt_u();
      b.if_(selector.signature.inputs, selector.signature.inputs);
      _call(target);
      b.br(block);
      b.end();
      for (int id in sorted) {
        if (id == pivotId) break;
        implementations.remove(id);
      }
      continue calls;
    }
    // Call remaining implementation.
    Reference target = implementations.values.first;
    _call(target);
    b.end();
  }

  @override
  w.ValueType visitVariableGet(VariableGet node, w.ValueType expectedType) {
    w.Local? local = locals[node.variable];
    Capture? capture = closures.captures[node.variable];
    if (capture != null) {
      if (!capture.written && local != null) {
        b.local_get(local);
        return local.type;
      } else {
        b.local_get(capture.context.currentLocal);
        b.struct_get(capture.context.struct, capture.fieldIndex);
        return capture.type;
      }
    } else {
      if (local == null) {
        throw "Read of undefined variable ${node.variable}";
      }
      b.local_get(local);
      return local.type;
    }
  }

  @override
  w.ValueType visitVariableSet(VariableSet node, w.ValueType expectedType) {
    w.Local? local = locals[node.variable];
    Capture? capture = closures.captures[node.variable];
    bool preserved = expectedType != voidMarker;
    if (capture != null) {
      assert(capture.written);
      b.local_get(capture.context.currentLocal);
      wrap(node.value, capture.type);
      if (preserved) {
        w.Local temp = addLocal(translateType(node.variable.type));
        b.local_tee(temp);
        b.struct_set(capture.context.struct, capture.fieldIndex);
        b.local_get(temp);
        return temp.type;
      } else {
        b.struct_set(capture.context.struct, capture.fieldIndex);
        return voidMarker;
      }
    } else {
      if (local == null) {
        throw "Write of undefined variable ${node.variable}";
      }
      wrap(node.value, local.type);
      if (preserved) {
        b.local_tee(local);
        return local.type;
      } else {
        b.local_set(local);
        return voidMarker;
      }
    }
  }

  @override
  w.ValueType visitStaticGet(StaticGet node, w.ValueType expectedType) {
    w.ValueType? intrinsicResult =
        intrinsifier.generateStaticGetterIntrinsic(node);
    if (intrinsicResult != null) return intrinsicResult;

    Member target = node.target;
    if (target is Field) {
      return translator.globals.readGlobal(b, target);
    } else {
      return _call(target.reference);
    }
  }

  @override
  w.ValueType visitStaticTearOff(StaticTearOff node, w.ValueType expectedType) {
    translator.constants.instantiateConstant(
        function, b, StaticTearOffConstant(node.target), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitStaticSet(StaticSet node, w.ValueType expectedType) {
    bool preserved = expectedType != voidMarker;
    Member target = node.target;
    if (target is Field) {
      w.Global global = translator.globals.getGlobal(target);
      wrap(node.value, global.type.type);
      b.global_set(global);
      if (preserved) {
        b.global_get(global);
        return global.type.type;
      } else {
        return voidMarker;
      }
    } else {
      w.BaseFunction targetFunction =
          translator.functions.getFunction(target.reference);
      wrap(node.value, targetFunction.type.inputs.single);
      w.Local? temp;
      if (preserved) {
        temp = addLocal(translateType(dartTypeOf(node.value)));
        b.local_tee(temp);
      }
      _call(target.reference);
      if (preserved) {
        b.local_get(temp!);
        return temp.type;
      } else {
        return voidMarker;
      }
    }
  }

  @override
  w.ValueType visitSuperPropertyGet(
      SuperPropertyGet node, w.ValueType expectedType) {
    Member target = _lookupSuperTarget(node.interfaceTarget!, setter: false);
    if (target is Procedure && !target.isGetter) {
      throw "Not supported: Super tear-off at ${node.location}";
    }
    return _directGet(target, ThisExpression(), () => null);
  }

  @override
  w.ValueType visitSuperPropertySet(
      SuperPropertySet node, w.ValueType expectedType) {
    Member target = _lookupSuperTarget(node.interfaceTarget!, setter: true);
    return _directSet(target, ThisExpression(), node.value,
        preserved: expectedType != voidMarker);
  }

  @override
  w.ValueType visitInstanceGet(InstanceGet node, w.ValueType expectedType) {
    Member target = node.interfaceTarget;
    if (node.kind == InstanceAccessKind.Object) {
      late w.Label doneLabel;
      w.ValueType resultType = _virtualCall(node, target, (signature) {
        doneLabel = b.block(const [], signature.outputs);
        w.Label nullLabel = b.block();
        wrap(node.receiver, translator.topInfo.nullableType);
        b.br_on_null(nullLabel);
      }, (_) {}, getter: true, setter: false);
      b.br(doneLabel);
      b.end(); // nullLabel
      switch (target.name.text) {
        case "hashCode":
          b.i64_const(2011);
          break;
        case "runtimeType":
          wrap(ConstantExpression(TypeLiteralConstant(NullType())), resultType);
          break;
        default:
          _unimplemented(
              node, "Nullable get of ${target.name.text}", [resultType]);
          break;
      }
      b.end(); // doneLabel
      return resultType;
    }
    Member? singleTarget = translator.singleTarget(node);
    if (singleTarget != null) {
      return _directGet(singleTarget, node.receiver,
          () => intrinsifier.generateInstanceGetterIntrinsic(node));
    } else {
      return _virtualCall(node, target,
          (signature) => wrap(node.receiver, signature.inputs.first), (_) {},
          getter: true, setter: false);
    }
  }

  @override
  w.ValueType visitDynamicGet(DynamicGet node, w.ValueType expectedType) {
    // Provisional implementation of dynamic get which assumes the getter
    // is present (otherwise it traps or calls something random) and
    // does not support tearoffs. This is sufficient to handle the
    // dynamic .length calls in the core libraries.

    SelectorInfo selector =
        translator.dispatchTable.selectorForDynamicName(node.name.text);

    // Evaluate receiver
    wrap(node.receiver, selector.signature.inputs.first);
    w.Local receiverVar = addLocal(selector.signature.inputs.first);
    b.local_tee(receiverVar);
    if (options.parameterNullability && receiverVar.type.nullable) {
      b.ref_as_non_null();
    }

    // Dispatch table call
    b.comment("Dynamic get of '${selector.name}'");
    int offset = selector.offset!;
    b.local_get(receiverVar);
    b.struct_get(translator.topInfo.struct, FieldIndex.classId);
    if (offset != 0) {
      b.i32_const(offset);
      b.i32_add();
    }
    b.call_indirect(selector.signature);

    translator.functions.activateSelector(selector);

    return translator.outputOrVoid(selector.signature.outputs);
  }

  w.ValueType _directGet(
      Member target, Expression receiver, w.ValueType? Function() intrinsify) {
    w.ValueType? intrinsicResult = intrinsify();
    if (intrinsicResult != null) return intrinsicResult;

    if (target is Field) {
      ClassInfo info = translator.classInfo[target.enclosingClass]!;
      int fieldIndex = translator.fieldIndex[target]!;
      w.ValueType receiverType = info.nullableType;
      w.ValueType fieldType = info.struct.fields[fieldIndex].type.unpacked;
      wrap(receiver, receiverType);
      b.struct_get(info.struct, fieldIndex);
      return fieldType;
    } else {
      // Instance call of getter
      assert(target is Procedure && target.isGetter);
      w.BaseFunction targetFunction =
          translator.functions.getFunction(target.reference);
      wrap(receiver, targetFunction.type.inputs.single);
      return _call(target.reference);
    }
  }

  @override
  w.ValueType visitInstanceTearOff(
      InstanceTearOff node, w.ValueType expectedType) {
    return _virtualCall(node, node.interfaceTarget,
        (signature) => wrap(node.receiver, signature.inputs.first), (_) {},
        getter: true, setter: false);
  }

  @override
  w.ValueType visitInstanceSet(InstanceSet node, w.ValueType expectedType) {
    bool preserved = expectedType != voidMarker;
    w.Local? temp;
    Member? singleTarget = translator.singleTarget(node);
    if (singleTarget != null) {
      return _directSet(singleTarget, node.receiver, node.value,
          preserved: preserved);
    } else {
      _virtualCall(node, node.interfaceTarget,
          (signature) => wrap(node.receiver, signature.inputs.first),
          (signature) {
        w.ValueType paramType = signature.inputs.last;
        wrap(node.value, paramType);
        if (preserved) {
          temp = addLocal(paramType);
          b.local_tee(temp!);
        }
      }, getter: false, setter: true);
      if (preserved) {
        b.local_get(temp!);
        return temp!.type;
      } else {
        return voidMarker;
      }
    }
  }

  w.ValueType _directSet(Member target, Expression receiver, Expression value,
      {required bool preserved}) {
    w.Local? temp;
    if (target is Field) {
      ClassInfo info = translator.classInfo[target.enclosingClass]!;
      int fieldIndex = translator.fieldIndex[target]!;
      w.ValueType receiverType = info.nullableType;
      w.ValueType fieldType = info.struct.fields[fieldIndex].type.unpacked;
      wrap(receiver, receiverType);
      wrap(value, fieldType);
      if (preserved) {
        temp = addLocal(fieldType);
        b.local_tee(temp);
      }
      b.struct_set(info.struct, fieldIndex);
    } else {
      w.BaseFunction targetFunction =
          translator.functions.getFunction(target.reference);
      w.ValueType paramType = targetFunction.type.inputs.last;
      wrap(receiver, targetFunction.type.inputs.first);
      wrap(value, paramType);
      if (preserved) {
        temp = addLocal(paramType);
        b.local_tee(temp);
        translator.convertType(function, temp.type, paramType);
      }
      _call(target.reference);
    }
    if (preserved) {
      b.local_get(temp!);
      return temp.type;
    } else {
      return voidMarker;
    }
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    Capture? capture = closures.captures[node.variable];
    bool locallyClosurized = closures.closurizedFunctions.contains(node);
    if (capture != null || locallyClosurized) {
      if (capture != null) {
        b.local_get(capture.context.currentLocal);
      }
      w.StructType struct = _instantiateClosure(node.function);
      if (locallyClosurized) {
        w.Local local = addLocal(w.RefType.def(struct, nullable: false));
        locals[node.variable] = local;
        if (capture != null) {
          b.local_tee(local);
        } else {
          b.local_set(local);
        }
      }
      if (capture != null) {
        b.struct_set(capture.context.struct, capture.fieldIndex);
      }
    }
  }

  @override
  w.ValueType visitFunctionExpression(
      FunctionExpression node, w.ValueType expectedType) {
    w.StructType struct = _instantiateClosure(node.function);
    return w.RefType.def(struct, nullable: false);
  }

  w.StructType _instantiateClosure(FunctionNode functionNode) {
    int parameterCount = functionNode.requiredParameterCount;
    Lambda lambda = closures.lambdas[functionNode]!;
    w.DefinedGlobal global = translator.makeFunctionRef(lambda.function);

    ClassInfo info = translator.classInfo[translator.functionClass]!;
    translator.functions.allocateClass(info.classId);
    w.StructType struct = translator.closureStructType(parameterCount);

    b.i32_const(info.classId);
    b.i32_const(initialIdentityHash);
    _pushContext(functionNode);
    b.global_get(global);
    translator.struct_new(b, parameterCount);

    return struct;
  }

  void _pushContext(FunctionNode functionNode) {
    Context? context = closures.contexts[functionNode]?.parent;
    if (context != null) {
      b.local_get(context.currentLocal);
      if (context.currentLocal.type.nullable) {
        b.ref_as_non_null();
      }
    } else {
      b.global_get(translator.globals.dummyGlobal); // Dummy context
    }
  }

  @override
  w.ValueType visitFunctionInvocation(
      FunctionInvocation node, w.ValueType expectedType) {
    Expression receiver = node.receiver;
    if (receiver is InstanceGet &&
        receiver.interfaceTarget == translator.wasmFunctionCall) {
      // Receiver is a WasmFunction
      assert(receiver.name.text == "call");
      w.RefType receiverType =
          translator.translateType(dartTypeOf(receiver.receiver)) as w.RefType;
      w.Local temp = addLocal(receiverType);
      wrap(receiver.receiver, receiverType);
      b.local_set(temp);
      w.FunctionType functionType = receiverType.heapType as w.FunctionType;
      assert(node.arguments.positional.length == functionType.inputs.length);
      for (int i = 0; i < node.arguments.positional.length; i++) {
        wrap(node.arguments.positional[i], functionType.inputs[i]);
      }
      b.local_get(temp);
      b.call_ref();
      return translator.outputOrVoid(functionType.outputs);
    }
    int parameterCount = node.functionType?.requiredParameterCount ??
        node.arguments.positional.length;
    return _functionCall(parameterCount, receiver, node.arguments);
  }

  w.ValueType _functionCall(
      int parameterCount, Expression receiver, Arguments arguments) {
    w.StructType struct = translator.closureStructType(parameterCount);
    w.Local temp = addLocal(w.RefType.def(struct, nullable: false));
    wrap(receiver, temp.type);
    b.local_tee(temp);
    b.struct_get(struct, FieldIndex.closureContext);
    for (Expression arg in arguments.positional) {
      wrap(arg, translator.topInfo.nullableType);
    }
    b.local_get(temp);
    b.struct_get(struct, FieldIndex.closureFunction);
    b.call_ref();
    return translator.topInfo.nullableType;
  }

  @override
  w.ValueType visitLocalFunctionInvocation(
      LocalFunctionInvocation node, w.ValueType expectedType) {
    var decl = node.variable.parent as FunctionDeclaration;
    _pushContext(decl.function);
    for (Expression arg in node.arguments.positional) {
      wrap(arg, translator.topInfo.nullableType);
    }
    Lambda lambda = closures.lambdas[decl.function]!;
    b.comment("Local call of ${decl.variable.name}");
    b.call(lambda.function);
    return translator.topInfo.nullableType;
  }

  @override
  w.ValueType visitLogicalExpression(
      LogicalExpression node, w.ValueType expectedType) {
    _conditional(node, () => b.i32_const(1), () => b.i32_const(0),
        const [w.NumType.i32]);
    return w.NumType.i32;
  }

  @override
  w.ValueType visitNot(Not node, w.ValueType expectedType) {
    wrap(node.operand, w.NumType.i32);
    b.i32_eqz();
    return w.NumType.i32;
  }

  @override
  w.ValueType visitConditionalExpression(
      ConditionalExpression node, w.ValueType expectedType) {
    _conditional(
        node.condition,
        () => wrap(node.then, expectedType),
        () => wrap(node.otherwise, expectedType),
        [if (expectedType != voidMarker) expectedType]);
    return expectedType;
  }

  @override
  w.ValueType visitNullCheck(NullCheck node, w.ValueType expectedType) {
    w.ValueType operandType =
        translator.translateType(dartTypeOf(node.operand));
    w.ValueType nonNullOperandType = operandType.withNullability(false);
    w.Label nullCheckBlock = b.block(const [], [nonNullOperandType]);
    wrap(node.operand, operandType);

    // We lower a null check to a br_on_non_null, throwing a [TypeError] in the
    // null case.
    b.br_on_non_null(nullCheckBlock);
    _call(translator.stackTraceCurrent.reference);
    _call(translator.throwNullCheckError.reference);
    b.unreachable();
    b.end();
    return nonNullOperandType;
  }

  void _visitArguments(Arguments node, Reference target, int signatureOffset) {
    final w.FunctionType signature = translator.signatureFor(target);
    final ParameterInfo paramInfo = translator.paramInfoFor(target);
    for (int i = 0; i < node.types.length; i++) {
      _makeType(node.types[i], node);
    }
    signatureOffset += node.types.length;
    for (int i = 0; i < node.positional.length; i++) {
      wrap(node.positional[i], signature.inputs[signatureOffset + i]);
    }
    // Default values for positional parameters
    for (int i = node.positional.length; i < paramInfo.positional.length; i++) {
      final w.ValueType type = signature.inputs[signatureOffset + i];
      translator.constants
          .instantiateConstant(function, b, paramInfo.positional[i]!, type);
    }
    // Named arguments
    final Map<String, w.Local> namedLocals = {};
    for (var namedArg in node.named) {
      final w.ValueType type = signature
          .inputs[signatureOffset + paramInfo.nameIndex[namedArg.name]!];
      final w.Local namedLocal = addLocal(type);
      namedLocals[namedArg.name] = namedLocal;
      wrap(namedArg.value, namedLocal.type);
      b.local_set(namedLocal);
    }
    for (String name in paramInfo.names) {
      w.Local? namedLocal = namedLocals[name];
      final w.ValueType type =
          signature.inputs[signatureOffset + paramInfo.nameIndex[name]!];
      if (namedLocal != null) {
        b.local_get(namedLocal);
        translator.convertType(function, namedLocal.type, type);
      } else {
        translator.constants
            .instantiateConstant(function, b, paramInfo.named[name]!, type);
      }
    }
  }

  @override
  w.ValueType visitStringConcatenation(
      StringConcatenation node, w.ValueType expectedType) {
    _makeList(
        node.expressions,
        translator.fixedLengthListClass,
        InterfaceType(translator.stringBaseClass, Nullability.nonNullable),
        node);
    return _call(translator.stringInterpolate.reference);
  }

  @override
  w.ValueType visitThrow(Throw node, w.ValueType expectedType) {
    wrap(node.expression, translator.topInfo.nonNullableType);
    _call(translator.stackTraceCurrent.reference);

    // At this point, we have the exception and the current stack trace on the
    // stack, so just throw them using the exception tag.
    b.throw_(translator.exceptionTag);
    return expectedType;
  }

  @override
  w.ValueType visitRethrow(Rethrow node, w.ValueType expectedType) {
    b.rethrow_(tryLabels.last);
    return expectedType;
  }

  @override
  w.ValueType visitInstantiation(Instantiation node, w.ValueType expectedType) {
    throw "Not supported: Generic function instantiation at ${node.location}";
  }

  @override
  w.ValueType visitConstantExpression(
      ConstantExpression node, w.ValueType expectedType) {
    translator.constants
        .instantiateConstant(function, b, node.constant, expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitNullLiteral(NullLiteral node, w.ValueType expectedType) {
    translator.constants
        .instantiateConstant(function, b, NullConstant(), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitStringLiteral(StringLiteral node, w.ValueType expectedType) {
    translator.constants.instantiateConstant(
        function, b, StringConstant(node.value), expectedType);
    return expectedType;
  }

  @override
  w.ValueType visitBoolLiteral(BoolLiteral node, w.ValueType expectedType) {
    b.i32_const(node.value ? 1 : 0);
    return w.NumType.i32;
  }

  @override
  w.ValueType visitIntLiteral(IntLiteral node, w.ValueType expectedType) {
    b.i64_const(node.value);
    return w.NumType.i64;
  }

  @override
  w.ValueType visitDoubleLiteral(DoubleLiteral node, w.ValueType expectedType) {
    b.f64_const(node.value);
    return w.NumType.f64;
  }

  @override
  w.ValueType visitListLiteral(ListLiteral node, w.ValueType expectedType) {
    return _makeList(node.expressions, translator.growableListClass,
        node.typeArgument, node);
  }

  w.ValueType _makeList(List<Expression> expressions, Class cls,
      DartType typeArg, TreeNode node) {
    ClassInfo info = translator.classInfo[cls]!;
    translator.functions.allocateClass(info.classId);
    w.RefType refType = info.struct.fields.last.type.unpacked as w.RefType;
    w.ArrayType arrayType = refType.heapType as w.ArrayType;
    w.ValueType elementType = arrayType.elementType.type.unpacked;
    int length = expressions.length;

    b.i32_const(info.classId);
    b.i32_const(initialIdentityHash);
    _makeType(typeArg, node);
    b.i64_const(length);
    if (options.lazyConstants) {
      // Avoid array.init instruction in lazy constants mode
      b.i32_const(length);
      translator.array_new_default(b, arrayType);
      if (length > 0) {
        w.Local arrayLocal = addLocal(refType.withNullability(false));
        b.local_set(arrayLocal);
        for (int i = 0; i < length; i++) {
          b.local_get(arrayLocal);
          b.i32_const(i);
          wrap(expressions[i], elementType);
          b.array_set(arrayType);
        }
        b.local_get(arrayLocal);
        if (arrayLocal.type.nullable) {
          b.ref_as_non_null();
        }
      }
    } else {
      for (Expression expression in expressions) {
        wrap(expression, elementType);
      }
      translator.array_init(b, arrayType, length);
    }
    translator.struct_new(b, info);

    return info.nonNullableType;
  }

  @override
  w.ValueType visitMapLiteral(MapLiteral node, w.ValueType expectedType) {
    w.BaseFunction mapFactory =
        translator.functions.getFunction(translator.mapFactory.reference);
    w.ValueType factoryReturnType = mapFactory.type.outputs.single;
    _makeType(node.keyType, node);
    _makeType(node.valueType, node);
    b.call(mapFactory);
    if (node.entries.isEmpty) {
      return factoryReturnType;
    }
    w.BaseFunction mapPut =
        translator.functions.getFunction(translator.mapPut.reference);
    w.ValueType putReceiverType = mapPut.type.inputs[0];
    w.ValueType putKeyType = mapPut.type.inputs[1];
    w.ValueType putValueType = mapPut.type.inputs[2];
    w.Local mapLocal = addLocal(putReceiverType);
    translator.convertType(function, factoryReturnType, mapLocal.type);
    b.local_set(mapLocal);
    for (MapLiteralEntry entry in node.entries) {
      b.local_get(mapLocal);
      translator.convertType(function, mapLocal.type, putReceiverType);
      wrap(entry.key, putKeyType);
      wrap(entry.value, putValueType);
      b.call(mapPut);
    }
    b.local_get(mapLocal);
    return mapLocal.type;
  }

  @override
  w.ValueType visitTypeLiteral(TypeLiteral node, w.ValueType expectedType) {
    return _makeType(node.type, node);
  }

  w.ValueType _makeType(DartType type, TreeNode node) {
    w.ValueType typeType =
        translator.classInfo[translator.typeClass]!.nullableType;
    if (_isTypeConstant(type)) {
      return wrap(ConstantExpression(TypeLiteralConstant(type)), typeType);
    }
    if (type is TypeParameterType) {
      if (type.parameter.parent is FunctionNode) {
        // Type argument to function
        w.Local? local = typeLocals[type.parameter];
        if (local != null) {
          b.local_get(local);
          return local.type;
        } else {
          _unimplemented(
              node, "Type parameter access inside lambda", [typeType]);
          return typeType;
        }
      }
      // Type argument of class
      Class cls = type.parameter.parent as Class;
      ClassInfo info = translator.classInfo[cls]!;
      int fieldIndex = translator.typeParameterIndex[type.parameter]!;
      w.ValueType thisType = _visitThis(info.nullableType);
      translator.convertType(function, thisType, info.nullableType);
      b.struct_get(info.struct, fieldIndex);
      return typeType;
    }
    ClassInfo info = translator.classInfo[translator.typeClass]!;
    translator.functions.allocateClass(info.classId);
    if (type is FutureOrType) {
      // TODO(askesc): Have an actual representation of FutureOr types
      b.ref_null(info.nullableType.heapType);
      return info.nullableType;
    }
    if (type is! InterfaceType) {
      _unimplemented(node, type, [info.nullableType]);
      return info.nullableType;
    }
    ClassInfo typeInfo = translator.classInfo[type.classNode]!;
    w.ValueType typeListExpectedType = info.struct.fields[3].type.unpacked;
    b.i32_const(info.classId);
    b.i32_const(initialIdentityHash);
    b.i64_const(typeInfo.classId);
    if (type.typeArguments.isEmpty) {
      b.global_get(translator.constants.emptyTypeList);
      translator.convertType(function,
          translator.constants.emptyTypeList.type.type, typeListExpectedType);
    } else if (type.typeArguments.every(_isTypeConstant)) {
      ListConstant typeArgs = ListConstant(
          InterfaceType(translator.typeClass, Nullability.nonNullable),
          type.typeArguments.map((t) => TypeLiteralConstant(t)).toList());
      translator.constants
          .instantiateConstant(function, b, typeArgs, typeListExpectedType);
    } else {
      w.ValueType listType = _makeList(
          type.typeArguments.map((t) => TypeLiteral(t)).toList(),
          translator.fixedLengthListClass,
          InterfaceType(translator.typeClass, Nullability.nonNullable),
          node);
      translator.convertType(function, listType, typeListExpectedType);
    }
    translator.struct_new(b, info);
    return info.nullableType;
  }

  bool _isTypeConstant(DartType type) {
    return type is DynamicType ||
        type is VoidType ||
        type is NeverType ||
        type is NullType ||
        type is FunctionType ||
        type is InterfaceType && type.typeArguments.every(_isTypeConstant);
  }

  @override
  w.ValueType visitIsExpression(IsExpression node, w.ValueType expectedType) {
    wrap(node.operand, translator.topInfo.nullableType);
    emitTypeTest(node.type, dartTypeOf(node.operand), node);
    return w.NumType.i32;
  }

  /// Test value against a Dart type. Expects the value on the stack as a
  /// (ref null #Top) and leaves the result on the stack as an i32.
  void emitTypeTest(DartType type, DartType operandType, TreeNode node) {
    if (type is! InterfaceType) {
      // TODO(askesc): Implement type test for remaining types
      print("Not implemented: Type test with non-interface type $type"
          " at ${node.location}");
      b.drop();
      b.i32_const(1);
      return;
    }
    bool isNullable = operandType.isPotentiallyNullable;
    w.Label? resultLabel;
    if (isNullable) {
      // Store operand in a temporary variable, since Binaryen does not support
      // block inputs.
      w.Local operand = addLocal(translator.topInfo.nullableType);
      b.local_set(operand);
      resultLabel = b.block(const [], const [w.NumType.i32]);
      w.Label nullLabel = b.block(const [], const []);
      b.local_get(operand);
      b.br_on_null(nullLabel);
    }
    if (type.typeArguments.any((t) => t is! DynamicType)) {
      // If the tested-against type as an instance of the static operand type
      // has the same type arguments as the static operand type, it is not
      // necessary to test the type arguments.
      Class cls = translator.classForType(operandType);
      InterfaceType? base = translator.hierarchy
          .getTypeAsInstanceOf(type, cls, member.enclosingLibrary)
          ?.withDeclaredNullability(operandType.declaredNullability);
      if (base != operandType) {
        print("Not implemented: Type test with type arguments"
            " at ${node.location}");
      }
    }
    List<Class> concrete = translator.subtypes
        .getSubtypesOf(type.classNode)
        .where((c) => !c.isAbstract)
        .toList();
    if (type.classNode == translator.coreTypes.functionClass) {
      ClassInfo functionInfo = translator.classInfo[translator.functionClass]!;
      translator.ref_test(b, functionInfo);
    } else if (concrete.isEmpty) {
      b.drop();
      b.i32_const(0);
    } else if (concrete.length == 1) {
      ClassInfo info = translator.classInfo[concrete.single]!;
      b.struct_get(translator.topInfo.struct, FieldIndex.classId);
      b.i32_const(info.classId);
      b.i32_eq();
    } else {
      w.Local idLocal = addLocal(w.NumType.i32);
      b.struct_get(translator.topInfo.struct, FieldIndex.classId);
      b.local_set(idLocal);
      w.Label done = b.block(const [], const [w.NumType.i32]);
      b.i32_const(1);
      for (Class cls in concrete) {
        ClassInfo info = translator.classInfo[cls]!;
        b.i32_const(info.classId);
        b.local_get(idLocal);
        b.i32_eq();
        b.br_if(done);
      }
      b.drop();
      b.i32_const(0);
      b.end(); // done
    }
    if (isNullable) {
      b.br(resultLabel!);
      b.end(); // nullLabel
      b.i32_const(type.declaredNullability == Nullability.nullable ? 1 : 0);
      b.end(); // resultLabel
    }
  }

  @override
  w.ValueType visitAsExpression(AsExpression node, w.ValueType expectedType) {
    w.Label asCheckBlock = b.block();
    wrap(node.operand, translator.topInfo.nullableType);
    w.Local operand = addLocal(translator.topInfo.nullableType);
    b.local_tee(operand);

    // We lower an `as` expression to a type test, throwing a [TypeError] if
    // the type test fails.
    emitTypeTest(node.type, dartTypeOf(node.operand), node);
    b.br_if(asCheckBlock);
    b.local_get(operand);
    _makeType(node.type, node);
    _call(translator.stackTraceCurrent.reference);
    _call(translator.throwAsCheckError.reference);
    b.unreachable();
    b.end();
    b.local_get(operand);
    return operand.type;
  }
}

class TryBlockFinalizer {
  final w.Label label;
  bool mustHandleReturn = false;

  TryBlockFinalizer(this.label);
}
