public string GetTypeNameForTypeAccessExpression(GrapeCodeGeneratorConfiguration config, GrapeExpression expression)
 {
     string dummyMessage = "";
     return GetTypeNameForTypeAccessExpression(config, expression, ref dummyMessage);
 }
		public GrapeBinaryOrExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
        public bool ValidateExpression(GrapeCodeGeneratorConfiguration config, GrapeExpression expression)
        {
            if (expression != null) {
                GrapeAst ast = config.Ast;
                string errorMessage = "";
                if (GrapeAstVisitor.IsTypeInTypeArray(expression.GetType(), accessExpressionValidator.NodeType)) {
                    return accessExpressionValidator.ValidateNode(expression);
                } else if (expression.GetType() == typeof(GrapeAddExpression)) {
                    GrapeAddExpression addExpression = expression as GrapeAddExpression;
                    if (!(typeCheckingUtils.DoesExpressionResolveToType(config, expression, addExpression.Left, "int_base") && typeCheckingUtils.DoesExpressionResolveToType(config, expression, addExpression.Right, "int_base", ref errorMessage)) || !(typeCheckingUtils.DoesExpressionResolveToType(config, expression, addExpression.Left, "fixed_base", ref errorMessage) && typeCheckingUtils.DoesExpressionResolveToType(config, expression, addExpression.Right, "fixed_base", ref errorMessage)) || !(typeCheckingUtils.DoesExpressionResolveToType(config, expression, addExpression.Left, "string_base", ref errorMessage) && typeCheckingUtils.DoesExpressionResolveToType(config, expression, addExpression.Right, "string_base", ref errorMessage))) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve addition expressions to the same type or addition expressions resolve to a type that is unable to be merged. " + errorMessage, FileName = expression.FileName, Entity = addExpression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }
                } else if (expression.GetType() == typeof(GrapeConditionalExpression)) {
                    GrapeConditionalExpression conditionalExpression = expression as GrapeConditionalExpression;
                    if (conditionalExpression.Type == GrapeConditionalExpression.GrapeConditionalExpressionType.BinaryAnd || conditionalExpression.Type == GrapeConditionalExpression.GrapeConditionalExpressionType.BinaryOr) {
                        if (!typeCheckingUtils.DoesExpressionResolveToType(config, expression, conditionalExpression.Left, "int_base", ref errorMessage) || !typeCheckingUtils.DoesExpressionResolveToType(config, expression, conditionalExpression.Right, "int_base", ref errorMessage)) {
                            errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve expression to the type 'int_base'. " + errorMessage, FileName = expression.FileName, Entity = conditionalExpression });
                            if (!config.ContinueOnError) {
                                return false;
                            }
                        }
                    } else {
                        if (!typeCheckingUtils.DoesExpressionResolveToType(config, expression, conditionalExpression.Left, "bool_base", ref errorMessage) || !typeCheckingUtils.DoesExpressionResolveToType(config, expression, conditionalExpression.Right, "bool_base", ref errorMessage)) {
                            errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve expression to the type 'bool_base'. " + errorMessage, FileName = expression.FileName, Entity = conditionalExpression });
                            if (!config.ContinueOnError) {
                                return false;
                            }
                        }
                    }
                } else if (expression.GetType() == typeof(GrapeMultiplicationExpression)) {
                    GrapeMultiplicationExpression multiplicationExpression = expression as GrapeMultiplicationExpression;
                    if (!(typeCheckingUtils.DoesExpressionResolveToType(config, expression, multiplicationExpression.Left, "int_base", ref errorMessage) && typeCheckingUtils.DoesExpressionResolveToType(config, expression, multiplicationExpression.Right, "int_base", ref errorMessage)) || !(typeCheckingUtils.DoesExpressionResolveToType(config, expression, multiplicationExpression.Left, "fixed_base", ref errorMessage) && typeCheckingUtils.DoesExpressionResolveToType(config, expression, multiplicationExpression.Right, "fixed_base", ref errorMessage))) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve addition expressions to the same type or addition expressions resolve to a type that is unable to be merged. " + errorMessage, FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }
                } else if (expression.GetType() == typeof(GrapeNameofExpression)) {
                    GrapeNameofExpression nameofExpression = expression as GrapeNameofExpression;
                    if (nameofExpression.Value.GetType() != typeof(GrapeMemberExpression)) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve expression to type, field or function.", FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }

                    string qualifiedId = nameofExpression.Value.ToString();
                    GrapeEntity valueEntity = (new List<GrapeEntity>(typeCheckingUtils.GetEntitiesForAccessExpression(config, nameofExpression.Value, expression, out errorMessage, false)))[0];
                    if (valueEntity == null) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot find entity for expression '" + qualifiedId + "'. " + errorMessage, FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }

                    GrapeClass c = expression.GetLogicalParentOfEntityType<GrapeClass>();
                    GrapeModifier.GrapeModifierType modifiers = c.GetAppropriateModifiersForEntityAccess(config, valueEntity);
                    GrapeModifier.GrapeModifierType potentialModifiers = valueEntity.GetPotentialModifiersOfEntity();
                    bool invalidModifiers = false;
                    if (modifiers != 0) {
                        if (potentialModifiers == 0) {
                            if (modifiers == GrapeModifier.GrapeModifierType.Public) {
                                invalidModifiers = false;
                            } else {
                                invalidModifiers = true;
                            }
                        } else {
                            if (modifiers != potentialModifiers) {
                                invalidModifiers = true;
                            }
                        }
                    } else {
                        invalidModifiers = true;
                    }

                    if (invalidModifiers) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot access member '" + qualifiedId + "'.", FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }
                } else if (expression.GetType() == typeof(GrapeShiftExpression)) {
                    GrapeShiftExpression shiftExpression = expression as GrapeShiftExpression;
                    if (!(typeCheckingUtils.DoesExpressionResolveToType(config, expression, shiftExpression.Left, "int_base", ref errorMessage) && typeCheckingUtils.DoesExpressionResolveToType(config, expression, shiftExpression.Right, "int_base", ref errorMessage))) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve shift expressions to the same type or addition expressions resolve to a type that is unable to be merged. " + errorMessage, FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }
                } else if (expression.GetType() == typeof(GrapeTypecastExpression)) {
                    GrapeTypecastExpression typecastExpression = expression as GrapeTypecastExpression;
                    if (typeCheckingUtils.DoesExpressionResolveToType(config, typecastExpression, typecastExpression.Value, "text_base")) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot cast from type 'text_base'.", FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }

                    return typeCheckingUtils.DoesExpressionResolveToType(config, expression, typecastExpression.Value, typecastExpression.TypeName);
                } else if (expression.GetType() == typeof(GrapeUnaryExpression)) {
                    GrapeUnaryExpression unaryExpression = expression as GrapeUnaryExpression;
                    if (unaryExpression.Type == GrapeUnaryExpression.GrapeUnaryExpressionType.Not) {
                        if (!typeCheckingUtils.DoesExpressionResolveToType(config, expression, unaryExpression.Value, "bool_base", ref errorMessage)) {
                            errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve expression to the type 'bool_base'. " + errorMessage, FileName = expression.FileName, Entity = expression });
                            if (!config.ContinueOnError) {
                                return false;
                            }
                        }
                    } else if (!(typeCheckingUtils.DoesExpressionResolveToType(config, expression, unaryExpression.Value, "int_base", ref errorMessage))) {
                        errorSink.AddError(new GrapeErrorSink.Error { Description = "Cannot resolve expression to the type 'int_base'. " + errorMessage, FileName = expression.FileName, Entity = expression });
                        if (!config.ContinueOnError) {
                            return false;
                        }
                    }
                }
            }

            return true;
        }
		public GrapeNotEqualExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		public GrapeSwitchStatement(GrapeExpression expression, GrapeList<GrapeSwitchCase> cases): base() {
			this.expression = expression;
			this.cases = cases.ToList(this).AsReadOnly();
		}
		public GrapeCurlyEqualUnaryExpression(GrapeExpression value): base(value) {}
		public GrapeMultiplicationExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		public GrapeSubExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
 public GrapeSetExpression(GrapeAccessExpression memberAccess, GrapeExpression value)
 {
     this.memberAccess = memberAccess;
     this.value = value;
 }
 public GrapeValueInitializer(GrapeExpression value)
 {
     this.value = value;
 }
		public GrapeModuloExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
        public bool DoesExpressionResolveToType(GrapeCodeGeneratorConfiguration config, GrapeEntity parent, GrapeExpression expression, string typeName, ref string errorMessage)
        {
            if (parent == null) {
                throw new ArgumentNullException("parent");
            }

            if (expression is GrapeLiteralExpression) {
                if (typeName == literalTypes[((GrapeLiteralExpression)expression).Type]) {
                    return true;
                } else {
                    GrapeClass c = astUtils.GetClassWithNameFromImportedPackagesInFile(config.Ast, typeName, expression.FileName);
                    if (c != null && c.IsClassInInheritanceTree(config, astUtils.GetClassWithNameFromImportedPackagesInFile(config.Ast, literalTypes[((GrapeLiteralExpression)expression).Type], expression.FileName))) {
                        return true;
                    }
                }

                return false;
            } else if (expression is GrapeConditionalExpression) {
                GrapeConditionalExpression conditionalExpression = expression as GrapeConditionalExpression;
                if (conditionalExpression.Type == GrapeConditionalExpression.GrapeConditionalExpressionType.BinaryAnd || conditionalExpression.Type == GrapeConditionalExpression.GrapeConditionalExpressionType.BinaryOr) {
                    return DoesExpressionResolveToType(config, parent, conditionalExpression.Left, "int_base", ref errorMessage) && DoesExpressionResolveToType(config, parent, conditionalExpression.Right, "int_base", ref errorMessage);
                }

                string leftType = GetTypeNameForTypeAccessExpression(config, conditionalExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, conditionalExpression.Right, ref errorMessage);
                if (errorMessage != "") {
                    return false;
                }

                bool result = leftType == rightType;
                if (!result) {
                    GrapeClass left = astUtils.GetClassWithNameFromImportedPackagesInFile(config.Ast, leftType, parent.FileName);
                    GrapeClass right = astUtils.GetClassWithNameFromImportedPackagesInFile(config.Ast, rightType, parent.FileName);
                    if (left != null && right != null) {
                        if (left.IsClassInInheritanceTree(config, right)) {
                            return true;
                        }
                    }
                }

                if (!result) {
                    errorMessage = "Cannot resolve left and right expressions to the same type. The resolved left type is '" + leftType + "' and the resolved right type is '" + rightType + "'.";
                }

                return result;
            } else if (expression is GrapeMemberExpression) {
                GrapeEntity entity = (new List<GrapeEntity>(GetEntitiesForAccessExpression(config, expression as GrapeMemberExpression, parent, out errorMessage)))[0];
                if (entity != null) {
                    GrapeClass type = null;
                    if (entity is GrapeVariable) {
                        type = astUtils.GetClassWithNameFromImportedPackagesInFile(config.Ast, GetCorrectNativeTypeName(GetTypeNameForTypeAccessExpression(config, ((GrapeVariable)entity).Type, ref errorMessage)), parent.FileName);
                    } else if (entity is GrapeMethod) {
                        type = astUtils.GetClassWithNameFromImportedPackagesInFile(config.Ast, GetCorrectNativeTypeName(GetTypeNameForTypeAccessExpression(config, ((GrapeMethod)entity).ReturnType, ref errorMessage)), parent.FileName);
                    } else if (entity is GrapeClass) {
                        type = entity as GrapeClass;
                    }

                    if (type != null) {
                        return type.Name == GetCorrectNativeTypeName(typeName) || IsTypeInClassInheritanceTree(config, typeName, type);
                    }
                } else {
                    if (expression.GetType() == typeof(GrapeMemberExpression)) {
                        string qualifiedId = ((GrapeMemberExpression)expression).GetAccessExpressionQualifiedId();
                        foreach (GalaxyConstantAttribute constant in GalaxyNativeInterfaceAggregator.Constants) {
                            if (constant.Name == qualifiedId) {
                                return GetCorrectNativeTypeName(constant.Type) == GetCorrectNativeTypeName(typeName);
                            }
                        }
                    } else if (expression.GetType() == typeof(GrapeCallExpression)) {
                        GrapeCallExpression callExpression = expression as GrapeCallExpression;
                        GrapeAccessExpression accessExpression = callExpression.GetAccessExpressionInAccessExpression();
                        string qualifiedId = accessExpression.GetAccessExpressionQualifiedId();
                        foreach (GalaxyFunctionAttribute function in GalaxyNativeInterfaceAggregator.Functions) {
                            if (function.Name == qualifiedId) {
                                if (!IsSignatureValid(config, function, callExpression, out errorMessage)) {
                                    return false;
                                }

                                return GetCorrectNativeTypeName(function.Type) == GetCorrectNativeTypeName(typeName);
                            }
                        }
                    }
                }
            } else if (expression is GrapeNameofExpression) {
                GrapeNameofExpression nameofExpression = expression as GrapeNameofExpression;
                if (nameofExpression.Value.GetType() != typeof(GrapeMemberExpression)) {
                    errorMessage = "Cannot resolve expression to type, field or method.";
                    if (!config.ContinueOnError) {
                        return false;
                    }
                }

                string qualifiedId = nameofExpression.Value.ToString();
                GrapeEntity valueEntity = (new List<GrapeEntity>(GetEntitiesForAccessExpression(config, nameofExpression.Value, expression, out errorMessage, false)))[0];
                if (valueEntity == null) {
                    errorMessage = "Cannot find entity for expression '" + qualifiedId + "'. " + errorMessage;
                    if (!config.ContinueOnError) {
                        return false;
                    }
                }

                GrapeClass c = expression.GetLogicalParentOfEntityType<GrapeClass>();
                GrapeModifier.GrapeModifierType modifiers = c.GetAppropriateModifiersForEntityAccess(config, valueEntity);
                GrapeModifier.GrapeModifierType potentialModifiers = valueEntity.GetPotentialModifiersOfEntity();
                bool invalidModifiers = false;
                if (modifiers != 0) {
                    if (potentialModifiers == 0) {
                        if (modifiers == GrapeModifier.GrapeModifierType.Public) {
                            invalidModifiers = false;
                        } else {
                            invalidModifiers = true;
                        }
                    } else {
                        if (modifiers != potentialModifiers) {
                            invalidModifiers = true;
                        }
                    }
                } else {
                    invalidModifiers = true;
                }

                if (invalidModifiers) {
                    errorMessage = "Cannot access member '" + qualifiedId + "'.";
                    if (!config.ContinueOnError) {
                        return false;
                    }
                }

                return typeName == "string_base";
            } else if (expression is GrapeAddExpression) {
                GrapeAddExpression addExpression = expression as GrapeAddExpression;
                string leftType = GetTypeNameForTypeAccessExpression(config, addExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, addExpression.Right, ref errorMessage);
                if (errorMessage != "") {
                    return false;
                }

                return leftType == rightType;
            } else if (expression is GrapeMultiplicationExpression) {
                GrapeMultiplicationExpression multiplicationExpression = expression as GrapeMultiplicationExpression;
                string leftType = GetTypeNameForTypeAccessExpression(config, multiplicationExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, multiplicationExpression.Right, ref errorMessage);
                if (errorMessage != "") {
                    return false;
                }

                return leftType == rightType;
            } else if (expression is GrapeShiftExpression) {
                GrapeShiftExpression shiftExpression = expression as GrapeShiftExpression;
                string leftType = GetTypeNameForTypeAccessExpression(config, shiftExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, shiftExpression.Right, ref errorMessage);
                if (errorMessage != "") {
                    return false;
                }

                return leftType == rightType;
            } else if (expression is GrapeTypecastExpression) {
                GrapeTypecastExpression typecastExpression = expression as GrapeTypecastExpression;
                if (DoesExpressionResolveToType(config, typecastExpression, typecastExpression.Value, "text_base")) {
                    errorMessage = "Cannot cast from type 'text_base'.";
                    return false;
                }

                return DoesExpressionResolveToType(config, parent, typecastExpression.TypeName, typeName, ref errorMessage);
            } else if (expression is GrapeUnaryExpression) {
                GrapeUnaryExpression unaryExpression = expression as GrapeUnaryExpression;
                return DoesExpressionResolveToType(config, parent, unaryExpression.Value, typeName, ref errorMessage);
            }

            return false;
        }
 public bool DoesExpressionResolveToType(GrapeCodeGeneratorConfiguration config, GrapeEntity parent, GrapeExpression expression, string typeName)
 {
     string dummyMessage = "";
     return DoesExpressionResolveToType(config, parent, expression, typeName, ref dummyMessage);
 }
        public string GetTypeNameForTypeAccessExpression(GrapeCodeGeneratorConfiguration config, GrapeExpression expression, ref string errorMessage)
        {
            if (expression is GrapeMemberExpression) {
                GrapeEntity entity = (new List<GrapeEntity>(GetEntitiesForAccessExpression(config, ((GrapeMemberExpression)expression), expression, out errorMessage)))[0];
                if (entity is GrapeVariable) {
                    return GetCorrectNativeTypeName(((GrapeVariable)entity).Type.ToString());
                } else if (entity is GrapeMethod) {
                    return GetCorrectNativeTypeName(((GrapeMethod)entity).ReturnType.ToString());
                } else if (entity is GrapeClass) {
                    return GetCorrectNativeTypeName((entity as GrapeClass).Name);
                } else if (entity == null) {
                    string qualifiedId = ((GrapeMemberExpression)expression).GetAccessExpressionQualifiedId();
                    foreach (GalaxyFunctionAttribute function in GalaxyNativeInterfaceAggregator.Functions) {
                        if (function.Name == qualifiedId) {
                            errorMessage = "";
                            return GetCorrectNativeTypeName(function.Type);
                        }
                    }

                    foreach (GalaxyConstantAttribute constant in GalaxyNativeInterfaceAggregator.Constants) {
                        if (constant.Name == qualifiedId) {
                            errorMessage = "";
                            return GetCorrectNativeTypeName(constant.Type);
                        }
                    }

                    foreach (Tuple<GalaxyTypeAttribute, GalaxyTypeDefaultValueAttribute> type in GalaxyNativeInterfaceAggregator.Types) {
                        if (type.Item1.NativeAlias == qualifiedId || type.Item1.TypeName == qualifiedId) {
                            errorMessage = "";
                            return GetCorrectNativeTypeName(type.Item1.NativeAlias);
                        }
                    }
                }

                return "";// GetCorrectNativeTypeName(((GrapeMemberExpression)expression).GetMemberExpressionQualifiedId());
            } else if (expression is GrapeLiteralExpression) {
                return literalTypes[((GrapeLiteralExpression)expression).Type];
            } else if (expression is GrapeAddExpression) {
                GrapeAddExpression addExpression = expression as GrapeAddExpression;
                string leftType = GetTypeNameForTypeAccessExpression(config, addExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, addExpression.Right, ref errorMessage);
                if (leftType != rightType) {
                    errorMessage = "The left and right expressions do not resolve to the same type.";
                }

                return leftType;
            } else if (expression is GrapeMultiplicationExpression) {
                GrapeMultiplicationExpression multiplicationExpression = expression as GrapeMultiplicationExpression;
                string leftType = GetTypeNameForTypeAccessExpression(config, multiplicationExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, multiplicationExpression.Right, ref errorMessage);
                if (leftType != rightType) {
                    errorMessage = "The left and right expressions do not resolve to the same type.";
                }

                return leftType;
            } else if (expression is GrapeShiftExpression) {
                GrapeShiftExpression shiftExpression = expression as GrapeShiftExpression;
                string leftType = GetTypeNameForTypeAccessExpression(config, shiftExpression.Left, ref errorMessage);
                string rightType = GetTypeNameForTypeAccessExpression(config, shiftExpression.Right, ref errorMessage);
                if (leftType != rightType) {
                    errorMessage = "The left and right expressions do not resolve to the same type.";
                }

                return leftType;
            } else if (expression is GrapeUnaryExpression) {
                GrapeUnaryExpression unaryExpression = expression as GrapeUnaryExpression;
                return GetTypeNameForTypeAccessExpression(config, unaryExpression.Value, ref errorMessage);
            }

            return "";
        }
		public GrapeConditionalStatement(GrapeExpression condition, GrapeList<GrapeStatement> statements, GrapeConditionalStatement elseStatement): base(statements) {
			this.condition = condition;
			this.elseStatement = (elseStatement != null) && (elseStatement.Statements.Count > 0) ? elseStatement : null;
		}
		public GrapeAddExpression(GrapeExpression left, GrapeExpression right) {
			this.left = left;
			this.right = right;
		}
		public GrapeGreaterThanOrEqualExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		protected GrapeBinaryExpression(GrapeExpression left, GrapeExpression right) {
			this.left = left;
			this.right = right;
		}
 public GrapeDivisionExpression(GrapeExpression left, GrapeExpression right)
     : base(left, right)
 {
 }
		public GrapeExpressionStatement(GrapeExpression expression) {
			this.expression = expression;
		}
		protected GrapeShiftExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		public GrapeLessThanExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		public GrapeLogicalOrExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		public GrapeNegateUnaryExpression(GrapeExpression value): base(value) {}
		public GrapeDeleteStatement(GrapeExpression value) {
			this.value = value;
		}
		public GrapeTypecastExpression(GrapeExpression value, GrapeType typeName) {
			this.value = value;
			this.typeName = typeName;
		}
		public GrapeShiftLeftExpression(GrapeExpression left, GrapeExpression right): base(left, right) {}
		protected GrapeUnaryExpression(GrapeExpression value) {
			this.value = value;
		}
		public GrapeWhileStatement(GrapeExpression condition, GrapeList<GrapeStatement> statements): base(statements) {
			this.condition = condition;
		}
 public bool DoesExpressionResolveToType(GrapeCodeGeneratorConfiguration config, GrapeEntity parent, GrapeExpression expression, GrapeType type, ref string errorMessage)
 {
     // left for compat
     return DoesExpressionResolveToType(config, parent, expression, type.ToString(), ref errorMessage);
 }