// x = a + b private Action WriteLValueExpression(ExpressionSyntaxNode expression, out IType?expressionResultType) { switch (expression) { case ArrayIndexExpression arrIdx: IType?arrayType = null; IType?lengthType = null; WriteExpression(arrIdx.Expression, true, false, ref arrayType); WriteExpression(arrIdx.LengthExpression, true, false, ref lengthType); typeChecker.TypeCheck(store.Types["System.Int32"], lengthType); if (arrayType == null) { throw new MissingTypeException("Array type must have been found"); } // Use the runtime provided Get() method to determine the inner type of the array var arrayRootType = arrayType.GetMethod("Get").ReturnType; // The expression needs the inner array type, then will call a Stelem expressionResultType = arrayRootType; return(() => generator.EmitStelem(arrayRootType)); case VariableSyntaxNode varNode: if (currentMethodInfo.Locals.TryGetValue(varNode.Name, out var localVar)) { expressionResultType = localVar.LocalType; return(() => generator.EmitStloc(localVar)); } else if (currentMethodInfo.Parameters.TryGetValue(varNode.Name, out var parameterVar)) { expressionResultType = parameterVar.type; return(() => generator.EmitStarg(parameterVar.idx)); } else if (currentMethodInfo.Fields.TryGetValue(varNode.Name, out var fieldVar)) { generator.EmitLdthis(); expressionResultType = fieldVar.FieldType; return(() => generator.EmitStfld(fieldVar)); } else { throw new MissingVariableDefinitionException("Not supported"); } case VariableAccessExpression varAccess: { IType?callTarget = null; WriteExpression(varAccess.Expression, true, false, ref callTarget); if (callTarget == null) { throw new MissingTypeException("No target for field access"); } IFieldInfo?fieldToCall = null; if (store.Fields.TryGetValue(callTarget, out var typeFieldList)) { foreach (var localField in typeFieldList) { if (localField.Name == varAccess.Name) { fieldToCall = localField; break; } } } if (fieldToCall == null) { throw new MissingTypeException("Field not found"); } expressionResultType = fieldToCall.FieldType; return(() => generator.EmitStfld(fieldToCall)); } default: throw new LValueOperationException("No other type of operations supported as lvalue"); } }