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; } }
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); }