示例#1
0
        public BuiltInPointerOperator(string name)
        {
            this.Name = name;
            switch (name)
            {
            case "==": ResultType = CheezType.Bool; break;

            case "!=": ResultType = CheezType.Bool; break;

            default: ResultType = PointerType.GetPointerType(CheezType.Void, true); break;
            }
        }
示例#2
0
        private AstExpression MatchPatternWithExpression(AstAssignment ass, AstExpression pattern, AstExpression value)
        {
            // check for operator set[]
            if (ass.Pattern is AstArrayAccessExpr arr)
            {
                // before we search for operators, make sure that all impls for both arguments have been matched
                GetImplsForType(arr.SubExpression.Type);
                GetImplsForType(arr.Arguments[0].Type);
                GetImplsForType(value.Type);

                var ops = ass.Scope.GetNaryOperators("set[]", arr.SubExpression.Type, arr.Arguments[0].Type, value.Type);
                if (ops.Count == 0)
                {
                    var type = arr.SubExpression.Type;
                    if (type is ReferenceType r)
                    {
                        type = r.TargetType;
                    }
                    else
                    {
                        type = ReferenceType.GetRefType(type, true);
                    }
                    ops = ass.Scope.GetNaryOperators("set[]", type, arr.Arguments[0].Type, value.Type);
                }

                if (ops.Count == 0)
                {
                    if (!pattern.TypeInferred)
                    {
                        pattern.SetFlag(ExprFlags.AssignmentTarget, false);
                        ass.Pattern = pattern = InferType(pattern, null);
                    }
                }
                else if (ops.Count == 1)
                {
                    arr.SubExpression = HandleReference(arr.SubExpression, ops[0].ArgTypes[0], null);
                    var args = new List <AstExpression>
                    {
                        arr.SubExpression,
                        arr.Arguments[0],
                        value
                    };
                    var opCall = new AstNaryOpExpr("set[]", args, value.Location);
                    opCall.ActualOperator = ops[0];
                    opCall.Replace(value);
                    ass.OnlyGenerateValue = true;
                    return(InferType(opCall, null));
                }
                else
                {
                    ReportError(ass, $"Multiple operators 'set[]' match the types ({arr.SubExpression.Type}, {arr.Arguments[0].Type}, {value.Type})");
                }
            }

            if (ass.Operator != null)
            {
                var assOp   = ass.Operator + "=";
                var valType = LiteralTypeToDefaultType(value.Type);

                // before we search for operators, make sure that all impls for both arguments have been matched
                GetImplsForType(pattern.Type);
                GetImplsForType(valType);

                var ops = ass.Scope.GetBinaryOperators(assOp, pattern.Type, valType);
                if (ops.Count == 0)
                {
                    var type = pattern.Type;
                    if (type is ReferenceType r)
                    {
                        type = r.TargetType;
                    }
                    else
                    {
                        type = ReferenceType.GetRefType(type, true);
                    }
                    ops = ass.Scope.GetBinaryOperators(assOp, type, valType);
                }

                if (ops.Count == 1)
                {
                    ass.OnlyGenerateValue = true;
                    pattern = HandleReference(pattern, ops[0].LhsType, null);
                    var opCall = new AstBinaryExpr(assOp, pattern, value, value.Location);
                    opCall.Replace(value);
                    return(InferType(opCall, null));
                }
                else if (ops.Count > 1)
                {
                    ReportError(ass, $"Multiple operators '{assOp}' match the types {PointerType.GetPointerType(pattern.Type, true)} and {value.Type}");
                }
            }

            switch (pattern)
            {
            case AstIdExpr id:
            {
                if (!id.GetFlag(ExprFlags.IsLValue))
                {
                    ReportError(pattern, $"Can't assign to '{id}' because it is not an lvalue");
                }

                if (ass.Operator != null)
                {
                    AstExpression newVal = new AstBinaryExpr(ass.Operator, pattern, value, value.Location);
                    newVal.Replace(value);
                    newVal = InferType(newVal, pattern.Type);

                    return(newVal);
                }

                ConvertLiteralTypeToDefaultType(ass.Value, pattern.Type);

                return(CheckType(ass.Value, ass.Pattern.Type, $"Can't assign a value of type {ass.Value.Type} to a pattern of type {ass.Pattern.Type}"));
            }

            case AstTupleExpr t:
            {
                if (value is AstTupleExpr v)
                {
                    if (t.Values.Count != v.Values.Count)
                    {
                        ReportError(ass, $"Can't assign the tuple '{v}' to the pattern '{t}' because the amount of values does not match");
                        return(value);
                    }

                    // create new assignments for all sub values
                    for (int i = 0; i < t.Values.Count; i++)
                    {
                        var subPat = t.Values[i];
                        var subVal = v.Values[i];
                        var subAss = new AstAssignment(subPat, subVal, ass.Operator, ass.Location);
                        subAss.Scope = ass.Scope;
                        subAss.Value = MatchPatternWithExpression(subAss, subPat, subVal);
                        ass.AddSubAssignment(subAss);
                    }
                }
                else
                {
                    var tmp = new AstTempVarExpr(value);
                    tmp.SetFlag(ExprFlags.IsLValue, true);

                    // create new assignments for all sub values
                    for (int i = 0; i < t.Values.Count; i++)
                    {
                        AstExpression subVal = new AstArrayAccessExpr(tmp, new AstNumberExpr(i));
                        subVal.Scope = ass.Scope;
                        subVal       = InferType(subVal, t.Values[i].Type);

                        var subAss = new AstAssignment(t.Values[i], subVal, ass.Operator, ass.Location);
                        subAss.Scope = ass.Scope;
                        subAss.Value = MatchPatternWithExpression(subAss, t.Values[i], subVal);
                        ass.AddSubAssignment(subAss);
                    }
                }
                break;
            }

            case AstDereferenceExpr de:
            {
                if (!pattern.GetFlag(ExprFlags.IsLValue))
                {
                    ReportError(pattern, $"Can't assign to '{pattern}' because it is not an lvalue");
                }

                if (ass.Operator != null)
                {
                    if (!de.SubExpression.GetFlag(ExprFlags.IsLValue))
                    {
                        AstExpression tmp = new AstTempVarExpr(de.SubExpression);
                        tmp.SetFlag(ExprFlags.IsLValue, true);
                        tmp = InferType(tmp, de.SubExpression.Type);

                        de.SubExpression = tmp;
                    }

                    AstExpression newVal = new AstBinaryExpr(ass.Operator, pattern, value, value.Location);
                    newVal.Replace(value);
                    newVal = InferType(newVal, pattern.Type);
                    return(newVal);
                }

                ConvertLiteralTypeToDefaultType(ass.Value, pattern.Type);


                return(CheckType(ass.Value, ass.Pattern.Type, $"Can't assign a value of type {value.Type} to a pattern of type {pattern.Type}"));
            }

            case AstDotExpr dot:
            {
                if (!pattern.GetFlag(ExprFlags.IsLValue))
                {
                    ReportError(pattern, $"Can't assign to '{pattern}' because it is not an lvalue");
                }

                if (ass.Operator != null)
                {
                    AstExpression tmp = new AstTempVarExpr(dot.Left, true);
                    tmp.SetFlag(ExprFlags.IsLValue, true);
                    //tmp = new AstDereferenceExpr(tmp, tmp.Location);
                    tmp = InferType(tmp, dot.Left.Type);

                    dot.Left = tmp;

                    AstExpression newVal = new AstBinaryExpr(ass.Operator, pattern, value, value.Location);
                    newVal.Replace(value);
                    newVal = InferType(newVal, pattern.Type);
                    return(newVal);
                }

                ConvertLiteralTypeToDefaultType(ass.Value, pattern.Type);


                return(CheckType(ass.Value, ass.Pattern.Type, $"Can't assign a value of type {value.Type} to a pattern of type {pattern.Type}"));
            }

            case AstArrayAccessExpr index:
            {
                if (!pattern.GetFlag(ExprFlags.IsLValue))
                {
                    ReportError(pattern, $"Can't assign to '{pattern}' because it is not an lvalue");
                }

                if (ass.Operator != null)
                {
                    AstExpression tmp = new AstTempVarExpr(index.SubExpression, true);
                    tmp.SetFlag(ExprFlags.IsLValue, true);
                    tmp = InferType(tmp, index.SubExpression.Type);

                    index.SubExpression = tmp;

                    AstExpression newVal = new AstBinaryExpr(ass.Operator, pattern, value, value.Location);
                    newVal.Replace(value);
                    newVal = InferType(newVal, pattern.Type);
                    return(newVal);
                }

                ConvertLiteralTypeToDefaultType(ass.Value, pattern.Type);


                return(CheckType(ass.Value, ass.Pattern.Type, $"Can't assign a value of type {value.Type} to a pattern of type {pattern.Type}"));
            }

            case AstExpression e when e.Type is ReferenceType r:
            {
                if (!pattern.GetFlag(ExprFlags.IsLValue))
                {
                    ReportError(pattern, $"Can't assign to '{pattern}' because it is not an lvalue");
                }

                // TODO: check if can be assigned to id (e.g. not const)
                if (ass.Operator != null)
                {
                    AstExpression newVal = new AstBinaryExpr(ass.Operator, pattern, value, value.Location);
                    newVal.Replace(value);
                    newVal = InferType(newVal, pattern.Type);
                    return(newVal);
                }

                ConvertLiteralTypeToDefaultType(ass.Value, pattern.Type);
                return(CheckType(ass.Value, r.TargetType, $"Can't assign a value of type {value.Type} to a pattern of type {pattern.Type}"));
            }

            default: ReportError(pattern, $"Can't assign to '{pattern.Type}', not an lvalue"); break;
            }

            return(value);
        }