示例#1
0
        private PrimitiveType BindFunctionExpr(IVariableTypeProvider VariableTypeProvider, Dictionary <Expr, PrimitiveType> TypeDict, FunctionExpr fe)
        {
            foreach (var p in fe.Parameters)
            {
                BindExpr(VariableTypeProvider, TypeDict, p);
            }
            var ParameterTypes = fe.Parameters.Select(p => TypeDict[p]).ToList();
            List <FunctionParameterAndReturnTypes> Functions;

            try
            {
                Functions = VariableTypeProvider.GetOverloads(fe.Name);
            }
            catch (Exception ex)
            {
                throw new InvalidSyntaxException("'{0}' : FunctionNotExist".Formats(fe.Name), new FileTextRange {
                    Text = Text, Range = Positions[fe]
                }, ex);
            }
            var Sorted = Functions.Where(fs => IsOverloadSatisfied(ParameterTypes, fs.ParameterTypes)).GroupBy(fs => GetOverloadTypeConversionPoint(ParameterTypes, fs.ParameterTypes)).OrderBy(g => g.Key).ToList();

            if (Sorted.Count == 0)
            {
                throw new InvalidSyntaxException("'{0}' : FunctionNotExist".Formats(fe.Name), new FileTextRange {
                    Text = Text, Range = Positions[fe]
                });
            }
            var MostMatchedGroup = Sorted.First().ToList();

            if (MostMatchedGroup.Count > 1)
            {
                throw new InvalidSyntaxException("'{0}' : MultipleFunctionOverloadExist".Formats(fe.Name), new FileTextRange {
                    Text = Text, Range = Positions[fe]
                });
            }
            var MostMatchedSignature = MostMatchedGroup.Single();

            for (int k = 0; k < ParameterTypes.Count; k += 1)
            {
                var pt   = ParameterTypes[k];
                var fspt = MostMatchedSignature.ParameterTypes[k];
                if (pt == PrimitiveType.Int && fspt == PrimitiveType.Real)
                {
                    var feCReal = new FunctionExpr {
                        Name = "creal", Parameters = new List <Expr> {
                            fe.Parameters[k]
                        }
                    };
                    var CReal = Expr.CreateFunction(feCReal);
                    var Range = Positions[fe.Parameters[k]];
                    Positions.Add(feCReal, Range);
                    Positions.Add(CReal, Range);
                    TypeDict.Add(CReal, PrimitiveType.Real);
                    fe.Parameters[k] = CReal;
                }
            }
            return(MostMatchedSignature.ReturnType);
        }
