visitForLoopStmt method

  1. @override
Object? visitForLoopStmt(
  1. ForLoopStmt forLoopStmt
)
inherited

Implementation

@override
Object? visitForLoopStmt(ForLoopStmt forLoopStmt) {
  final prevScope = scope;
  pushScope();

  try {
    Object? control = forLoopStmt.control.accept(this);

    evalVar(Object? v) {
      if (v is LuaObject && v.valueAsInt() is int) {
        final String id = v.id;
        return (id, v.valueAsInt()!);
      } else {
        final String lineInfo = this.lineInfo(forLoopStmt.token);
        throw '$lineInfo For-loop control did not evaluate to a variable!';
      }
    }

    evalNum(LuaObject? n, String label) {
      if (n == null) {
        return 1;
      } else if (n.valueAs<num>() != null) {
        return n.valueAs<num>();
      }

      // n is not num
      throw '$lineInfo For-loop $label did not evaluate to a number!';
    }

    final String controlId;
    num ncontrol;
    (controlId, ncontrol) = evalVar(control);

    final num end = evalNum(forLoopStmt.endExpr.accept(this)?.unpack(), 'end')!;
    final num step = evalNum(forLoopStmt.stepExpr.accept(this)?.unpack(), 'step')!;

    while (ncontrol <= end) {
      defLocal(LuaObject.variable(controlId, ncontrol));

      for (int i = 0; i < forLoopStmt.body.length; i++) {
        final stmt = forLoopStmt.body[i];
        try {
          stmt.accept(this);
        } on LuaBreakStmtException {
          break;
        } on LuaReturnValueException {
          rethrow;
        } catch (e) {
          addError(e.toString());
        }
      }
      ncontrol += step;
    }
  } catch (e) {
    rethrow;
  } finally {
    restoreScope(prevScope);
  }

  return null;
}