doOneLine method

void doOneLine(
  1. Line line,
  2. Context context
)

Implementation

void doOneLine(Line line, Context context) {
  if (line.op == LineOp.pushParam) {
    final val = context.valueInContext(line.rhsA);
    context.pushParamArgument(val);
  } else if (line.op == LineOp.callFunctionA) {
    // Resolve rhsA. If it's a function, invoke it; otherwise,
    // just store it directly (but pop the call context).
    var valueFoundInPointer = ValuePointer<ValMap>();
    final funcVal = line.rhsA!.valWithMap(context, valueFoundInPointer);

    if (funcVal is ValFunction) {
      Value? self;
      // Bind "super" to the parent of the map the function was found in
      final superVal = valueFoundInPointer.value
          ?.lookup(ValString.magicIsA, ValuePointer());

      if (line.rhsA is ValSeqElem) {
        // Bind "self" to the object used to invoke the call,
        // except when invoking via "super"
        final seq = (line.rhsA as ValSeqElem).sequence;
        if (seq is ValVar && (seq).identifier == "super") {
          self = context.self;
        } else {
          self = context.valueInContext(seq);
        }
      }

      final argCount = line.rhsB!.intValue();
      final nextContext = context.nextCallContext(
        funcVal.function,
        argCount,
        self != null,
        line.lhs,
      );

      nextContext.outerVars = funcVal.outerVars;
      if (valueFoundInPointer.value != null) {
        nextContext.setVar("super", superVal);
      }
      if (self != null) nextContext.self = self;
      stack.add(nextContext);
    } else {
      // The user is attempting to call something that's not a function.
      // We'll allow that, but any number of parameters is too many.  [#35]
      // (No need to pop them, as the exception will pop the whole call stack anyway.)
      int argCount = line.rhsB!.intValue();
      if (argCount > 0) throw TooManyArgumentsException();
      context.storeValue(line.lhs, funcVal);
    }
  } else if (line.op == LineOp.returnA) {
    final val = line.evaluate(context);
    context.storeValue(line.lhs, val);
    popContext();
  } else if (line.op == LineOp.assignImplicit) {
    final val = line.evaluate(context);
    if (storeImplicit) {
      context.storeValue(ValVar.implicitResult, val);
      context.implicitResultCounter++;
    }
  } else {
    final val = line.evaluate(context);
    context.storeValue(line.lhs, val);
  }
}