JTokenToRuntimeObject static method

RuntimeObject? JTokenToRuntimeObject(
  1. dynamic token
)

Implementation

static RuntimeObject? JTokenToRuntimeObject(dynamic token) {
  if (token is int || token is double || token is bool) {
    return Value.create(token);
  }
  if (token is String) {
    var str = token;
    // String Value
    var firstChar = str[0];
    if (firstChar == '^') {
      return StringValue(str.substring(1));
    } else if (firstChar == '\n' && str.length == 1) {
      return StringValue('\n');
    }

    // Glue
    if (str == '<>') {
      return Glue();
    }

    // Control commands (would looking up in a hash set be faster?)
    for (var i = 0; i < controlCommandNames.length; ++i) {
      var cmdName = controlCommandNames[i];
      if (str == cmdName) {
        return ControlCommand(CommandType.values[i]);
      }
    }

    // Native functions
    // "^" conflicts with the way to identify strings, so now
    // we know it's not a string, we can convert back to the proper
    // symbol for the operator.
    if (str == 'L^') str = '^';
    if (NativeFunctionCall.callExistsWithName(str)) {
      return NativeFunctionCall.callWithName(str);
    }
    // Pop
    if (str == '->->') {
      return ControlCommand.PopTunnel();
    } else if (str == '~ret') {
      return ControlCommand.PopFunction();
    }

    // Void
    if (str == 'void') {
      return RuntimeVoid();
    }
  }

  if (token is Map<String, dynamic>) {
    var obj = token;
    dynamic propValue;

    // Divert target value to path
    propValue = obj['^->'];
    if (propValue != null) {
      return DivertTargetValue(Path(propValue as String));
    }

    // VariablePointerValue
    propValue = obj['^var'];
    if (propValue != null) {
      var varPtr = VariablePointerValue(obj['^var'] as String);

      propValue = obj['ci'];

      if (propValue != null) {
        varPtr.contextIndex = propValue as int;
      }
      return varPtr;
    }

    // Divert
    var isDivert = false;
    var pushesToStack = false;
    var divPushType = PushPopType.Function;
    var external = false;

    propValue = obj['->'];
    if (propValue != null) {
      isDivert = true;
    } else {
      propValue = obj['f()'];

      if (propValue != null) {
        isDivert = true;
        pushesToStack = true;
        divPushType = PushPopType.Function;
      } else {
        propValue = obj['->t->'];
        if (propValue != null) {
          isDivert = true;
          pushesToStack = true;
          divPushType = PushPopType.Tunnel;
        } else {
          propValue = obj['x()'];
          if (propValue != null) {
            isDivert = true;
            external = true;
            pushesToStack = false;
            divPushType = PushPopType.Function;
          }
        }
      }
    }
    if (isDivert) {
      var divert = Divert();
      divert.pushesToStack = pushesToStack;
      divert.stackPushType = divPushType;
      divert.isExternal = external;

      var target = propValue.toString();

      propValue = obj['var'];

      if (propValue != null) {
        divert.variableDivertName = target;
      } else {
        divert.targetPathString = target;
      }

      propValue = obj['c'];
      divert.isConditional = obj['c'] ?? false;

      if (external) {
        propValue = obj['exArgs'];
        if (propValue != null) {
          divert.externalArgs = obj['exArgs'] as int;
        }
      }

      return divert;
    }

    // Choice
    propValue = obj['*'];
    if (propValue != null) {
      var choice = ChoicePoint();
      choice.pathStringOnChoice = propValue.toString();
      propValue = obj['flg'];

      if (propValue != null) {
        choice.flags = obj['flg'] as int;
      }
      return choice;
    }

    // Variable reference
    propValue = obj['VAR?'];
    if (propValue != null) {
      return VariableReference(propValue.toString());
    } else {
      propValue = obj['CNT?'];
      if (propValue != null) {
        var readCountVarRef = VariableReference();
        readCountVarRef.pathStringForCount = propValue.toString();
        return readCountVarRef;
      }
    }

    // Variable assignment
    var isVarAss = false;
    var isGlobalVar = false;

    propValue = obj['VAR='];
    if (propValue != null) {
      isVarAss = true;
      isGlobalVar = true;
    } else {
      propValue = obj['temp='];
      if (propValue != null) {
        isVarAss = true;
        isGlobalVar = false;
      }
    }
    if (isVarAss) {
      var varName = propValue.toString();
      propValue = obj['re'];
      bool isNewDecl = propValue == null;

      var varAss = VariableAssignment(varName, isNewDecl);
      varAss.isGlobal = isGlobalVar;
      return varAss;
    }

    // Legacy Tag with text
    propValue = obj['#'];
    if (propValue != null) {
      return Tag(obj['#'].toString());
    }

    // List value
    propValue = obj['list'];
    // List value
    if (propValue != null) {
      var listContent = Map<String, dynamic>.from(propValue);
      var rawList = InkList();
      propValue = obj['origins'];

      if (propValue != null) {
        var namesAsObjs = List<String>.from(propValue);
        rawList.setInitialOriginNames(namesAsObjs);
      }
      listContent.forEach((key, value) {
        var item = InkListItem.fullName(key);
        var val = value;
        rawList[item] = val;
      });
      return ListValue(rawList);
    }

    // Used when serialising save state only
    if (obj['originalChoicePath'] != null) {
      return JObjectToChoice(obj);
    }
  }

  // Array is always a Runtime.Container
  if (token is List<dynamic>) {
    return JArrayToContainer(token);
  }

  if (token == null) return null;

  throw Exception('Failed to convert token to runtime object: $token');
}