Ejemplo n.º 1
0
        // 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");
            }
        }