fxAssignment function

dynamic fxAssignment(
  1. String expression,
  2. Map envValues, {
  3. void leftEnvs(
    1. List<String>
    )?,
})

Run assignment expression and return the right side value.

expression: Assignment expression,eg: $a.b$=1+2+3. envValues: Environment values set. If the expression contains a variable $a.b$. Then you should give a values set like {"a": {"b": something}}. leftEnvs: Used for jsfxAssignment in jsfx.dart.

Implementation

dynamic fxAssignment(String expression, Map envValues,
    {void Function(List<String>)? leftEnvs}) {
  if (expression.isEmpty) {
    return null;
  }
  var program = _parseProgram(content: expression);

  var visitor = AstRuntimeVisitor();
  var ast = program.accept(visitor);

  var executor = DefaultAstRuntimeExecutor(onGetEnvValue: (envVar) {
    if (envVar.startsWith('\$') && envVar.endsWith('\$')) {
      var varStr = envVar.substring(1, envVar.length - 1);
      return _parseEnvValue(varStr, envValues);
    } else {
      warn(tag: _tag, message: "Unkown environment variable: $envVar");
      return null;
    }
  });
  var runtimeNode = runtime.Program.fromAst(ast)!.body!;
  if (runtimeNode is! runtime.AssignmentExpression ||
      (runtimeNode.operator != '=' &&
          runtimeNode.operator != '+=' &&
          runtimeNode.operator != '-=' &&
          runtimeNode.operator != '*=' &&
          runtimeNode.operator != '/=' &&
          runtimeNode.operator != '~/=' &&
          runtimeNode.operator != '%=' &&
          runtimeNode.operator != '&=' &&
          runtimeNode.operator != '|=' &&
          runtimeNode.operator != '^=' &&
          runtimeNode.operator != '>>=' &&
          runtimeNode.operator != '<<=')) {
    error(tag: _tag, message: 'Unsupport assignment expression: $expression');
    return null;
  }
  if (runtimeNode.left is! runtime.StringLiteral ||
      !executor
          .isEnvString((runtimeNode.left as runtime.StringLiteral).value)) {
    warn(tag: _tag, message: 'Assignment left is not env variable');
    return null;
  }
  var astContext = AstContext();
  dynamic rightValue = executor.execute(astContext, runtimeNode.right);

  var leftEnvVar = (runtimeNode.left as runtime.StringLiteral).value as String;
  if (leftEnvVar.startsWith('\$') && leftEnvVar.endsWith('\$')) {
    leftEnvVar = leftEnvVar.substring(1, leftEnvVar.length - 1);
  } else {
    warn(tag: _tag, message: 'Assignment left is not env variable');
    return null;
  }
  var leftValue = _parseEnvValue(leftEnvVar, envValues);
  var fields = leftEnvVar.split(".");
  leftEnvs?.call(fields);
  dynamic value = envValues;
  for (var i = 0; i < fields.length - 1; i++) {
    value = value[fields[i]];
  }
  if (rightValue != null) {
    if (leftValue != null) {
      switch (runtimeNode.operator) {
        case '+=':
          rightValue = leftValue + rightValue;
          break;
        case '-=':
          rightValue = leftValue - rightValue;
          break;
        case '*=':
          rightValue = leftValue * rightValue;
          break;
        case '%=':
          rightValue = leftValue % rightValue;
          break;
        case '&=':
          rightValue = leftValue & rightValue;
          break;
        case '|=':
          rightValue = leftValue | rightValue;
          break;
        case '^=':
          rightValue = leftValue ^ rightValue;
          break;
        case '>>=':
          rightValue = leftValue >> rightValue;
          break;
        case '<<=':
          rightValue = leftValue << rightValue;
          break;
      }
    } else {
      warn(tag: _tag, message: 'Assignment right side is null');
    }

    value[fields.last] = rightValue;
  } else {
    warn(tag: _tag, message: 'Assignment right side is null');
  }

  return rightValue;
}