示例#2
0
        private void BindExpr(IVariableTypeProvider VariableTypeProvider, Dictionary <Expr, PrimitiveType> TypeDict, Expr e)
        {
            if (e.OnLiteral)
            {
                var l = e.Literal;
                if (l.OnBooleanValue)
                {
                    TypeDict.Add(e, PrimitiveType.Boolean);
                }
                else if (l.OnIntValue)
                {
                    TypeDict.Add(e, PrimitiveType.Int);
                }
                else if (l.OnRealValue)
                {
                    TypeDict.Add(e, PrimitiveType.Real);
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
            else if (e.OnVariable)
            {
                List <FunctionParameterAndReturnTypes> t;
                try
                {
                    t = VariableTypeProvider.GetOverloads(e.Variable.Name).Where(fs => fs.ParameterTypes == null).ToList();
                }
                catch (Exception ex)
                {
                    throw new InvalidSyntaxException(String.Format("'{0}' : VariableNotExist", e.Variable.Name), new FileTextRange {
                        Text = Text, Range = Positions[e]
                    }, ex);
                }
                if (t.Count == 0)
                {
                    throw new InvalidSyntaxException("'{0}' : VariableNotExist".Formats(e.Variable.Name), new FileTextRange {
                        Text = Text, Range = Positions[e]
                    });
                }
                if (t.Count > 1)
                {
                    throw new InvalidSyntaxException("'{0}' : VariableFunctionOverloadExist".Formats(e.Variable.Name), new FileTextRange {
                        Text = Text, Range = Positions[e]
                    });
                }
                TypeDict.Add(e, t.Single().ReturnType);
            }
            else if (e.OnFunction)
            {
                var t = BindFunctionExpr(VariableTypeProvider, TypeDict, e.Function);
                TypeDict.Add(e, t);
            }
            else if (e.OnIf)
            {
                var Condition = e.If.Condition;
                var TruePart  = e.If.TruePart;
                var FalsePart = e.If.FalsePart;

                BindExpr(VariableTypeProvider, TypeDict, Condition);
                var ConditionType = TypeDict[Condition];
                if (ConditionType != PrimitiveType.Boolean)
                {
                    throw new InvalidSyntaxException("TypeMismatch : 'Boolean' expected.", new FileTextRange {
                        Text = Text, Range = Positions[Condition]
                    });
                }
                BindExpr(VariableTypeProvider, TypeDict, TruePart);
                var TruePartType = TypeDict[TruePart];
                BindExpr(VariableTypeProvider, TypeDict, FalsePart);
                var           FalsePartType = TypeDict[FalsePart];
                PrimitiveType ReturnType;
                if (TruePartType == PrimitiveType.Int && FalsePartType == PrimitiveType.Real)
                {
                    var fe = new FunctionExpr {
                        Name = "creal", Parameters = new List <Expr> {
                            TruePart
                        }
                    };
                    var CReal = Expr.CreateFunction(fe);
                    var Range = Positions[TruePart];
                    Positions.Add(fe, Range);
                    Positions.Add(CReal, Range);
                    TypeDict.Add(CReal, PrimitiveType.Real);
                    e.If.TruePart = CReal;
                    ReturnType    = PrimitiveType.Real;
                }
                else if (TruePartType == PrimitiveType.Real && FalsePartType == PrimitiveType.Int)
                {
                    var fe = new FunctionExpr {
                        Name = "creal", Parameters = new List <Expr> {
                            FalsePart
                        }
                    };
                    var CReal = Expr.CreateFunction(fe);
                    var Range = Positions[FalsePart];
                    Positions.Add(fe, Range);
                    Positions.Add(CReal, Range);
                    TypeDict.Add(CReal, PrimitiveType.Real);
                    e.If.FalsePart = CReal;
                    ReturnType     = PrimitiveType.Real;
                }
                else if (TruePartType != FalsePartType)
                {
                    throw new InvalidSyntaxException("TypeMismatch: true_part is '{0}' and false_part is '{1}'.".Formats(GetTypeString(TruePartType), GetTypeString(FalsePartType)), new FileTextRange {
                        Text = Text, Range = Positions[e]
                    });
                }
                else
                {
                    ReturnType = TruePartType;
                }
                TypeDict.Add(e, ReturnType);
            }
            else if (e.OnAndAlso)
            {
                var Left  = e.AndAlso.Left;
                var Right = e.AndAlso.Right;
                BindExpr(VariableTypeProvider, TypeDict, Left);
                var LeftType = TypeDict[Left];
                if (LeftType != PrimitiveType.Boolean)
                {
                    throw new InvalidSyntaxException("TypeMismatch : 'Boolean' expected.", new FileTextRange {
                        Text = Text, Range = Positions[Left]
                    });
                }
                BindExpr(VariableTypeProvider, TypeDict, Right);
                var RightType = TypeDict[Right];
                if (RightType != PrimitiveType.Boolean)
                {
                    throw new InvalidSyntaxException("TypeMismatch : 'Boolean' expected.", new FileTextRange {
                        Text = Text, Range = Positions[Right]
                    });
                }
                TypeDict.Add(e, PrimitiveType.Boolean);
            }
            else if (e.OnOrElse)
            {
                var Left  = e.OrElse.Left;
                var Right = e.OrElse.Right;
                BindExpr(VariableTypeProvider, TypeDict, Left);
                var LeftType = TypeDict[Left];
                if (LeftType != PrimitiveType.Boolean)
                {
                    throw new InvalidSyntaxException("TypeMismatch : 'Boolean' expected.", new FileTextRange {
                        Text = Text, Range = Positions[Left]
                    });
                }
                BindExpr(VariableTypeProvider, TypeDict, Right);
                var RightType = TypeDict[Right];
                if (RightType != PrimitiveType.Boolean)
                {
                    throw new InvalidSyntaxException("TypeMismatch : 'Boolean' expected.", new FileTextRange {
                        Text = Text, Range = Positions[Right]
                    });
                }
                TypeDict.Add(e, PrimitiveType.Boolean);
            }
            else
            {
                throw new InvalidOperationException();
            }
        }