public override void CheckTypes(ErrorHandler errorHandler) { if (!Length.CanConvertTo(PrimTypeName.INT, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use type {Length.GetExprType(errorHandler)} as array indexer", Token); } if (!DefaultValue.CanConvertTo(Type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use type {DefaultValue.GetExprType(errorHandler)} to initialize an array of {Type}", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { if (Op == UnaryOp.MIN && !Expr.CanConvertTo(PrimTypeName.FLOAT, errorHandler) && !Expr.CanConvertTo(PrimTypeName.INT, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use pre-operator '-' with type {Expr.GetExprType(errorHandler)}", Token); } if (Op == UnaryOp.NEG && !Expr.CanConvertTo(PrimTypeName.BOOL, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use pre-operator '!' with type {Expr.GetExprType(errorHandler)}", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { if (TargetNode != null) { return; } var viableCandidates = new List <FnDecl>(); var args = Args.ToList(); foreach (var decl in TargetNodeCandidates) { var parameters = decl.Parameters.ToList(); if (parameters.Count != args.Count) { continue; } bool success = false; for (int i = 0; i < parameters.Count; i++) { if (!args[i].CanConvertTo(parameters[i].Type, errorHandler)) { break; } success = true; } if (!success) { continue; } viableCandidates.Add(decl); } if (viableCandidates.Count == 0) { errorHandler.AddMessage(Severity.Error, $"No overload of function {Token.Value} with matching parameters found", Token); } else if (viableCandidates.Count > 1) { errorHandler.AddMessage(Severity.Error, $"Multiple overloads of function {Token.Value} with the same parameter types found", Token); } else { TargetNode = viableCandidates[0]; } }
public override bool CanConvertTo(Type type, ErrorHandler errorHandler) { bool success = true; Type elType; if (type is ArrayType arrayType) { elType = arrayType.Type; } else { return(false); } foreach (var expr in Data) { if (!expr.CanConvertTo(elType, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use expression of type {expr.GetExprType(errorHandler)} in array of {elType}", Token); success = false; } } return(success); }
public override void CheckTypes(ErrorHandler errorHandler) { if (!(Right.TargetNode is DeclStmt)) { errorHandler.AddMessage(Severity.Error, $"Cannot find member {Right.Token.Value} in struct {Left.GetExprType(errorHandler)}", Right.Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { Body.CheckTypes(errorHandler); if (!Condition.CanConvertTo(PrimTypeName.BOOL, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"For loop condition is not a boolean", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { Value.CheckTypes(errorHandler); if (!Value.CanConvertTo(Type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Incorrect initializer type for variable of type {Type}", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { Type type = LHS.GetTypeInfo(); if (!RHS.CanConvertTo(type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot assign value of type {RHS.GetExprType(errorHandler)} to variable of type {type}", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { if (!Condition.CanConvertTo(PrimTypeName.BOOL, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Condition must be a boolean", Token); } Body.CheckTypes(errorHandler); ElseBody?.CheckTypes(errorHandler); }
public override void CheckTypes(ErrorHandler errorHandler) { if (typesChecked) { return; } typesChecked = true; var targetType = base.GetTypeInfo(); if (!(targetType is ArrayType)) { errorHandler.AddMessage(Severity.Error, $"{Token.Value} is not an array type", Token); } if (!Index.CanConvertTo(PrimTypeName.INT, errorHandler)) { errorHandler.AddMessage(Severity.Error, "Array indexer must be an integer", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { if (Value == null) { return; } if (!Value.CanConvertTo(TargetFn.Type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Function {TargetFn.Token.Value} must return type {TargetFn.Type}, tried to return {Value.GetExprType(errorHandler)}", Token); } }
public override void CheckTypes(ErrorHandler errorHandler) { if (DefaultValue == null) { return; } if (!DefaultValue.CanConvertTo(Type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Invalid initializer type for function parameter {Token.Value} of type {Type}", Token); } }
public override void ResolveNames(Scope scope, ErrorHandler errorHandler) { Value?.ResolveNames(scope, errorHandler); FnDecl target = scope.FindFn(); if (target == null) { errorHandler.AddMessage(Severity.Error, $"return statement is not inside a function", Token); } TargetFn = target; }
public void ResolveStructMember(Expr beforePoint, ErrorHandler errorHandler) { Type typeBeforePoint = new PrimType(PrimTypeName.BOOL); if (beforePoint is FnCall fnc) { fnc.CheckTypes(errorHandler); typeBeforePoint = fnc.TargetNode.Type; } else if (beforePoint is Var v) { typeBeforePoint = v.GetTypeInfo(); } else if (beforePoint is PointExpr pex) { return; // it should have been already resolved } if (!(typeBeforePoint is StructType type)) { errorHandler.AddMessage(Severity.Error, $"Expected struct type, got {typeBeforePoint}", Token); return; } var statement = type.TargetNode.Body.Statements.FirstOrDefault(stmt => { if (stmt is DeclStmt decl) { return(decl.Token.Value == Token.Value); } return(false); }); if (statement == null) { errorHandler.AddMessage(Severity.Error, $"Struct {type.TargetNode.Token.Value} does not contain a member called {Token.Value}", Token); } TargetNode = statement; }
public override void CheckTypes(ErrorHandler errorHandler) { LHS.CheckTypes(errorHandler); RHS.CheckTypes(errorHandler); bool canApply = true; var intType = new PrimType(PrimTypeName.INT); var floatType = new PrimType(PrimTypeName.FLOAT); var boolType = new PrimType(PrimTypeName.BOOL); var stringType = new PrimType(PrimTypeName.STRING); if (Op == BinaryOp.ADD && !CanBothConvertTo(stringType, errorHandler) && !CanBothConvertTo(intType, errorHandler) && !CanBothConvertTo(floatType, errorHandler)) { canApply = false; } if ((Op == BinaryOp.AND || Op == BinaryOp.OR) && !CanBothConvertTo(boolType, errorHandler)) { canApply = false; } if ((Op == BinaryOp.DIV || Op == BinaryOp.MUL || Op == BinaryOp.SUB) && !CanBothConvertTo(intType, errorHandler) && !CanBothConvertTo(floatType, errorHandler)) { canApply = false; } if (Op == BinaryOp.MOD && !CanBothConvertTo(intType, errorHandler)) { canApply = false; } if ((Op == BinaryOp.L || Op == BinaryOp.LE || Op == BinaryOp.G || Op == BinaryOp.GE || Op == BinaryOp.NE || Op == BinaryOp.EQ) && !CanBothConvertTo(boolType, errorHandler)) { canApply = false; } if ((Op == BinaryOp.B_AND || Op == BinaryOp.B_NOT || Op == BinaryOp.B_OR || Op == BinaryOp.B_SHL || Op == BinaryOp.B_SHR || Op == BinaryOp.B_XOR) && !CanBothConvertTo(intType, errorHandler)) { canApply = false; } if (!canApply) { errorHandler.AddMessage(Severity.Error, $"Cannot apply operator {OpName(Op)} to operands of types {LHS.GetExprType(errorHandler)} ans {RHS.GetExprType(errorHandler)}", OpToken); } }
public override void ResolveNames(Scope scope, ErrorHandler errorHandler) { var curScope = scope; while (curScope != null) { if (curScope.Owner is WhileLoop wloop) { TargetNode = wloop; return; } if (curScope.Owner is ForLoop floop) { TargetNode = floop; return; } curScope = curScope.Parent; } errorHandler.AddMessage(Severity.Error, "Break statement not in loop body", Token); }
public override bool CanConvertTo(Type type, ErrorHandler errorHandler) { if (!(type is StructType)) { return(false); } var target = ((StructType)type).TargetNode; var required = new Dictionary <string, DeclStmt>(); var requiredFilled = new Dictionary <string, bool>(); var optional = new List <DeclAssignStmt>(); foreach (var stmt in target.Body.Statements) { if (stmt is DeclAssignStmt das) { optional.Add(das); } else if (stmt is DeclStmt ds) { required.Add(ds.Token.Value, ds); requiredFilled.Add(ds.Token.Value, false); } } bool success = true; var pastIdentifiers = new List <string>(); foreach (var stmt in Statements) { if (pastIdentifiers.Contains(stmt.Token.Value)) { errorHandler.AddMessage(Severity.Error, $"Duplicate struct member {stmt.Token.Value}", Token); success = false; } pastIdentifiers.Add(stmt.Token.Value); var optionalStmt = optional.FirstOrDefault(opt => opt.Token.Value == stmt.Token.Value); if (optionalStmt != null) { if (!stmt.Data.CanConvertTo(optionalStmt.Type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use type {GetExprType(errorHandler)} for member {optionalStmt.Token.Value} of type {optionalStmt.Type}", Token); success = false; } continue; } if (required.ContainsKey(stmt.Token.Value)) { requiredFilled[stmt.Token.Value] = true; if (!stmt.Data.CanConvertTo(required[stmt.Token.Value].Type, errorHandler)) { errorHandler.AddMessage(Severity.Error, $"Cannot use type {GetExprType(errorHandler)} for member {required[stmt.Token.Value].Token.Value} of type {required[stmt.Token.Value].Type}", Token); success = false; } continue; } errorHandler.AddMessage(Severity.Error, $"Unknown member {stmt.Token.Value} for struct {target.Token.Value}", Token); success = false; } foreach (var filled in requiredFilled) { if (!filled.Value) { errorHandler.AddMessage(Severity.Error, $"Missing required member {filled.Key} for struct {target.Token.Value}", Token); success = false; } } return(success); }